flat assembler
Message board for the users of flat assembler.

Index > Main > [bug] corupted stack using double within cinvoke

Author
Thread Post new topic Reply to topic
Roman



Joined: 21 Apr 2012
Posts: 1847
Roman 04 Aug 2022, 12:51
In MSVCRT.DLL sprintf
In fasmw 1.73 i write simple code.
Code:
resultq  dq 0
resultq2 dq 0
resultq3 dq 0
resultq4 dq 0
             finit
             mov   esi,3DMatrix
             mov   ebx,Status
   .mtt:     fld   dword [esi]
             fstp  [resultq]
             fld   dword [esi+4]
             fstp  [resultq2]
             fld   dword [esi+8]
             fstp  [resultq3]
             fld   dword [esi+12]
             fstp  [resultq4]

             ;push  edx
             cinvoke sprintf,ebx,'[%f ,%f ,%f ,%f]',double [resultq],double [resultq2],double [resultq3],double [resultq4]
             ;do add     esp, 18h this corupted esp and pop edx= 0  !
             ;pop   edx
             add   ebx,eax
             mov   word [ebx],0x0a0d
             add   ebx,2
             add   esi,16
             cmp   esi,3DMatrix+16*4
             jb    .mtt
    


Last edited by Roman on 17 Aug 2022, 08:53; edited 3 times in total
Post 04 Aug 2022, 12:51
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20451
Location: In your JS exploiting you and your system
revolution 04 Aug 2022, 12:53
Each double is 8 bytes.

But i suspect your macro for cinvoke is already doing the stack adjustment for you. You haven't shown your macro implementation for that so we can only guess what it does.


Last edited by revolution on 04 Aug 2022, 20:59; edited 1 time in total
Post 04 Aug 2022, 12:53
View user's profile Send private message Visit poster's website Reply with quote
Roman



Joined: 21 Apr 2012
Posts: 1847
Roman 04 Aug 2022, 12:55
add esp, 18h show IDA PRO
Post 04 Aug 2022, 12:55
View user's profile Send private message Reply with quote
Roman



Joined: 21 Apr 2012
Posts: 1847
Roman 04 Aug 2022, 12:59
I using include 'c:\fasmw17316\include\Win32a.inc'
Code:
;from fasmw17316\INCLUDE\MACRO\proc32.inc

macro cinvoke proc,[arg]                ; indirectly call CDECL procedure
 { common
    size@ccall = 0
    if ~ arg eq
   reverse
    pushd arg
    size@ccall = size@ccall+4
   common
    end if
    call [proc]
    if size@ccall
    add esp,size@ccall
    end if }

    
Post 04 Aug 2022, 12:59
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20451
Location: In your JS exploiting you and your system
revolution 04 Aug 2022, 13:05
size@ccall should be the size of the pushed arguments, not simply the count * 4.
Post 04 Aug 2022, 13:05
View user's profile Send private message Visit poster's website Reply with quote
ProMiNick



Joined: 24 Mar 2012
Posts: 804
Location: Russian Federation, Sochi
ProMiNick 04 Aug 2022, 14:17
use
Code:
invoke sprintf,ebx,'[%f ,%f ,%f ,%f]',double [resultq],double [resultq2],double [resultq3],double [resultq4]
add esp,4*2+8*4;$28 not $18    

instead of
Code:
cinvoke sprintf,ebx,'[%f ,%f ,%f ,%f]',double [resultq],double [resultq2],double [resultq3],double [resultq4]    


or override pushd in way it properly collect size@ccall for ccalls & not collect it for stdcall(because in stdcall size@ccall is undefined)
Post 04 Aug 2022, 14:17
View user's profile Send private message Send e-mail Reply with quote
ProMiNick



Joined: 24 Mar 2012
Posts: 804
Location: Russian Federation, Sochi
ProMiNick 04 Aug 2022, 21:53
Roman thou should shame.
That isn`t bug. It is uncorrect using of macros.
Every macro have limit of use cases.
At some moment adding more use cases bacame too painfull for preprocessor and thou stoped on that macro version that works in all general cases and not become too greedy for preprocessor.
thou could add feature in pushd macro that
if defined size@ccall
size@ccall = size@ccall+4
end if
for cases when argument is double.
or thou could avoid using cinvoke with double args using "invoke & add esp" pair.
or you could fix each time manualy
cinvoke sprintf,ebx,'[%f ,%f ,%f ,%f]',double [resultq],double [resultq2],double [resultq3],double [resultq4]
store 2*4+4*8 at $-1; imm here is 1 byte size if cinvoke calculate it incorrect - calculate it thourself
Post 04 Aug 2022, 21:53
View user's profile Send private message Send e-mail Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20451
Location: In your JS exploiting you and your system
revolution 04 Aug 2022, 22:10
ProMiNick wrote:
Roman thou should shame.
I changed the title.

It is a bug with the macros in the standard fasm download. The macros should just do the right thing. Don't burden the programmer with small "gotcha" details that can be easily fixed.
Post 04 Aug 2022, 22:10
View user's profile Send private message Visit poster's website Reply with quote
Roman



Joined: 21 Apr 2012
Posts: 1847
Roman 04 Aug 2022, 22:49
ProMiNick
I do. Simple write add esp, 16
But problem in macro, how said Revolution.
And I found esp spoiling Accidentally.
That's reason this topic.
Post 04 Aug 2022, 22:49
View user's profile Send private message Reply with quote
Roman



Joined: 21 Apr 2012
Posts: 1847
Roman 16 Aug 2022, 06:48
What about 64 bits ?
cinvoke sprintf,ebx,'[%f ,%f ,%f ,%f]',double [resultq],double [resultq2],double [resultq3],double [resultq4]

First params going in RCX\RDX\R8\R9
Where is going double [resultq3],double [resultq4] ?
In [RSP+32] and [RSP+40] ?
Post 16 Aug 2022, 06:48
View user's profile Send private message Reply with quote
ProMiNick



Joined: 24 Mar 2012
Posts: 804
Location: Russian Federation, Sochi
ProMiNick 14 Sep 2022, 14:11
\INCLUDE\MACRO\ESPTRACE.INC
Code:
; assumption: module is not expected to be used with 64 bit mode

macro x86 [symbol] { x86.#symbol equ symbol } ; symlink
x86 sub,add,push,pushw,pushd,pushf,pushfw,pushfd,pusha,pushaw,pushad,pop,popw,popd,popf,popfw,popfd,popa,popaw,popad

local@trackbase = 0 ; internal stacktrace variable

stack@trace equ local@trackbase = local@trackbase +
push@ equ
sub@ equ
pop@ equ (-1)*
add@ equ (-1)*

x86.f = 1
x86.w = 2
x86.d = 4
x86.a = 8
x86.mode = 32

macro getmode {
        virtual at 0
                push ax
                x86.mode = $*16
        end virtual }

;programmer responsible for correct x86.mode or use only in 32 bit mode by default
macro stacktrace pushtype,amount:1,instr& {
        local .tmp,tmp
        .tmp: instr
        load tmp byte from .tmp
        if tmp = $66
                stack@trace pushtype(amount*64/x86.mode)
        else
                stack@trace pushtype(amount*x86.mode/8)
        end if }

irp pushpop,push,pop {
        macro pushpop statement& \{
                match first rest,statement: \\{
                        if eax eqtype first
                                irps sym,statement \\\{ stacktrace pushpop#@,,x86.#pushpop sym \\\}
                        else
                                stacktrace pushpop#@,,x86.#pushpop statement
                        end if
                \\} \}
        irp suffix,f,a \{
                irp sizemod,w,d \\{
                        macro pushpop\#suffix\\#sizemod \\\{
                                x86.#pushpop\#suffix\\#sizemod
                                stack@trace pushpop#@(x86.\#suffix*x86.\\#sizemod) \\\} \\}
                macro pushpop\#suffix \\{ stacktrace pushpop#@,x86.\#suffix,x86.#pushpop\#suffix \\} \}
        irp sizemod,w,d \{
                macro pushpop\#sizemod value& \\{
                x86.#pushpop\#sizemod value
                stack@trace pushpop#@(x86.\#sizemod) \\} \} }

irp subadd,sub,add {
        macro subadd arg1, arg2 \{
                x86.#subadd arg1, arg2
                match =esp,arg1 \\{
                        if (0 eqtype arg2) | ($ eqtype arg2)
                                stack@trace subadd#@(arg2)
                        end if \\} \} }    

\INCLUDE\MACRO\PUSHD.INC
Code:
sizeof.byte     = 1
sizeof.word     = 2
sizeof.dword    = 4
sizeof.fword    = 6
sizeof.pword    = 6
sizeof.qword    = 8
sizeof.tword    = 12
sizeof.tbyte    = 12
sizeof.xword    = 16
sizeof.dqword   = 16
sizeof.yword    = 32
sizeof.qqword   = 32
sizeof.zword    = 64
sizeof.dqqword  = 64

macro pushd value& {
        match =addr var, value \{
                if +var relative to 0 | +var relative to $
                        pushd   var
                else
                        lea     edx, [var]
                        pushd   edx
                end if
                pushx equ \}
        match =pushx type [var], pushx value \{
                repeat (sizeof.\#type+3) shr 2
                        pushd   [var+4*(((sizeof.\#type+3) shr 2)-%)
                end repeat
                pushx equ \}
        match =pushx [var], pushx value \{
                pushd   value
                pushx equ \}
        match =pushx type num, pushx value \{
                if value eqtype byte 0 | value eqtype byte 0:0 | value eqtype byte 0f
                        virtual at 0
                                if type in <byte,word,dword>
                                        dd num
                                else if type in <fword,pword>
                                        dp num
                                else if type eq qword
                                        dq num
                                else if type in <tbyte,tword>
                                        dt num
                                else
                                        error value
                                end if
                                dq 0
                                load ..low dword from 0
                                load ..mid dword from 4
                                load ..high dword from 8
                        end virtual
                        if type in <tbyte,tword>
                                pushd   ..high
                        end if
                        if ~type in <byte,word,dword>
                                pushd   ..mid
                        end if
                        pushd   ..low
                else
                        pushd   value
                end if
                pushx equ \}
        match =pushx , pushx \{
                pushd   value
                pushx equ \}
        restore pushx }    

\INCLUDE\MACRO\CALL32.INC
Code:
macro RTLorder [args] {
 common if ~ arg eq
 reverse pushd args
 common end if }

macro LTRorder [args] {
 common if ~ arg eq
 forward pushd args
 common end if }

CCcleanup equ callee

macro cleanup@stack amount {
        if amount
                match =callee, CCcleanup \{ virtual \}
                add     esp, amount
                match =callee, CCcleanup \{ end virtual \}
        end if }

macro stdcall proc,[arg]                                                ; directly call STDCALL procedure
 { common local tmp
        tmp = local@trackbase ; required ESPTRACE.INC
        RTLorder arg
        call proc
        cleanup@stack local@trackbase-tmp}

macro ccall proc,[arg]                                                  ; directly call CDECL procedure
 { common
        CCcleanup equ caller
        stdcall proc,arg
        restore CCcleanup }

macro invoke proc,[arg] { common stdcall [proc],arg }                   ; indirectly call STDCALL procedure
macro cinvoke proc,[arg] { common ccall [proc],arg }                    ; indirectly call CDECL procedure

macro fastcall proc,toECX:ecx,toEDX:edx,[arg]                           ; directly call FASTCALL procedure
 { common
    RTLorder arg
    if ~edx eq toEDX
    mov edx,toEDX
    end if
    if ~ecx eq toECX
    mov ecx,toECX
    end if
    call proc }

macro regcall proc,toEAX:eax,toEDX:edx,toECX:ecx,[arg]                  ; directly call DELPHI procedure
 { common
    LTRorder arg
    if ~ecx eq toECX
    mov ecx,toECX
    end if
    if ~edx eq toEDX
    mov edx,toEDX
    end if
    if ~eax eq toEAX
    mov eax,toEAX
    end if
    call proc }

macro thiscall proc,toECX:ecx,[arg]                                     ; directly call THISCALL procedure
 { common
    RTLorder arg
    if ~ecx eq toECX
    mov ecx,toECX
    end if
    call proc }

macro watcomcall proc,toEAX:eax,toEDX:edx,toEBX:ebx,toECX:ecx,[arg]     ; directly call WATCOM procedure
 { common
    RTLorder arg
    if ~ecx eq toECX
    mov ecx,toECX
    end if
    if ~ebx eq toEBX
    mov ebx,toEBX
    end if
    if ~edx eq toEDX
    mov edx,toEDX
    end if
    if ~eax eq toEAX
    mov eax,toEAX
    end if
    call proc }     
i.e. part of proc32.inc, calling convention list was extended to be more friendly for making patches in fasm for binaries made in various HLLs

win32a.inc
Code:
; Win32 programming headers (ASCII)

include 'macro/struct.inc'
include 'macro/esptrace.inc' ; every stack move affect semiinternal local@trackbase variable
include 'macro/pushd.inc' ; overriding pushd for complex vaues
include 'macro/proc32.inc'
include 'macro/call32.inc' ; override ones defined in proc32.inc, or remove them from proc32.inc
include 'macro/com32.inc'
include 'macro/import32.inc'
include 'macro/export.inc'
include 'macro/resource.inc'

struc TCHAR [val] { common match any, val \{ . db val \}
                           match , val \{ . db ? \} }
sizeof.TCHAR = 1

include 'equates/kernel32.inc'
include 'equates/user32.inc'
include 'equates/gdi32.inc'
include 'equates/comctl32.inc'
include 'equates/comdlg32.inc'
include 'equates/shell32.inc'
include 'equates/wsock32.inc'

macro api [name] { if used name
                    label name dword at name#A
                   end if }    

lastly double equ qword - and that will fix stack for double in ccall, cinvoke for x32 (i canceled from use of word "double", just word "qword" instead)
(call32.inc requires esptrace.inc but to way independant from|to pushd.inc which only overrides pushd)
Post 14 Sep 2022, 14:11
View user's profile Send private message Send e-mail Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2025, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.