如何从汇编代码中找出函数原型?

Mic*_*ine 6 c++ assembly reverse-engineering visual-studio visual-c++

我有一些汇编代码,我想找出调用函数原型,以便我可以从c ++代码中获取所有函数.

我真正想要做的是将一个dll注入到一个正在运行的进程中,然后从我的dll中调用正在运行的进程的函数.现在我已成功注入了我的dll,但不知道如何进行'调用'.

我是新手,我只对汇编代码有所了解.我的dll是用visual c ++ 2012编写的.

以下是正在运行的进程的代码:

CPU Disasm
Address   Hex dump          Command                                  Comments
6013BE24  /$  53            PUSH EBX
6013BE25  |.  8B1D 10461860 MOV EBX,DWORD PTR DS:[60184610]
6013BE2B  |.  8B1B          MOV EBX,DWORD PTR DS:[EBX]
6013BE2D  |.  8B40 04       MOV EAX,DWORD PTR DS:[EAX+4]
6013BE30  |.  FFD3          CALL EBX
6013BE32  |.  5B            POP EBX
6013BE33  \.  C3            RETN
Run Code Online (Sandbox Code Playgroud)

您可以看到6013BE30它正在调用该函数,而函数(EBX)位于004BAFAC

CPU Disasm
Address   Hex dump          Command                                  Comments
004BAFAC  /$  55            PUSH EBP                                 ; Test.004BAFAC(guessed void)
004BAFAD  |.  8BEC          MOV EBP,ESP
004BAFAF  |.  53            PUSH EBX
004BAFB0  |.  8BD8          MOV EBX,EAX
004BAFB2  |.  8B43 08       MOV EAX,DWORD PTR DS:[EBX+8]
004BAFB5  |.  E8 3EF40B00   CALL 0057A3F8                            ; [Test.0057A3F8
004BAFBA  |.  8B43 0C       MOV EAX,DWORD PTR DS:[EBX+0C]
004BAFBD  |.  E8 36F40B00   CALL 0057A3F8                            ; [Test.0057A3F8
004BAFC2  |.  8B43 14       MOV EAX,DWORD PTR DS:[EBX+14]
004BAFC5  |.  E8 2EF40B00   CALL 0057A3F8                            ; [Test.0057A3F8
004BAFCA  |.  8B43 18       MOV EAX,DWORD PTR DS:[EBX+18]
004BAFCD  |.  E8 26F40B00   CALL 0057A3F8                            ; [Test.0057A3F8
004BAFD2  |.  8B43 1C       MOV EAX,DWORD PTR DS:[EBX+1C]
004BAFD5  |.  E8 1EF40B00   CALL 0057A3F8                            ; [Test.0057A3F8
004BAFDA  |.  8B43 10       MOV EAX,DWORD PTR DS:[EBX+10]
004BAFDD  |.  E8 16F40B00   CALL 0057A3F8                            ; [Test.0057A3F8
004BAFE2  |.  8B43 20       MOV EAX,DWORD PTR DS:[EBX+20]
004BAFE5  |.  E8 0EF40B00   CALL 0057A3F8                            ; [Test.0057A3F8
004BAFEA  |.  8B43 44       MOV EAX,DWORD PTR DS:[EBX+44]
004BAFED  |.  E8 06F40B00   CALL 0057A3F8                            ; [Test.0057A3F8
004BAFF2  |.  8B43 44       MOV EAX,DWORD PTR DS:[EBX+44]
Run Code Online (Sandbox Code Playgroud)

那么如何004BAFAC从visual c ++ 调用函数呢?

Sas*_*nig 2

在汇编中,函数参数从堆栈中弹出,从最后一个开始。因此,要将参数传递给函数,首先将它们压入堆栈,然后调用该函数。在 MASM 中,这看起来类似于显示消息框:

.data 
MsgBoxCaption  db "Attention",0 
MsgBoxText     db "Hello Message Box!",0 

.code
start:
push 0
mov eax, offset MsgBoxCaption
push eax
push offset MsgBoxText
push 0
call MessageBoxA
call ExitProcess
end start
Run Code Online (Sandbox Code Playgroud)

在 C++ 中,它看起来像这样:

int retval = MessageBox(NULL, "Hello Message Box!", "Attention", 0);
Run Code Online (Sandbox Code Playgroud)

用 OllyDbg 反汇编你会得到:

CPU Disasm
Address   Hex dump          Command                                  Comments
011D13C0  |.  6A 00         PUSH 0                                   ; /Type = MB_OK|MB_DEFBUTTON1|MB_APPLMODAL
011D13C2  |.  68 54571D01   PUSH OFFSET 011D5754                     ; |Caption = "Attention"
011D13C7  |.  68 3C571D01   PUSH OFFSET 011D573C                     ; |Text = "Hello Message Box!"
011D13CC  |.  6A 00         PUSH 0                                   ; |hOwner = NULL
011D13CE  |.  FF15 40831D01 CALL DWORD PTR DS:[<&USER32.MessageBoxA> ; \USER32.MessageBoxA
Run Code Online (Sandbox Code Playgroud)

返回值存储在 eax 中。您会发现,如果数据类型大于 DWORD(4 个字节),您实际上传递的不是值,而是引用。每个参数实际上只是一个 DWORD。这是因为堆栈在 32 位系统中是 32 位对齐的,因此只能保存 32 位值。寄存器的情况也是如此。在 32 位系统中,寄存器是 32 位宽。如果传递字符串,则传递的是对该字符串的引用,而不是字符串或字符/字节的可变宽度数组。如果是整数,它很可能作为值而不是引用传递。在 MASM 中对函数进行原型设计时,所有参数都可以使用 DWORD 原型(但在 C++ 中则不然)。

因此,在上面的示例中,似乎一个参数传递到堆栈上(push ebx)。我说似乎是因为很可能只是 ebx 被推送来存储它以供以后检索(即在调用 ebx 再次弹出之后 - 也许需要保留存储在 ebx 中的值)。您只能在实际运行实时调试会话并观察堆栈/寄存器时才能确定。跳过调用并检查前后的堆栈指针(esp),以查看传递给函数的参数数量(再次强调:1 个参数 = 1 个 DWORD = 4 个字节)。

要在 C++ 中对函数进行原型设计,您需要弄清楚参数是什么数据类型,可能是通过单步执行汇编代码并在遍历相关函数的代码时检查寄存器和/或堆栈。eax 中的返回值也是如此。因此 eax 永远不会保存字符串,而可能保存对字符串的引用,但它可能保存 32 位或更小的整数。您还必须通过反转周围的代码来找出 eax 指向哪种数据。

编辑:实际上我写的东西有一半是错误的,最值得注意的是参数总是引用,所以请重新阅读我写的内容。抱歉给您带来不便 - 不应该回答累了的问题:)