flat assembler
Message board for the users of flat assembler.

Index > Windows > frameless(no ebp) stack for stdcall

Author
Thread Post new topic Reply to topic
ProMiNick



Joined: 24 Mar 2012
Posts: 805
Location: Russian Federation, Sochi
ProMiNick 24 Sep 2018, 09:49
proc args has no structuring. they has only order - so for all of them one general macro can be used (who cares how arg named - naming args could be manually if needed)
Code:
macro stackidxfromzero bool:1
{ if ~bool
    stackarg equ esp+4* ; use case: stackarg (number of arg)
  else
    stackarg equ esp+4+4*   ; use case: stackarg (number of arg)
  end if
  _push equ 4             ; use case: _push*count_of_pushes
  _pop equ (-4)           ; use case: _pop*count_of_popes
  _subesp equ 1*          ; use case: _subesp (same value that passed to "sub esp" instruction)
  _addesp equ (-1)*       ; use case: _addesp (same value that passed to "add esp" instruction)
  _beforecall equ (-4)
  _beforesettingparameters equ (-4)*  ; use case: _beforesettingparameters (count of parameters)
  _setparameters equ sub esp, 4*  ; use case: _settingparameters (count of parameters)
  _removeparameters equ add esp, 4* ; use case: _removeparameters (count of parameters)
}    


syntax of use:
Code:
        stackidxfromzero 
        mov     ebx,[stackarg(0)]
        add     esp,-$0C
        mov     edx,[stackarg(1)+_addesp(-$0C)]
        push   eax
        push   eax
        push   eax
        mov     edi,[stackarg(2)+_addesp(-$0C)+_push*3]
        cmp     edi,[stackarg(2)+24]
     

looks very readable - programmer is free to declare stack address as any combination of direct numeric shifts or any kind of sybolic representation of them
(In the way of cancelling from macro proc - I don`t see any needance in ebp at all).

locals have specific structuring for different procs but representation of numeric shifts that corresponds to stack operatrions applicable to locals too.

_________________
I don`t like to refer by "you" to one person.
My soul requires acronim "thou" instead.


Last edited by ProMiNick on 27 Sep 2018, 12:31; edited 1 time in total
Post 24 Sep 2018, 09:49
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: 20458
Location: In your JS exploiting you and your system
revolution 24 Sep 2018, 09:58
Yeah, there have been a few implementations of ESP referencing macros for proc and etc.

But they get tricky when the programmer uses push or pop. It might be prudent to not use push or pop and remove the _addesp and _push syntax. That could help avoid lots of errors when editing code.

I like to keep the pushes and pops inside macros only and never use them raw within procedures. Then the programmer is free to change the proc macro to use EBP or ESP as desired without having to change the code enclosed by the macros.
Post 24 Sep 2018, 09:58
View user's profile Send private message Visit poster's website Reply with quote
ProMiNick



Joined: 24 Mar 2012
Posts: 805
Location: Russian Federation, Sochi
ProMiNick 24 Sep 2018, 15:16
tryed on smthing big
Code:
format binary as 'dll'
USE32
macro stackidxfromzero bool:1
{ if ~bool
    stackarg equ esp+4* ; use case: stackarg (number of arg)
  else
    stackarg equ esp+4+4*   ; use case: stackarg (number of arg)
  end if
  _push equ 4             ; use case: _push*count_of_pushes
  _pop equ (-4)           ; use case: _pop*count_of_popes
  _subesp equ 1*          ; use case: _subesp (same value that passed to "sub esp" instruction)
  _addesp equ (-1)*       ; use case: _addesp (same value that passed to "add esp" instruction)
  _beforecall equ (-4)
  _beforesettingparameters equ (-4)*  ; use case: _beforesettingparameters (count of parameters)
  _setparameters equ sub esp, 4*  ; use case: _settingparameters (count of parameters)
  _removeparameters equ add esp, 4* ; use case: _removeparameters (count of parameters)
}
        stackidxfromzero

        NULL equ 0
        TRUE equ 1
        FALSE equ 0
        DLL_PROCESS_ATTACH = 1

        label   DllMain at $5C281E0E
        label   AtlModuleGetClassObject at $5C281040
        label   AtlModuleRegisterServer at $5C28104C
        label   AtlModuleUnregisterServerEx at $5C281050
        label   CRT_INIT at $5C283C91
        label   p_ATL_Module at $5C285260
        label   skip_DLL_PROCESS_DETACH at $5C28561C
        label   rawDllMain at $5C28568C
        accept.rawDllMain equ TRUE;FALSE;
        accept.threadcalls equ TRUE;FALSE;

file 'slayerxp.dll':0,$1282 ;5C281D30 at 1130

org $5C281E82
DllGetClassObject:
        db $8B,$FF ; mov     edi, edi
        pop     eax
        push    p_ATL_Module
        push    eax
        jmp     dword [AtlModuleGetClassObject]
        db 19 dup $CC
DllRegisterServer:
        pop     eax
        push    NULL
        push    TRUE
        push    p_ATL_Module
        push    eax
        jmp     dword [AtlModuleRegisterServer] ; jmpimp AtlModuleRegisterServer _ATL_Module *p_ATL_Module, BOOL bUnRegTypeLib, const CLSID* pCLSID
        db 4 dup $CC
DllUnregisterServer:
        pop     eax
        push    NULL
        push    TRUE
        push    p_ATL_Module
        push    eax
        jmp     dword [AtlModuleUnregisterServerEx] ; jmpimp AtlModuleUnregisterServerEx _ATL_Module *p_ATL_Module, BOOL bUnRegTypeLib, const CLSID* pCLSID
        db 4 dup $CC
file 'slayerxp.dll':$12CE,$3146-$12CE

org $5C283D46
DllMainCRTStartup:
        .hinstDLL equ stackarg(0);HINSTANCE
        .fdwReason equ stackarg(1);DWORD
        .lpReserved equ stackarg(2);LPVOID
        db $8B,$FF ; mov     edi, edi
        push    ebx
        push    esi
        push    edi
        mov     ebx, [.hinstDLL+3*_push]
        mov     esi, [.fdwReason+3*_push]
        mov     edi, [.lpReserved+3*_push]
        push    edi
        push    esi
        push    ebx
        if accept.rawDllMain
          mov     edi,[rawDllMain]
        end if
        neg     esi
        test    esi,2 ;flags for ...000-ZPcos; ...111-zpcoS; ....110-zPcoS; ...101-ZpcoS
        jnz     .attachOnly
        if accept.threadcalls
          jnp     .common
        end if
        mov     eax, [skip_DLL_PROCESS_DETACH]
        test    eax,eax
        jnz     .common
        _removeparameters(3);add     esp,12
        jmp     .exit

.attachOnly:
        if accept.rawDllMain
          test    edi,edi
          jz      .rawskip1
          call    edi
          test    eax,eax
          jz      .exit
          _setparameters(3);sub     esp,12;

.rawskip1:
        end if
        call    CRT_INIT
        test    eax,eax
        jz      .exit
        _setparameters(3);sub     esp,12;

.common:
        call    DllMain
        mov     ebx,eax
        test    esi,2
        jz      .dettachOnly
        if accept.threadcalls
          jp      .exit
        end if
        test    eax,eax
        jnz     .exit
        mov     [stackarg(1)+_beforesettingparameters(3)+_beforecall],eax ; pushing params just like in linux calling style

.dettachOnly:
        _setparameters(3);sub     esp,12  ;
        call    CRT_INIT
        and     eax,ebx
        if accept.rawDllMain
          jz      .exit
          test    esi,2
          jnz     .exit
          test    edi,edi
          jnz     .exit
          _setparameters(3);sub     esp,12;
          call    edi
        end if

.exit:
        pop     edi
        pop     esi
        pop     ebx
        ret     $0C
        db $5C283DEC-$ dup $cc
file 'slayerxp.dll':$31EC,$6400-$31EC

virtual at 0
_alloca_probe.countofparameters =0

__alloca_probe:
        push    ecx
        lea     ecx, [esp+4*_alloca_probe.countofparameters+_push]
        jmp     .probesetup

.probepages:
        sub     ecx, 1000h
        sub     eax, 1000h
        test    [ecx], eax              ; generate 1st pagefault - hidden
.probesetup:
        cmp     eax, 1000h
        jnb     .probepages
.lastpage:
        sub     ecx, eax
        mov     eax, esp
        test    [ecx], eax               ; generate 1st pagefault - hidden
        mov     esp, ecx                 ; page prepared for esp - no fault
        mov     ecx, [eax]
        jmp     dword [eax+_push]
end virtual                                         

result looked as expected in IDA Pro.
Of cource relocs unfixed... example not targeted on it.
for patching macro stackidxfromzero looks nice. I modernized it by adding in 1st post _beforecall,_beforesettingparameters to well operate on linuxcalls, and I added for fullness _setparameters, _removeparameters.
Post 24 Sep 2018, 15:16
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.