奇怪的行为与一个简单的MASM32程序

我想写一个类似于下面的C ++程序的MASM程序:

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

正如你所看到的,这段代码执行微软计算器。 我只是想使用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 。 但是dynamic地,有一个问题。 如果我反汇编上面的代码,我们可以看到字节的顺序是颠倒的。

 8EEH047E379 

也许这不是dynamic的,也许我需要在以下行(在逗号和procAddr之间)的关键字:

 mov esi, procAddr 

我找不到解决scheme。 我迷路了。 谁能帮我?

提前感谢您的帮助。

执行失败,因为你没有传递它的参数。

这里你只需要调用函数而不用任何参数,或者使用无效的参数(因为当前在堆栈中的任何东西都将被采用,堆栈在进程中被破坏)。

 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

正如Gunner指出的那样,路径必须终止。

要添加到Devolus发布的正确答案,您的calc的路径不是NULL终止。 这个

"C:\WINDOWS\system32\calc.exe"是不正确的!

相反,它应该是:

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

另外,如果要在代码段中使用字符串,则需要给它们一个标签才能使用它们,并且需要跳过它们,否则CPU将尝试执行这些字节。

  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, hmodulee 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