逆向工程获得功能原型

问题描述 投票:3回答:1

我试图从我注入的c++ dll中获取一个asm函数的原型来调用它。

这里是函数。

PUSH EBP
MOV EBP,ESP
PUSH -1
PUSH Program.0151A5BB
MOV EAX,DWORD PTR FS:[0]
PUSH EAX
SUB ESP,0F8
MOV EAX,DWORD PTR DS:[167D380]
XOR EAX,EBP
MOV DWORD PTR SS:[EBP-14],EAX
PUSH EBX
PUSH ESI
PUSH EDI
PUSH EAX
LEA EAX,DWORD PTR SS:[EBP-C]
MOV DWORD PTR FS:[0],EAX
MOV DWORD PTR SS:[EBP-10],ESP
MOV EDI,EDX
MOV ESI,ECX
MOV DWORD PTR SS:[EBP-4],0
CMP ESI,0FFFF
JE SHORT Program.0117DFC9
CALL Program.01205130
MOV ECX,82
CALL Program.012F2AE0
MOV ECX,ESI
CALL Program.012F3050
MOV ECX,EDI
CALL Program.012F3050
MOV ECX,DWORD PTR SS:[EBP+8]
CALL Program.012F2EA0
MOV ECX,DWORD PTR SS:[EBP+C]
CALL Program.012F3050
MOV ECX,DWORD PTR SS:[EBP+10]
CALL Program.012F2EA0
MOV ECX,DWORD PTR SS:[EBP+14]
CALL Program.012F2EA0
MOV CL,1
CALL Program.012F39B0
MOV DWORD PTR SS:[EBP-4],-1
MOV ECX,DWORD PTR SS:[EBP-C]
MOV DWORD PTR FS:[0],ECX
POP ECX
POP EDI
POP ESI
POP EBX
MOV ECX,DWORD PTR SS:[EBP-14]
XOR ECX,EBP
CALL Program.014BB1AC
MOV ESP,EBP
POP EBP
RETN

下面是一个调用这个函数的例子:

JMP Program.001CDD83
CALL Program.000930A0
MOV ECX,EAX
CALL Program.0024EC10
PUSH EAX                                 ; /Arg4
PUSH DWORD PTR SS:[EBP-168]              ; |Arg3
PUSH DWORD PTR DS:[EDI+8]                ; |Arg2
PUSH DWORD PTR SS:[EBP-160]              ; |Arg1
MOV EDX,DWORD PTR SS:[EBP-16C]           ; |
MOV ECX,DWORD PTR SS:[EBP-164]           ; |
CALL Program.0006DF80                      ; \<---- TARGET FUNCTION
ADD ESP,10
JMP Program.001CDD83
TEST EAX,800
JE SHORT Program.001CDF6D
TEST ESI,ESI
JE Program.001CDD83
CMP ESI,DWORD PTR DS:[72202C]
JE Program.001CDD83
CMP ESI,DWORD PTR DS:[584684]

通过函数调用,我能够推断出这是一个 __fastcall 函数,因为它使用了 EDXECX 寄存器,并通过堆栈获取4个附加参数。

在调用的瞬间检查栈和寄存器,我可以确定6个参数都是数字。

这是一张刚刚在函数调用时的状态图。

Registry and stack at the moment of the call

考虑到这些,我做了这样的定义

typedef void(__fastcall *_programFunction)(DWORD ECX, DWORD EDX, DWORD param1, DWORD param2, DWORD param3, DWORD param4);

它调用函数和函数 作品 但我的DLL 崩溃 显示这个错误。

"Debug Error!Run-Time Check Failure #0--ESP的值在一次函数调用中没有正确保存。这通常是由于调用一个用一种调用约定声明的函数,而用另一种调用约定声明的函数指针。"

我很确定这是一个 __fastcall 函数,因为它是唯一一个优先处理 EDXECX 在栈上。另外,调用函数并没有清理栈,这也是另一个提示,对于 __fastcall

有什么技巧可以从asm代码中推导出函数protptype?

我的思路有什么问题吗?

EDIT:

我查了一下 主要实际 说过

ADD ESP,在你的函数调用后的10在我看来更像是__cdecl:调用者清理栈。如果是一个__fastcall,你应该在最后找到RET 10。–

当我手动将前两个参数添加到 ECXEDX 册。

像这样

typedef void(__cdecl *_targetFunction)(DWORD param1, DWORD param2, DWORD param3, DWORD param4);


_targetFunction fcall= (_targetFunction)(ADD_TARGET_FUNCTION);
__asm
        {
            mov ECX, ECX_PARAM
            mov EDX, EDX_PARAM
        }
fcall(param1, pram2, param3, param4);

谢谢!但我为什么要这样做呢?有什么办法可以自动设置寄存器吗?

谢谢你!我想让一个asm函数的原型从我注入的c++ dll中调用它。

c++ reverse-engineering dll-injection
1个回答
0
投票

由于优化的原因,你偶尔会发现一些函数不完全符合正常的调用习惯。

在这种情况下,解决方案是使用内联汇编,你在问题中已经完成了。

typedef void(__cdecl *_targetFunction)(DWORD param1, DWORD param2, DWORD param3, DWORD param4);


_targetFunction fcall= (_targetFunction)(ADD_TARGET_FUNCTION);
__asm
        {
            mov ECX, ECX_PARAM
            mov EDX, EDX_PARAM
        }
fcall(param1, pram2, param3, param4);

有时候就是这样.

© www.soinside.com 2019 - 2024. All rights reserved.