Search code examples
assemblymasm32

Assembly dynamic call causes segmentation fault


I'm working on a university project, so i'm trying to code a PE infector in MASM32. One of the needed features is not to directly call the needed functions, but to find their address dynamically: I search the kernel32 lib in memory, with its export table I find the GetProcAddressName function, then GetModuleHandle function, then with this I load the user32 handle, which i use with GetProcAdsress to gain access to functions; MessageBoxA in my example:

.386
.model flat, stdcall
option casemap:none

      include \masm32\include\windows.inc
      include \masm32\include\user32.inc
      include \masm32\include\kernel32.inc
      include \masm32\include\masm32rt.inc

      includelib \masm32\lib\user32.lib
      includelib \masm32\lib\kernel32.lib

.code

start:
        mov ebx, dword ptr[esp]
        and ebx, 0ffff0000h
        .while word ptr[ebx] != 'ZM'
            dec ebx
        .endw
        mov kernelAddr, ebx

        mov eax, ebx
        add eax, 3Ch
        mov eax, dword ptr[eax]
        add eax, ebx
 pekernelFound:
        mov peKernelAddr, eax

        mov edx, kernelAddr
        mov ebx, eax
        add ebx, 78h
        mov ebx,  dword ptr[ebx]
        add ebx, edx

        mov ecx, ebx
        add ecx, 1ch
        mov ecx, dword ptr[ecx]
        add ecx, edx
        mov functionTableAddr, ecx

        mov ecx, ebx
        add ecx, 20h
        mov ecx, dword ptr[ecx]
        add ecx, edx
        mov functionNameTableAddr, ecx

        mov ecx, ebx
        add ecx, 24h
        mov ecx, dword ptr[ecx]
        add ecx, edx
        mov ordinalTableAddr, ecx

searchProcAddressFunc:     
        mov ebx, functionNameTableAddr
        mov esi, dword ptr[ebx]
        add esi, kernelAddr
        mov edi, offset GetProcAddressName
        mov edx, 1
        mov ecx, 0 ; l'index
        .while edx != 0
            mov al, byte ptr [esi]
            mov bl, byte ptr [edi]
            .if al != bl
                .while byte ptr [esi] != 0
                    inc esi
                .endw
                inc esi
                inc ecx 
                mov edi, offset GetProcAddressName
             .else
                .if byte ptr [esi] == 0
                    mov edx, 0 
                .else
                    inc esi
                    inc edi
                .endif
            .endif
        .endw

        mov eax, 2
        mul ecx
        mov ecx, eax
        add ecx, ordinalTableAddr
        xor eax, eax
        mov ax, word ptr [ecx]
        mov ecx, 4
        mul ecx
        add eax, functionTableAddr
        mov eax, dword ptr [eax]
        add eax, kernelAddr
        mov GetProcAddressAddr, eax

gettingGetModuleHandle:
        push offset GetModuleHandleName
        push kernelAddr
        call GetProcAddressAddr
        mov GetModuleHandleAddr, eax
        push offset User32DllName
        call GetModuleHandleAddr

gettingMessageBox:        
        mov user32Addr, eax
        push offset MessageBoxName
        push eax
        call GetProcAddressAddr
        mov MessageBoxAddr, eax

        push MB_OK
        push offset hello
        push offset hello
        push 0
        call  MessageBoxAddr

        push    0
    call    ExitProcess

        hello                       db      "Hello buddy", 0


        kernelAddr                  dd      ?
        user32Addr                  dd      ?
        peKernelAddr                dd      ?
        functionTableAddr           dd      ?
        functionNameTableAddr       dd      ?
        ordinalTableAddr            dd      ?

        GetProcAddressName          db      "GetProcAddress",0
        GetModuleHandleName         db      "GetModuleHandleA",0
        MessageBoxName              db      "MessageBoxA", 0
        MessageBoxAddr              dd      ?

        GetProcAddressAddr          dd      ?
        GetModuleHandleAddr         dd      ?

        User32DllName               db      "User32.dll",0
end start

The result is a segmentation fault at the call MessageBoxAddr. Excepted if I call the original function, doesn't matter where:

    push MB_OK
    push offset hello
    push offset hello
    push 0
    call  MessageBoxA

If I place this sample before, or after, both calls work, which is a complete non-sense to me.

Do you have any leads ? Thank you


Solution

  • Problem solved : The GetModuleHandle function only works if the lib was already loaded in memory, and gives the handle of it.

    I use the LoadLibraryA instead (LoadLibrary is not found, I don't know why...) and it works perfectly. Thanks anyway :p