Странное поведение с простой программой 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

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

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


person user1364743    schedule 28.11.2013    source источник


Ответы (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 после вызова.

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

person Devolus    schedule 28.11.2013

Чтобы добавить к правильному ответу 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
person Gunner    schedule 28.11.2013