Domanda

I want to write a MASM program similar to the following C++ program :

#include <Windows.h>
#include <iostream>

typedef UINT (_stdcall *FuncPtr)(LPCSTR lpCmdLine, UINT uCmdShow);

int main(void)
{
    HMODULE hDll = LoadLibrary(TEXT("Kernel32.dll"));
    FuncPtr func_addr = reinterpret_cast<FuncPtr>(GetProcAddress(hDll, "WinExec"));

    (*func_addr)("C:\\WINDOWS\\system32\\calc.exe", SW_SHOWDEFAULT);
    FreeLibrary(hDll);

    return (0);
}

As you can see, this code execute the microsoft calculator. I just want to do the same thing using MASM but the execution fails.

Here's the MASM source code :

.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\masm32.inc
include \masm32\include\msvcrt.inc

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

.data

LpFileName db "kernel32.dll", 0
procName db "WinExec", 0
display db "addr_func = 0x%x", 0

.data?

hModule HMODULE ?
procAddr FARPROC ?

.code

start:

    invoke LoadLibrary, offset LpFileName
    mov hModule, eax
    invoke GetProcAddress, hModule, ADDR procName
    mov procAddr, eax

    INVOKE crt_printf, ADDR display, procAddr

    mov esi, procAddr
    call esi

    db "C:\WINDOWS\system32\calc.exe"

    invoke FreeLibrary, hModule
    invoke ExitProcess, NULL

end start

The crt_printf output is correct. The same address is printed like withe the C++ program. So the address passed to call is the same one. However the execution fails.

Here's a MASM32 code which works but this time the address of the function WinExec is hardcoded like this :

.386
.model flat, stdcall
option casemap:none

include \masm32\include\windows.inc

.code

start:
jmp _Debut

_Final:
TCHAR 233
dword 42424242h

_Suite:
mov esi, 779e304eh
call esi
jmp _Final

_Debut:
xor eax, eax
push eax
call _Suite
db "C:\WINDOWS\system32\calc.exe"

end start

See the line mov esi, 779e304eh. But dynamically, there is a problem. If I disassemble the code just above we can see that the order of bytes is reversed.

8EEH047E379

Maybe it's not the case dynamically and maybe I need a keyword in the following line (between the comma and procAddr):

mov esi, procAddr

I cannot find the solution. I'm lost. Can anyone help me?

Thanks a lot in advance for your help.

È stato utile?

Soluzione

The execution fails because you are not passing it's parameters.

Here you just call the function without any arguments or rather with invalid arguments (because whatever is currently on the stack will be taken and the stack is corrupted in the process).

mov esi, procAddr
call esi

You should do

push SW_SHOWDEFAULT
push offset YourPathToCalc
mov esi, procAddr
call esi

In your samplecode this is what is done here implicitly

xor eax, eax
push eax      ; uCmdShow
call _Suite   ; Returnadress is the address of the commandline so this is bascially the "push path"

Another thing you are missing is, that when WinExec returns, it will start executing the path in your case so you need a jmp somewhere after the call.

And as Gunner pointed out, the path must be 0 terminated.

Altri suggerimenti

To add to the correct answer Devolus posted, your path to calc is not NULL terminated. This

"C:\WINDOWS\system32\calc.exe" is not correct!

Instead it should be:

"C:\WINDOWS\system32\calc.exe", 0

Also, if you are going to put strings in the code section to use, you need to give them a label in order to use them and you need to jump over them otherwise the CPU will try to execute the bytes.

    INVOKE crt_printf, ADDR display, procAddr

    mov     esi, procAddr
    push    SW_SHOWDEFAULT
    push    offset Calc
    call    esi

    jmp     @F
    Calc    db "C:\WINDOWS\system32\calc.exe", 0
    @@:

    invoke FreeLibrary, hModule
    invoke ExitProcess, NULL

* EDIT * To convert that code to Assembly using MASM, all that is needed is this:

    .data
    LpFileName  db "kernel32", 0
    procName    db "WinExec", 0
    Calc        db "calc", 0

    .code
    start:

        invoke  LoadLibrary, offset LpFileName
        push    eax
        invoke  GetProcAddress, eax, ADDR procName

        push    SW_SHOWDEFAULT
        push    offset Calc
        call    eax

        call    FreeLibrary

        invoke  ExitProcess, NULL

    end start
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top