flat assembler
Message board for the users of flat assembler.

flat assembler > High Level Languages > shellex x86 & x64: what HLL (VC++6,7) hides over the sources

Author
Thread Post new topic Reply to topic
ProMiNick



Joined: 24 Mar 2012
Posts: 206
Location: Russian Federation, Sochi
Usualy HLL wraps our usefull source code in HLL stuff, that growing from version to version.
This topic will always contain 6 posts:_DllMainCRTStartup and its callee tree, DllCanUnloadNow, DllGetClassObject, DllRegisterServer, DllUnregisterServer with theirs subcalls tree. For 6th post left definition of used structures.
You can see how same tasks realized in x86 & x64.

Note 1:Explored binaries has specific: projects in VC++6.0 both x86 & x64 are with disabled thread library calls, project in VC++7.0 only for x86 and thread library calls enabled in it.
Note 2:attached asm sources not identical to that VC++ creates, but they has exactly functionality.
Note 3: my first 6 posts will contain inaccuracyes and assumptions however they will be continously edited.

_DllMainCRTStartup - it is included in every VC++ DLL with invariable realization (invariable no matter VC++ version, invariable no matter payload code specific (such as disablingThreadLibraryCalls, or realization DLL as simple DLL, or as COM server), completely invariable)

BOOL __stdcall _DllMainCRTStartup(HANDLE hinstDLL, DWORD fdwReason, VOID *lpReserved)
x86 VC++6.0, 7.0:
Code:
DllEntryPoint:
        .hinstDLL   = _stackarg(0) ; where "_stackarg equ esp+ptrsize+ptrsize*" and ptrsize for x86 equal to 4 
        .fdwReason  = _stackarg(1)
        .lpReserved = _stackarg(2)
        mov     edi, edi ; x86 function start signature
        push    ebx
        push    esi
        push    edi
        mov     ebx, [.hinstDLL+3*_push] ; where "_push equ ptrsize" and ptrsize for x86 equal to 4
        mov     esi, [.fdwReason+3*_push]
        mov     edi, [.lpReserved+3*_push]
        push    edi
        push    esi
        push    ebx
        mov     edi, [rawDllMain]
        neg     esi ; with negating it is simple to separate attaches & detaches, process & thread in 1 test operation
        test    esi, 2
        jnz     .attachOnly
        jnp     .common
        mov     eax, [skip_DLL_PROCESS_DETACH]
        test    eax, eax
        jnz     .common
        add     esp, 12
        jmp     .exit

.attachOnly:
        test    edi, edi
        jz      .rawskip1
        call    edi
        test    eax, eax
        jz      .exit
        sub     esp, 12

.rawskip1:
        call    _CRT_INIT
        test    eax, eax
        jz      .exit
        sub     esp, 12

.common:
        call    DllMain
        mov     ebx, eax
        test    esi, 2
        jz      .dettachOnly
        jp      .exit
        test    eax, eax
        jz      .exit
        mov     [_stackarg(1) +_beforesettingparameters(3) +_beforecall], eax ; where "_beforesettingparameters equ (-ptrsize)*", "_beforecall equ -ptrsize" and ptrsize for x86 equal to 4

.dettachOnly:
        sub     esp, 12
        call    _CRT_INIT
        and     eax, ebx
        jz      .exit
        test    esi, 2
        jnz     .exit
        test    edi, edi
        jz      .exit
        sub     esp, 12
        call    edi

.exit:
        pop     edi
        pop     esi
        pop     ebx
        ret     $0C    

in every x64 fastcall proc we have a room for storing 5 registers
4 of them can be stored in stackshadow that caller create according to calling convention
and 1 register stored as callee stack alignment

BOOL __fastcall _DllMainCRTStartup(HANDLE hinstDLL, DWORD fdwReason, VOID *lpReserved)
x64 VC++6.0:
Code:
DllEntryPoint:
        add     rsp, $28 ;return stack to state before placing stack shadow (that always 4*8=$20 bytes size) and placing 8 byte retaddres
        push    rbx ;use shadow for storing register
        push    rbp ;use shadow for storing register
        push    rsi ;use shadow for storing register
        push    r10 ;use shadow for storing register
        sub     rsp, 8 ;skip retaddr
        push    rdi ;use alignment of stack for storing register, instead of useless analogue "and rsp,not $F"
        sub     rsp, $20 ;make minimal room 4*8 for first 4 param shadow in stack for subcalls
        mov     rbx, rdx
        mov     rbp, rcx
        mov     rsi, r8
        mov     r10, [rawDllMain]
        push    rbp
        neg     rbp
        test    rbp, 2
        pop     rbp
        jnz     .attachOnly
        jnp     .common
        mov     rax, [skip_DLL_PROCESS_DETACH]
        test    rax, rax
        jnz     .common
        jmp     .exit

.attachOnly:
        test    r10, r10
        jz      .rawskip1
        call    r10
        test    eax, eax
        jz      .exit
        mov     rdx, rbx
        mov     rcx, rbp
        mov     r8, rsi

.rawskip1:
        call    _CRT_INIT
        test    eax, eax
        jz      .exit
        mov     rdx, rbx
        mov     rcx, rbp
        mov     r8, rsi

.common:
        call    DllMain
        mov     edi, eax
        push    rbp
        neg     rbp
        test    rbp, 2
        pop     rbp
        jz      .dettachOnly
        jp      .exit
        test    eax, eax
        jz      .exit
        mov     ebp, eax

.dettachOnly:
        mov     rdx, rbx
        mov     rcx, rbp
        mov     r8, rsi
        call    _CRT_INIT
        and     eax, edi
        jz      .exit
        push    rbp
        neg     rbp
        test    rbp, 2
        pop     rbp
        jnz     .exit
        test    r10, r10
        jz      .exit
        mov     rdx, rbx
        mov     rcx, rbp
        mov     r8, rsi
        call    r10

.exit:
        add     rsp, $20
        pop     rdi
        add     rsp, 8
        pop     r10
        pop     rsi
        pop     rbp
        pop     rbx
        sub     rsp, $28
        ret    


subcall _CRT_INIT of _DllMainCRTStartup
BOOL __stdcall _CRT_INIT(HANDLE hinstDLL, DWORD fdwReason, VOID *lpReserved)
x86 VC++6.0:
Code:
_CRT_INIT:
        .hinstDLL   = _stackarg(0) ; where "_stackarg equ esp+ptrsize+ptrsize*" and ptrsize for x86 equal to 4 
        .fdwReason  = _stackarg(1)
        .lpReserved = _stackarg(2)
        mov     edi, edi ; x86 function start signature
        cmp     [.fdwReason], 1
        jb      .ProcDetach
        ja      .ThreadCases

.ProcAttach:
        mov     ecx, 32*sizeof.ptr
        call    _malloc_crt
        mov     [___onexitbegin], eax
        mov     [___onexitend], eax
        test    eax, eax
        jz      .exit
        mov     [eax], 0
        ;ccall  msvcrt.dll.__initterm (___xc_a,___xc_z)
        ;description: call list of functions from ___xc_a to ___xc_z
        ;body: list has only one item
        call    ___security_init_cookie
        ;end body
        inc     [crt_init_done]
        jmp     .retTrue

.ProcDetach:
        sub     [crt_init_done],1
        js      .retFalse
        mov     eax, [___onexitbegin]
        test    eax, eax
        jz      .retTrue

.loop___onexit:
        sub     [___onexitend], sizeof.ptr
        mov     ecx, [___onexitend]
        cmp     ecx, eax
        jb      .Free
        mov     eax, [ecx]
        test    eax, eax
        jz      .loop___onexit
        call    eax
        mov     eax, [___onexitbegin]
        jmp     .loop___onexit

.Free:
        push    eax
        call    msvcrt.dll.__free
        pop     ecx              
        mov     [___onexitbegin], 0

.ThreadCases:
.retTrue:
        xor     eax, eax
        inc     eax
        jmp     .exit

.retFalse:
        xor     eax, eax

.exit:
        ret     $0C    

BOOL __fastcall _CRT_INIT(HANDLE hinstDLL, DWORD fdwReason, VOID *lpReserved)
x64 VC++6.0:
Code:
_CRT_INIT:
        sub     rsp, $28
        cmp     rdx, 1
        jb      .ProcDetach
        ja      .ThreadCases

.ProcAttach:
        mov     ecx, 32*sizeof.ptr
        call    _malloc_crt
        mov     [___onexitbegin], rax
        mov     [___onexitend], rax
        test    rax, rax
        jz      .exit
        mov     [rax], 0
        ;fastcall  msvcrt.dll.__initterm (___xc_a,___xc_z)
        ;description: call list of functions from ___xc_a to ___xc_z
        ;body: list has only one item
        call    ___security_init_cookie
        ;end body
        inc     [crt_init_done]
        jmp     .retTrue

.ProcDetach:
        sub     [crt_init_done],1
        js      .retFalse
        mov     rax, [___onexitbegin]
        test    rax, rax
        jz      .retTrue

.loop___onexit:
        sub     [___onexitend], sizeof.ptr
        mov     rcx, [___onexitend]
        cmp     rcx, rax
        jb      .Free
        mov     rax, [rcx]
        test    rax, rax
        jz      .loop___onexit
        call    rax
        mov     rax, [___onexitbegin]
        jmp     .loop___onexit

.Free:
        mov     rcx, rax
        call    msvcrt.dll.__free
        mov     [___onexitbegin], 0

.ThreadCases:
.retTrue:
        xor     eax, eax
        inc     eax
        jmp     .exit

.retFalse:
        xor     eax, eax
.exit:
        add     rsp, $28
        ret    


As we can see _CRT_INIT for variant with disabled thread library calls makes only one usefull action - calls ___security_init_cookie.
Of cource it initialize table of up to 32 procedure entries, that called one by one on _CRT_INIT(...,dllProcessDetach,...), after all such calls made - that table freed. But this table initialy free and looks like it never filled anywhere in code.

BOOL __stdcall _CRT_INIT(HANDLE hinstDLL, DWORD fdwReason, VOID *lpReserved)
x86 VC++7.0:
Code:
_CRT_INIT:
        .hinstDLL   = _stackarg(0) ; where "_stackarg equ esp+ptrsize+ptrsize*" and ptrsize for x86 equal to 4 
        .fdwReason  = _stackarg(1)
        .lpReserved = _stackarg(2)
        mov     edi, edi ; x86 function start signature
        cmp     [.fdwReason], 1
        jb      .ProcDetach
        ja      .ThreadCases

.ProcAttach:
        push    OSverINFOa ;in original OSverINFOa located in stack, and its border tested with alloca_probe
        call    [GetVersionExA] ; require win2000+
        test    eax, eax
        jz      .retFalse
        mov     eax,[OSverINFOa.dwPlatformId]
        cmp     eax,VER_PLATFORM_WIN32_NT
        jz      .skip_BuildNumber_patch_for_nonNT
        or      [OSverINFOa.dwBuildNumber], $8000
.skip_BuildNumber_patch_for_nonNT:
        push    TRUE            ; bSERIALIZE
        call    __heap_init
        pop     ecx
        test    eax, eax
        jz      .exit
        call    multythreading_init
        test    eax, eax
        jz     .heap_terminate

.multythreading_inited:
        call    sub_10008198
        call    [GetCommandLineA]
        call    ___crtGetEnvironmentStringsA
        mov     [lpEnvStringsA], eax
        call    __ioinit
        test    eax, eax
        jl      .multythreading_terminate
        call    sub_10007FD4
        test    eax, eax
        jl      .io_terminate
        call     __setenvp
        test    eax, eax
        jl      .io_terminate
        call    sub_100078CE
        test    eax, eax
        jnz     .io_terminate
        inc     [crt_init_done]
        jmp     .retTrue

.io_terminate:
        call    __ioterm

.multythreading_terminate:
        call    __mtterm

.heap_terminate:
        call    __heap_term
        jmp     .retFalse

.ProcDetach:
        sub     [crt_init_done],1
        js      .retFalse
        cmp     [skip__cexit],0
        jnz     .after__cexit
        call    __cexit
.after__cexit:
        call    __ioterm
        call    __mtterm
        call    __heap_term
        jmp     .retTrue

.ThreadCases:
        test    [.fdwReason], 1
        jnz     .ThreadDetach
.ThreadAttach:
        ccall   sub_10007A9C, 1, $88
        test    eax, eax
        jz      .exit
        push    eax
        push    [dwTlsIndex]
        call    [TlsSetValue]
        sub     esp,4 ; place 1st param same as in previous
        test    eax, eax
        jz      .Free
        call    __initptd
        ;pop     ecx - make it later
        call    [GetCurrentThreadId]
        pop     ecx
        or      [ecx+4],-1
        mov     [ecx+0],eax
        jmp     .retTrue

.Free:
        call    msvcrt.dll.__free
        pop     ecx

.retFalse:
        xor     eax, eax
        jmp     .exit

.ThreadDetach:
        push    0
        call    sub_10007657
        pop     ecx

.retTrue:
        xor     eax, eax
        inc     eax

.exit:
        ret     $0C    


subcall DllMain of _DllMainCRTStartup
BOOL __stdcall DllMain(HANDLE hinstDLL, DWORD fdwReason, VOID *lpReserved)
x86 VC++6.0:
Code:
DllMain:
        .hinstDLL   = _stackarg(0) ; where "_stackarg equ esp+ptrsize+ptrsize*" and ptrsize for x86 equal to 4 
        .fdwReason  = _stackarg(1)
        .lpReserved = _stackarg(2)
        mov     edi, edi ; x86 function start signature
        cmp     [.fdwReason], 1
        jb      .ProcDetach
        ja      .retTrue

.ProcAttach:
        push    [.hinstDLL]
        push    ATLObjMap
        mov     ecx, CLayerUIModule
        push    ecx
        ;mov     [lpCLayerUIModule], ecx ; such tasks for design time in assembly but not for real time code
        mov     [ecx+ATL_BASE_MODULE30.cbSize], sizeof.ATL_BASE_MODULE30
        mov     [ecx+ATL_BASE_MODULE30.pguidVer], GUID_ATLVer30
        mov     [ecx+ATL_BASE_MODULE30.dwAtlBuildVer], ver3.0
        call    [AtlModuleInit]
        ;test    eax, eax
        ;js      .skip_ATLModule_ver_3_1_specific
        ;LIBID_SLAYERUILib copied

;.skip_ATLModule_ver_3_1_specific:
        push    RESID_IDMANIFEST
        push    [.hinstDLL]
        call    SHFusionInitializeFromModuleID
        sub     esp,8 ; keep .hinstDLL saved in stack from trashing by calling of LinkWindow_RegisterClass
        call    LinkWindow_RegisterClass
        call    [DisableThreadLibraryCalls]
        pop     eax
        pop     eax
        jmp     .retTrue

.ProcDetach:
        call    SHFusionUninitialize
        push    CLayerUIModule
        call    [AtlModuleTerm]

.retTrue:
        xor     eax, eax
        inc     eax
        ret     $0C    

BOOL __fastcall DllMain(HANDLE hinstDLL, DWORD fdwReason, VOID *lpReserved)
x64 VC++6.0:
Code:
DllMain:
        push    rbx
        sub     rsp, $20
        mov     rbx, rcx
        cmp     rdx, 1
        jb      .ProcDetach
        ja      .retTrue

.ProcAttach:
        mov     r8, rbx
        mov     rdx, ATLObjMap
        mov     rcx, CLayerUIModule
        ;mov     [lpCLayerUIModule], rcx ; such tasks for design time in assembly but not for real time code
        mov     [rcx+ATL_BASE_MODULE31.cbSize], sizeof.ATL_BASE_MODULE31
        mov     [rcx+ATL_BASE_MODULE31.pguidVer], GUID_ATLVer30
        mov     [rcx+ATL_BASE_MODULE31.dwAtlBuildVer], ver3.1
        call    [ATLModuleInit]
        test    eax, eax
        js      .skip_ATLModule_ver_3_1_specific
        mov     [rcx+ATL_BASE_MODULE31.field3_1], 1
        ;LIBID_SLAYERUILib copied

.skip_ATLModule_ver_3_1_specific:
        mov     rdx, RESID_IDMANIFEST
        mov     rcx, rbx
        call    SHFusionInitializeFromModuleID
        call    LinkWindow_RegisterClass
        mov     rcx, rbx
        call    [DisableThreadLibraryCalls]
        jmp     .retTrue

.ProcDetach:
        call    SHFusionUninitialize
        lea     rcx, [CLayerUIModule]
        call    [AtlModuleTerm]

.retTrue:
        xor     eax, eax
        inc     eax
        add     rsp, $20
        pop     rbx
        ret     

BOOL __stdcall DllMain(HANDLE hinstDLL, DWORD fdwReason, VOID *lpReserved)
x86 VC++7.0:
Code:
DllMain:
        .hinstDLL   = _stackarg(0) ; where "_stackarg equ esp+ptrsize+ptrsize*" and ptrsize for x86 equal to 4 
        .fdwReason  = _stackarg(1)
        .lpReserved = _stackarg(2)
        mov     edi, edi ; x86 function start signature
        xor     eax, eax 
        inc     eax 
        ret     $0C    


In case of VC++7.0 all initialization happened in CRT_INIT. Nothing left to DllMain.

AtlModuleInit exported from ATL.DLL
HRESULT __stdcall AtlModuleInit(struct _ATL_MODULE_30 *ATL__CComModule, struct _ATL_OBJMAP_ENTRY *ATLObjMap, HANDLE hinstDLL)
x86 VC++6.0:
Code:
AtlModuleInit:
        .ATL__CComModule   = _stackarg(0) ; where "_stackarg equ esp+ptrsize+ptrsize*" and ptrsize for x86 equal to 4
        .ATLObjMap         = _stackarg(1)
        .hinstDLL          = _stackarg(2)
        virtual at ebp-$18
                .ms_exc     CPPEH_RECORD
        end virtual

        push    $0C
        push    offset _SCOPETABLE_AtlModuleInit
        call    _SEH_prolog
        mov     esi, [.ATL__CComModule]
        test    esi, esi
        jz      AtlModuleInit.retE_INVALIDARG
        mov     eax, [esi+_ATL_MODULE_30.cbSize]
        cmp     eax,$64
        jz      AtlModuleInit.sizeOK
        cmp     eax,$84
        jz      AtlModuleInit.sizeOK

AtlModuleInit.retE_INVALIDARG:
        mov     eax, E_INVALIDARG
        jmp     AtlModuleInit.Epilog

AtlModuleInit.sizeOK:
        mov     eax, [.ATLObjMap]
        mov     [esi+_ATL_MODULE_30.m_pObjMap], eax
        mov     eax, [.hinstDLL]
        mov     [esi+_ATL_MODULE_30.m_hInst], eax
        mov     [esi+_ATL_MODULE_30.m_hInstResource], eax
        mov     [esi+_ATL_MODULE_30.m_hInstTypeLib], eax
        xor     ebx,ebx
        mov     [esi+_ATL_MODULE_30.m_nLockCnt], ebx
        mov     [esi+_ATL_MODULE_30.m_hHeap], ebx
        mov     [.ms_exc.registration.TryLevel], ebx
        lea     eax, [esi+_ATL_MODULE_30.m_csTypeInfoHolder]
        push    eax
        call    [InitializeCriticalSection]
        or      [.ms_exc.registration.TryLevel], -1
        mov     [.ms_exc.registration.TryLevel], 1
        lea     eax, [esi+_ATL_MODULE_30.m_csWindowCreate]
        push    eax
        call    [InitializeCriticalSection]
        or      [.ms_exc.registration.TryLevel], -1
        mov     [.ms_exc.registration.TryLevel], 2
        lea     eax, [esi+_ATL_MODULE_30.m_csObjMap]
        push    eax
        call    [InitializeCriticalSection]
        or      [.ms_exc.registration.TryLevel], -1
        cmp     [esi+_ATL_MODULE_30.cbSize], $64
        je      AtlModuleInit.retHRESULT_S_OK
        mov     [esi+_ATL_MODULE_30.m_pCreateWndList], ebx
        mov     [esi+_ATL_MODULE_30.m_bDestroyHeap], 1
        mov     [esi+_ATL_MODULE_30.m_dwHeaps], ebx
        mov     [esi+_ATL_MODULE_30.m_phHeaps], ebx
        mov     [esi+_ATL_MODULE_30.m_nHeap], ebx
        mov     [esi+_ATL_MODULE_30.m_pTermFuncs], ebx
        mov     edi, [esi+_ATL_MODULE_30.m_pObjMap]
        test    edi, edi
        jz      AtlModuleInit.retHRESULT_S_OK

AtlModuleInit.ForEachObjEntry:
        mov     eax, [edi+_ATL_OBJMAP_ENTRY.pclsid]
        test    eax, eax
        jz      AtlModuleInit.Epilog
        push    TRUE
        call    [edi+_ATL_OBJMAP_ENTRY.RevokeClassObject]
        push    edi
        push    esi
        call    _NextObjectMapEntry;_NextObjectMapEntry(_ATL_MODULE_30 *,_ATL_OBJMAP_ENTRY *)
        mov     edi, eax
        jmp     AtlModuleInit.ForEachObjEntry

AtlModuleInit.retHRESULT_S_OK:
        xor     eax, eax

AtlModuleInit.Epilog:
        call    __SEH_epilog
        ret     $0C    


AtlModuleInit SEH part
Code:
_SCOPETABLE_AtlModuleInit:
        ._0.EnclosingLevel dd -1
        ._0.FilterFunc     dd AtlModuleInit.ExceptionFilter
        ._0.HandlerFunc    dd AtlModuleInit.Level0Handler
        ._1.EnclosingLevel dd -1
        ._1.FilterFunc     dd AtlModuleInit.ExceptionFilter
        ._1.HandlerFunc    dd AtlModuleInit.Level1Handler
        ._2.EnclosingLevel dd -1
        ._2.FilterFunc     dd AtlModuleInit.ExceptionFilter
        ._2.HandlerFunc    dd AtlModuleInit.Level2Handler
        dd 3 dup 0

AtlModuleInit.ExceptionFilter:
        virtual at ebp-$18
                .ms_exc     CPPEH_RECORD
        end virtual
        mov     eax, [.ms_exc.exc_ptr]
        mov     eax, [eax+_EXCEPTION_POINTERS.ExceptionRecord]
        mov     eax, [eax+EXCEPTION_RECORD.ExceptionCode]
        xor     ecx, ecx
        cmp     eax, STATUS_NO_MEMORY
        setz    cl
        mov     eax, ecx
        ret

AtlModuleInit.Level2Handler:
        virtual at ebp-$18
                .ms_exc     CPPEH_RECORD
        end virtual
        mov     esp, [.ms_exc.old_esp]
        mov     esi, [AtlModuleInit.ATL__CComModule]
        lea     eax, [esi+_ATL_MODULE_30.m_csWindowCreate]
        push    eax
        call    [DeleteCriticalSection]
        lea     eax, [esi+_ATL_MODULE_30.m_csTypeInfoHolder]
        push    eax
        call    [DeleteCriticalSection]
        inDWORDS equ /4
        mov     ecx, 3*sizeof.RTL_CRITICAL_SECTION inDWORDS;
        xor     eax, eax
        lea     edi, [esi+_ATL_MODULE_30.m_csTypeInfoHolder]
        rep     stosd
        or      [.ms_exc.registration.TryLevel], -1
        mov     eax, STATUS_NO_MEMORY
        jmp     AtlModuleInit.Epilog

AtlModuleInit.Level1Handler:
        virtual at ebp-$18
                .ms_exc     CPPEH_RECORD
        end virtual
        mov     esp, [.ms_exc.old_esp]
        mov     esi, [AtlModuleInit.ATL__CComModule]
        lea     eax, [esi+_ATL_MODULE_30.m_csTypeInfoHolder]
        push    eax
        call    [DeleteCriticalSection]
        inDWORDS equ /4
        mov     ecx, 2*sizeof.RTL_CRITICAL_SECTION inDWORDS;
        xor     eax, eax
        lea     edi, [esi+_ATL_MODULE_30.m_csTypeInfoHolder]
        rep     stosd
        or      [.ms_exc.registration.TryLevel], -1
        mov     eax, STATUS_NO_MEMORY
        jmp     AtlModuleInit.Epilog

AtlModuleInit.Level0Handler:
        virtual at ebp-$18
                .ms_exc     CPPEH_RECORD
        end virtual
        mov     esp, [.ms_exc.old_esp]
        mov     esi, [AtlModuleInit.ATL__CComModule]
        inDWORDS equ /4
        mov     ecx, 1*sizeof.RTL_CRITICAL_SECTION inDWORDS;
        xor     eax, eax
        lea     edi, [esi+_ATL_MODULE_30.m_csTypeInfoHolder]
        rep     stosd
        or      [.ms_exc.registration.TryLevel], -1
        mov     eax, STATUS_NO_MEMORY
        jmp     AtlModuleInit.Epilog    


HRESULT __fastcall AtlModuleInit(struct _ATL_MODULE_30 *ATL__CComModule, struct _ATL_OBJMAP_ENTRY *ATLObjMap, HANDLE hinstDLL)
x64 VC++6.0:
Code:
AtlModuleInit:
        .ATL__CComModule.shadow   = _stackarg(0) ; where "_stackarg equ esp+ptrsize+ptrsize*" and ptrsize for x64 equal to 8
        .ATLObjMap.shadow         = _stackarg(1)
        .hinstDLL.shadow          = _stackarg(2)

        add     rsp, $28 ;return stack to state before placing stack shadow (that always 4*8=$20 bytes size) and placing 8 byte retaddres
        push    rbx ;use shadow for storing register
        push    rdi ;use shadow for storing register
        push    rsi ;use shadow for storing register
        push    rcx ;use shadow for storing register
        sub     rsp, $30 ;skip retaddr & alignment & make minimal room 4*8 for first 4 param shadow in stack for subcalls
        test    rcx, rcx; ? ATL__CComModule
        jz      AtlModuleInit.retE_INVALIDARG
        mov     eax, [rcx+_ATL_MODULE_30.cbSize]
        cmp     eax,$B0
        jz      AtlModuleInit.sizeOK
        cmp     eax,$F0
        jz      AtlModuleInit.sizeOK
        cmp     eax,$F8
        jz      AtlModuleInit.sizeOK

AtlModuleInit.retE_INVALIDARG:
        mov     eax, E_INVALIDARG
        jmp     AtlModuleInit.Epilog

AtlModuleInit.sizeOK:
        mov     rbx, rcx
        mov     [rbx+_ATL_MODULE_30.m_pObjMap], rdx      ; <ATLObjMap
        mov     [rbx+_ATL_MODULE_30.m_hInst], r8         ; <hinstDLL
        mov     [rbx+_ATL_MODULE_30.m_hInstResource], r8 ; <hinstDLL
        mov     [rbx+_ATL_MODULE_30.m_hInstTypeLib], r8  ; <hinstDLL
        xor     eax,eax
        mov     [rbx+_ATL_MODULE_30.m_nLockCnt], eax
        mov     [rbx+_ATL_MODULE_30.m_hHeap], rax
        lea     rcx, [rbx+_ATL_MODULE_30.m_csTypeInfoHolder]
        call    [InitializeCriticalSection]
        jnExc   equ jmp ; patched by 2 byte nop, or ignored in case of exception
        jnExc   AtlModuleInit.noException_0

AtlModuleInit.onException_0:
        mov     rdi, [.ATL__CComModule.shadow+$28]
        add     rdi, _ATL_MODULE_30.m_csTypeInfoHolder
        xor     eax,eax
        inQWORDS equ /8
        mov     ecx, 1*sizeof.RTL_CRITICAL_SECTION inQWORDS;
        rep     stosd
        mov     eax, STATUS_NO_MEMORY
        jmp     AtlModuleInit.Epilog

AtlModuleInit.noException_0:
        lea     rcx, [rbx+_ATL_MODULE_30.m_csWindowCreate]
        call    [InitializeCriticalSection]
        jnExc   AtlModuleInit.noException_1

AtlModuleInit.onException_1:
        mov     rdi, [.ATL__CComModule.shadow+$28]
        add     rdi, _ATL_MODULE_30.m_csTypeInfoHolder
        mov     rcx, rdi
        call    [DeleteCriticalSection]
        xor     eax,eax
        inQWORDS equ /8
        mov     ecx, 2*sizeof.RTL_CRITICAL_SECTION inQWORDS;
        rep     stosd
        mov     eax, STATUS_NO_MEMORY
        jmp     AtlModuleInit.Epilog

AtlModuleInit.noException_1:
        lea     rcx, [rbx+_ATL_MODULE_30.m_csObjMap]
        call    [InitializeCriticalSection]
        jnExc   AtlModuleInit.noException_2

AtlModuleInit.onException_2:
        mov     rdi, [.ATL__CComModule.shadow+$28]
        mov     rcx, rdi
        add     rcx, _ATL_MODULE_30.m_csWindowCreate
        call    [DeleteCriticalSection]
        add     rdi, _ATL_MODULE_30.m_csTypeInfoHolder
        mov     rcx, rdi
        call    [DeleteCriticalSection]
        xor     eax,eax
        inQWORDS equ /8
        mov     ecx, 3*sizeof.RTL_CRITICAL_SECTION inQWORDS;
        rep     stosd
        mov     eax, STATUS_NO_MEMORY
        jmp     AtlModuleInit.Epilog

AtlModuleInit.noException_2:
        cmp     [rbx+_ATL_MODULE_30.cbSize], $B0
        je      AtlModuleInit.retHRESULT_S_OK
        xor     eax, eax
        mov     [rbx+_ATL_MODULE_30.m_pCreateWndList], rax
        mov     [rbx+_ATL_MODULE_30.m_bDestroyHeap], 1
        mov     [rbx+_ATL_MODULE_30.m_dwHeaps], rax
        mov     [rbx+_ATL_MODULE_30.m_phHeaps], rax
        mov     [rbx+_ATL_MODULE_30.m_nHeap], rax
        mov     [rbx+_ATL_MODULE_30.m_pTermFuncs], rax
        mov     rdi, [rbx+_ATL_MODULE_30.m_pObjMap]
        test    rdi, rdi
        jz      AtlModuleInit.retHRESULT_S_OK

AtlModuleInit.ForEachObjEntry:
        mov     rax, [rdi+_ATL_OBJMAP_ENTRY.pclsid]
        test    rax, rax
        jz      AtlModuleInit.Epilog
        mov     cl, TRUE
        call    [rdi+_ATL_OBJMAP_ENTRY.RevokeClassObject]
        add     rdi, $48
        cmp     [rdi],0
        jnz     AtlModuleInit.ForEachObjEntry
        cmp     [rbx+_ATL_MODULE_30.cbSize], $F8
        jb      AtlModuleInit.retHRESULT_S_OK
        mov     [rbx+sizeof._ATL_MODULE_30], 1

AtlModuleInit.retHRESULT_S_OK:
        xor     rax, rax

AtlModuleInit.Epilog:
        add     rsp, $30
        pop     rcx ;use shadow for storing register
        pop     rsi ;use shadow for storing register
        pop     rdi ;use shadow for storing register
        pop     rbx
        sub     rsp, $28
        ret    


We can summarize that AtlModuleInit does nothing useful over atl module initialization except call of RevokeClassObject(TRUE) (RevokeClassObject body contains only "ret 4"). And all atl module has nothing usefull except 3 initialized critical sections.

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


Last edited by ProMiNick on 11 Nov 2018, 11:05; edited 16 times in total
Post 14 Oct 2018, 23:26
View user's profile Send private message Send e-mail Reply with quote
ProMiNick



Joined: 24 Mar 2012
Posts: 206
Location: Russian Federation, Sochi
HRESULT __stdcall DllCanUnloadNow()
x86 VC++6.0:
Code:
DllCanUnloadNow:
        xor     eax, eax
        cmp     [Addend], eax
        setnz   al
        ret    

HRESULT __fastcall DllCanUnloadNow()
x64 VC++6.0:
Code:
DllCanUnloadNow:
        xor     eax, eax
        cmp     [Addend], eax
        setnz   al
        ret    


HRESULT __stdcall DllCanUnloadNow()
x86 VC++7.0:
Code:
DllCanUnloadNow:
        mov     ecx, [COM_libobject]
        mov     eax, [ecx]
        call    [eax+.method_3] ;.method_3 equ 8, methods start counting from 1
        neg     eax
        sbb     eax, eax
        neg     eax
        ret    


Last edited by ProMiNick on 14 Oct 2018, 23:45; edited 4 times in total
Post 14 Oct 2018, 23:27
View user's profile Send private message Send e-mail Reply with quote
ProMiNick



Joined: 24 Mar 2012
Posts: 206
Location: Russian Federation, Sochi
HRESULT __stdcall DllGetClassObject(const IID *const rclsid, const IID *const riid, VOID **ppv)
x86 Code VC++6.0:
Code:
DllGetClassObject:
        mov     edi, edi
        ;noreturn AtlModuleGetClassObject(_ATL_Module *p_ATL_Module, [from_stack] const IID *const rclsid, [from_stack] const IID *const riid, [from_stack] VOID **ppv) 
        pop     eax
        push    p_ATL_Module
        push    eax
        jmp     dword [AtlModuleGetClassObject] ; realized in ATL.DLL    


HRESULT __fastcall DllGetClassObject(const IID *const rclsid, const IID *const riid, VOID **ppv)
x64 Code VC++6.0:
Code:
DllGetClassObject:
        ;noreturn AtlModuleGetClassObject(_ATL_Module *p_ATL_Module, [from_stack] const IID *const rclsid, [from_stack] const IID *const riid, [from_stack] VOID **ppv)
        mov     r9, r8
        mov     r8, rdx
        mov     rdx, rcx
        lea     rcx, [p_ATL_Module]
        jmp     qword [AtlModuleGetClassObject]; realized in ATL.DLL    


HRESULT __stdcall DllGetClassObject(const IID *const rclsid, const IID *const riid, VOID **ppv)
x86 Code VC++7.0:
Code:
DllGetClassObject:
        mov     edi, edi
        mov     ecx, [COM_libobject]
        ;noreturn AtlModuleGetClassObject(COM_LIBOBJECT *hidden This, _ATL_Module *p_ATL_Module, [from_stack] const IID *const rclsid, [from_stack] const IID *const riid, [from_stack] VOID **ppv)
        pop     eax
        push    p_ATL_Module
        push    eax
        jmp     dword [AtlModuleGetClassObject]; realized in same module    


Last edited by ProMiNick on 14 Oct 2018, 23:44; edited 1 time in total
Post 14 Oct 2018, 23:28
View user's profile Send private message Send e-mail Reply with quote
ProMiNick



Joined: 24 Mar 2012
Posts: 206
Location: Russian Federation, Sochi
HRESULT __stdcall DllRegisterServer()
x86 VC++6.0:
Code:
DllRegisterServer:
        mov     edi, edi
        ;noreturn AtlModuleRegisterServer(_ATL_Module *p_ATL_Module, BOOL bUnRegTypeLib, const CLSID *pCLSID)
        pop     eax
        push    NULL
        push    TRUE
        push    p_ATL_Module
        push    eax
        jmp     dword [AtlModuleRegisterServer]; realized in ATL.DLL    


HRESULT __fastcall DllRegisterServer()
x64 VC++6.0:
Code:
DllRegisterServer:
        ;noreturn AtlModuleRegisterServer(_ATL_Module *p_ATL_Module, BOOL bUnRegTypeLib, const CLSID *pCLSID)
        xor     r8d, r8d ; NULL
        lea     edx, [ r8 + 1] ; TRUE 
        lea     rcx, [p_ATL_Module]
        jmp     qword [AtlModuleRegisterServer]; realized in ATL.DLL    


HRESULT __stdcall DllRegisterServer()
x86 VC++7.0:
More complex analize needed... not used ATL for RegisterServer


Last edited by ProMiNick on 14 Oct 2018, 23:58; edited 2 times in total
Post 14 Oct 2018, 23:28
View user's profile Send private message Send e-mail Reply with quote
ProMiNick



Joined: 24 Mar 2012
Posts: 206
Location: Russian Federation, Sochi
HRESULT __stdcall DllUnregisterServer()
x86 VC++6.0:
Code:
DllUnregisterServer:
        mov     edi, edi
        ;noreturn AtlModuleUnregisterServerEx(_ATL_Module *p_ATL_Module, BOOL bUnRegTypeLib, const CLSID *pCLSID)
        pop     eax
        push    NULL
        push    TRUE
        push    p_ATL_Module
        push    eax
        jmp     dword [AtlModuleUnregisterServerEx]; realized in ATL.DLL    


HRESULT __fastcall DllUnregisterServer()
x64 VC++6.0:
Code:
DllUnregisterServer:
        ;noreturn AtlModuleUnregisterServerEx(_ATL_Module *p_ATL_Module, BOOL bUnRegTypeLib, const CLSID *pCLSID)
        xor     r8d, r8d ; NULL
        lea     edx, [ r8 + 1] ; TRUE
        lea     rcx, [p_ATL_Module]
        jmp     qword [AtlModuleUnregisterServerEx]; realized in ATL.DLL    




HRESULT __stdcall DllUnregisterServer()
x86 VC++7.0:
More complex analize needed... not used ATL for UnregisterServer


Last edited by ProMiNick on 15 Oct 2018, 00:03; edited 2 times in total
Post 14 Oct 2018, 23:29
View user's profile Send private message Send e-mail Reply with quote
ProMiNick



Joined: 24 Mar 2012
Posts: 206
Location: Russian Federation, Sochi
for x86 ptr equ dd, ptrsize equ 4
for x64 ptr equ dq, ptrsize equ 8

Code:
struct COMobject ;
        interfaceList ptr ?; order of 1st & 2nd members not tested
        pClsid ptr ?        ;
        useCounter dd ? ; tested - confirmed
        align ptrsize 
        userdata db 0 dup (?) ; tested - confirmed, if object has no userdata it can be initialized in static memory and shared with all threads, create in heap otherwise for each DllGetClassObject request
ends

struct _RTL_CRITICAL_SECTION
        DebugInfo        ptr ?
        LockCount        dd ?
        RecursionCount   dd ?
        OwningThread     ptr ?
        LockSemaphore    ptr ?
        SpinCount        ptr ?
ends

struct _ATL_MODULE
        cbSize          ptr ?
        m_hInst         ptr ?
        m_hInstResource ptr ?
        m_hInstTypeLib  ptr ?
        m_pObjMap       ptr ?
        m_nLockCnt      ptr ?
        m_hHeap         ptr ?
        m_csTypeInfoHolder _RTL_CRITICAL_SECTION
        m_csWindowCreate _RTL_CRITICAL_SECTION
        m_csObjMap      _RTL_CRITICAL_SECTION
ends

struct ATL_BASE_MODULE30 _ATL_MODULE
        dwAtlBuildVer   ptr ?                    
        m_pCreateWndList ptr ?
        m_bDestroyHeap  ptr ?
        pguidVer        ptr ?                    
        m_dwHeaps       ptr ?
        m_phHeaps       ptr ?
        m_nHeap         ptr ?
        m_pTermFuncs    ptr ?
ends

struct ATL_BASE_MODULE30x64Ex ATL_BASE_MODULE30
        dwHasValueOne    ptr ?
ends    
Post 14 Oct 2018, 23:29
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-2018, Tomasz Grysztar.

Powered by rwasa.