1

你好在 IDA 我有一个函数

void __userpurge Test(int a1<eax>, int a2, int a3, int a4, char a5)

我想从我的 C++ 注入的 dll 中挂钩/调用它这就是我尝试调用它的方式,但是 .exe 崩溃

DWORD CALL_ORIGINAL = 0x00EAF6D0;
__declspec(naked) void  myHookedFunc(int a1,int a2,int a3,int a4,char a5) {
    __asm
 {

    push a5
    push a4
    push a3
    push a2
    push eax
    call  CALL_ORGIGINAL //maybe use JMP?
    retn

   }
}

这就是exe调用这个函数的方式

mov     eax, [ebp+arg_4]
add     esp, 8
push    eax
push    ecx
mov     ecx, [edi+2138h]
mov     edx, [ecx+4]
mov     ecx, [edx+30h]
mov     edx, [ecx]
mov     eax, esp
mov     [eax], edx
mov     eax, [edi+20h]
mov     [esp+40h+var_24], esp
push    eax
push    eax
mov     eax, edi
call    Test
pop     edi
pop     esi  
retn

在功能上似乎有几次

add     esp, 24h
retn    10h

这意味着有更多的参数或 IDA 有错误的参数类型?

4

1 回答 1

2

__userpurge函数使用类似于 的调用约定,__usercall只是调用者负责清理堆栈。但是,查看您发布的 IDA 的附加代码很可能提供了不正确的参数数量不正确的调用约定。我建议您通过call CALL_ORGIGINAL在调用前后放置断点并观察 ESP 的值来验证这一点。如果 ESP 在返回时不同,那么它CALL_ORIGINAL正在清理堆栈,您无需再做任何事情。如果CALL_ORIGINAL确实清理了堆栈,您可能可以通过将差异除以 4 来确定传递的参数数量(假设每个参数都是 32 位)。

另一个问题是您不应该将堆栈推eax入堆栈(根据您编辑中包含的调用代码)。调用此函数的现有代码将第一个参数放入eax但不将其压入堆栈。

根据您问题中的代码并假设参数的数量是正确的,您的钩子函数应该类似于下面的示例。

__declspec(naked) void  myHookedFunc(int a1,int a2,int a3,int a4,char a5) {
    __asm
 {

    push a5
    push a4
    push a3
    push a2
    // eax is not pushed onto the stack
    call CALL_ORGIGINAL
    retn
   }
}

如果调用约定和参数个数是正确的,ESP前后的值应该是一样的CALL_ORIGINAL。如果不是,您将需要对其进行更多调查以确定正确的调用约定和参数。

简而言之,除非您自己验证,否则永远不要相信 IDA。

于 2013-05-29T14:06:47.660 回答