Странное поведение с простой программой MASM32

Я хочу написать программу MASM, похожую на следующую программу C++:

#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);
}

Как видите, этот код выполняет калькулятор Microsoft. Я просто хочу сделать то же самое, используя MASM, но выполнение не удается.

Вот исходный код MASM:

.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

crt_printf вывод правильный. Тот же адрес печатается как в программе C++. Таким образом, адрес передан call это тот же самый. Однако выполнение не удается.

Вот код MASM32, который работает, но на этот раз адрес функции WinExec жестко запрограммирован так:

.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

Увидеть линию mov esi, 779e304eh, Но динамически, есть проблема. Если я разоберу код чуть выше, мы увидим, что порядок байтов обратный.

8EEH047E379

Может быть, это не тот случай, и мне нужно ключевое слово в следующей строке (между запятой и procAddr):

mov esi, procAddr

Я не могу найти решение. Я потерялся. Может кто-нибудь мне помочь?

Заранее большое спасибо за вашу помощь.

2 ответа

Решение

Выполнение не выполняется, потому что вы не передаете его параметры.

Здесь вы просто вызываете функцию без каких-либо аргументов или, скорее, с недопустимыми аргументами (потому что все, что в данный момент находится в стеке, будет взято и стек поврежден в процессе).

mov esi, procAddr
call esi

Ты должен сделать

push SW_SHOWDEFAULT
push offset YourPathToCalc
mov esi, procAddr
call esi

В вашем примере кода это то, что делается здесь неявно

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

Еще одна вещь, которую вы упускаете, что когда WinExec возвращается, он начнет выполнять путь в вашем случае, поэтому вам нужно jmp somewhere после звонка.

И, как указал Ганнер, путь должен быть нулевым.

Чтобы добавить к правильному ответу, опубликованному Devolus, ваш путь к calc не NULL завершен. это

"C:\WINDOWS\system32\calc.exe" не является правильным!

Вместо этого должно быть:

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

Кроме того, если вы собираетесь поместить строки в секции кода для использования, вам нужно дать им метку, чтобы использовать их, и вам нужно перепрыгнуть через них, иначе процессор попытается выполнить байты.

    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

* РЕДАКТИРОВАТЬ * Чтобы преобразовать этот код в сборку с помощью MASM, все, что нужно, это:

    .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
Другие вопросы по тегам