2013-11-28 53 views
1

奇怪的行爲,我想寫類似下面的C++程序的MASM程序:用一個簡單的MASM32程序

#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 

我無法找到解決方案。我迷路了。誰能幫我?

非常感謝您的幫助。

回答

1

執行失敗,因爲您沒有傳遞它的參數。

在這裏,您只需調用沒有任何參數或者無效參數的函數(因爲當前堆棧中的任何內容都將被採用並且堆棧在進程中被破壞)。

mov esi, procAddr 
call esi 

你應該做

push SW_SHOWDEFAULT 
push offset YourPathToCalc 
mov esi, procAddr 
call esi 

在你samplecode這就是在這裏完成隱含

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終止的。

1

要添加到Devolus發佈的正確答案,您的calc路徑不是NULL終止。 This

"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