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