2012-01-12 62 views
0

我用IDA pro反汇编了一个可执行文件。我的目标是钩住__usercall函数。我知道我需要在我的C++代码中使用inine asm包装__usercall,因为我无法输入该函数。但我不知道这是如何工作的。用内联asm连接用户调用

我知道该函数将一个对象作为参数,一个* Vector3作为参数来存储计算出的值。有没有一种简单的方法可以告诉哪个参数是什么?

(抱歉长码)

char __usercall sub_572EA0<al>(int a1<ecx>, int a2<edx>, int a3<eax>, int a4) 
{ 
    int v4; // [email protected]                
    int v5; // [email protected]                
    float v6; // [email protected]               
    char v7; // [email protected]                
    int v8; // [email protected]                
    char result; // [email protected]              
    int v10; // [sp+Ch] [bp-74h]@2            
    float v11; // [sp+10h] [bp-70h]@4           
    float v12; // [sp+14h] [bp-6Ch]@4           
    float v13; // [sp+18h] [bp-68h]@5           
    float v14; // [sp+1Ch] [bp-64h]@5           
    float v15; // [sp+20h] [bp-60h]@5           
    float v16; // [sp+24h] [bp-5Ch]@10           
    float v17; // [sp+28h] [bp-58h]@10           
    float v18; // [sp+2Ch] [bp-54h]@10           
    char v19; // [sp+30h] [bp-50h]@10           
    float v20; // [sp+3Ch] [bp-44h]@4           
    float v21; // [sp+40h] [bp-40h]@4           
    float v22; // [sp+44h] [bp-3Ch]@4           
    float v23; // [sp+54h] [bp-2Ch]@7           

    v4 = a3;                  
    v5 = a1;                  
    if (a3)                 
    {                   
    LODWORD(v6) = sub_55A920(*(_DWORD *)(a1 + 208));       
    if (!sub_53ADD0(              
       v5,                
       v6,                
       v4,                
       (int)&v10))              
    {                   
     v7 = sub_4EC240(v4);             
     sub_4E3ED0(               
      1,                 
      "Cannot find tag [%s]\n",   
      v7);                
    }                   
    }                   
    else                   
    {                   
    sub_572BE0();                
    *(float *)&v10 = *(float *)(v5 + 20) + v20;        
    v11 = *(float *)(v5 + 24) + v21;           
    v12 = *(float *)(v5 + 28) + v22;           
    }                   
    v8 = dword_8FF12C;               
    v13 = flt_96A218;               
    v14 = flt_96A21C;               
    v15 = flt_96A220;               
    if (dword_8FF12C == 2047)             
    v8 = dword_8FF1D0;              
    sub_462250(                 
    &v23,                  
    &v13,                  
    &v10,                  
    &unk_82D6A0,                
    v8,                  
    8400899);                 
    if (1.0 == v23                
    || (unsigned __int16)sub_492C50(&v23) == *(_DWORD *)(v5 + 208)    
    || *(_UNKNOWN **)(v5 + 364) == &unk_FFFFFF         
    && (v16 = v13                
      + (*(float *)&v10 - v13)           
      * v23,                
     v17 = (v11 - v14) * v23 + v14,           
     v18 = v23 * (v12 - v15) + v15,           
     sub_4C35B0(               
      &v16,                
      v5 + 20,               
      v5 + 32,               
      &v19),                
     sub_432850(               
      *(_DWORD *)(v5 + 348),            
      &v19)))               
    result = sub_550250(a4, &v13, &v10);          
    else                   
    result = 0;                
    return result;                
} 

的ASM是probaly错误的,会是这样的接近?

// Don't know what params goes where, ie: where the Vec3 goes and where the object goes 
int __stdcall func_hook(param1, param2, param3, param4); 

// Where to put the address? -->> 0x572EA0 

// char __usercall sub_572EA0<al>(int a1<ecx>, int a2<edx>, int a3<eax>, int a4); 
__declspec(naked) void func_hook() 
{__asm{ 
    push ebp 
    mov ebp, esp 
    mov ecx param1 
    mov edx param2 
    mov eax param3 
    push param4 
    call func_hook 
    leave 
    ret 
}} 

这段代码中缺少的一件事是usercall(0x572EA0)的地址。不知道在哪里...


这是程序如何调用该函数。呼叫是在底部: http://i43.tinypic.com/2mez9c8.jpg

+0

你能调试exe,看看目标程序如何调用函数吗? '__usercall'通常意味着函数被编译器优化,它不遵循标准函数调用约定。 – user685684 2012-01-12 09:52:31

+0

@ user685684添加了屏幕截图。我不确定复制哪一部分。对__userfunction的调用发生在屏幕截图的底部(用红色边框标记)。 – w00 2012-01-12 10:16:23

+1

我的意思是,你可以尝试观察那些注册者的价值(通过使用调试器或者只是在钩子函数中打印它们),并猜测它们的含义。 – user685684 2012-01-12 11:29:03

回答

2

该功能,您的挂钩是Borland __fastcall,不__usercall(其实实际上没有这样的惯例,它只是IDA版的“未知公约”的)。

与内联汇编,ECXEDXEAX是临时寄存器,所以我们并不需要保留它们,呼叫以及foermed所以我们并不需要担心栈挂钩这方面:

static DWORD the_hook_address = 0x572EA0; 
//init this somewhere with the correct (Base + RVA) address in case of module relocation (from ASLR etc.) 
__declspec(naked) bool __stdcall the_hook(int a1, int a2, int a3, int a3) 
{ 
    __asm 
    { 
     MOV ECX,[ESP + 4]//a1 
     MOV EDX,[ESP + 8]//a2 
     MOV EAX,[ESP + 12]//a3 
     PUSH [ESP + 16]//a4 
     CALL the_hook_address 
     RETN 16 //4 * 4 args 
    } 
} 

我知道该功能需要一个对象作为参数和*如Vector3类型参数 其中所计算出的值将被存储。有没有一个简单的方法来告诉哪个参数会是什么?

的“easyness”取决于你的逆向工程,并与你REing程序的经验,在这种情况下,我会说其a1,因为你可以看到它移动到一个临时的,然后使用访问指针表示法(IDA表示未知结构的方式)来提取出大多数应用程序用于向量组件(以及大多数向量具有3个组件)的通用标记。如果你实际上可以调试调用的行为,看看有什么params是指针,看看函数调用的网站等等,那么它也会有很大的帮助。因此,我更喜欢使用ollydbg作为RE,并用IDA执行流程图补充它,以便进行棘手的跳转序列(想想20+ goto s在函数中:<)

+0

感谢您的解释,它真的帮助我! – w00 2012-01-12 12:34:21