2012-01-12 42 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