2013-05-29 59 views
1

你好,我有一个函数C++ __usercall在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 

几声函数有APPE ars是

add  esp, 24h 
retn 10h 

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

+0

不要信任来自IDA的函数签名。有时候,IDA不会产生正确的签名。你需要手动分析它。 – UltimaWeapon

+0

所以钩子好吗? – user1422473

回答

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,除非你自己验证它。

+0

有几次在功能有 加上ESP,24h retn 10h 所以我想有更多的参数和IDA是错的? – user1422473

+0

@ user1422473这是一个很好的假设。我编辑了我的答案,以反映您发布的其他代码。在“调用测试”之后注意行,以确保您正在清理堆栈。如果您可以在通话后添加代码,我会在必要时更新我的​​答案。 –

+0

包括在原来的帖子 – user1422473