【问题标题】:Strange behaviour with a simple MASM32 program一个简单的 MASM32 程序的奇怪行为
【发布时间】:2013-12-14 19:28:43
【问题描述】:

我想写一个类似于下面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 行。但是动态的,就有问题了。如果我反汇编上面的代码,我们可以看到字节顺序是颠倒的。

8EEH047E379

也许动态情况并非如此,也许我需要以下行中的关键字(在逗号和 procAddr 之间):

mov esi, procAddr

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

非常感谢您的帮助。

【问题讨论】:

    标签: windows assembly x86 masm masm32


    【解决方案1】:

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

    在这里,您只需调用不带任何参数或使用无效参数的函数(因为当前堆栈上的任何内容都将被占用,并且堆栈在进程中已损坏)。

    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 指出的那样,路径必须以 0 结尾。

    【讨论】:

      【解决方案2】:

      要添加到 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, 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
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2022-01-17
        • 2018-04-02
        • 1970-01-01
        • 1970-01-01
        • 2015-06-25
        • 2018-04-25
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多