2012-01-12 3 views
0

Я разобрал исполняемый файл с IDA pro. Моя цель - подключить функцию __usercall. Я знаю, что мне нужно обернуть __usercall с помощью inine asm в моем коде на C++, так как я не могу typedef thefunction. Но я просто не знаю, как это работает.Захват usercall с inline asm

Я знаю, что функция принимает объект как параметр и a * 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;                
} 

АНМ является 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

+0

@ user685684 Добавлен снимок экрана. Я не был уверен, какую часть копировать. Вызов функции __user происходит в нижней части скриншота (отмечен красной рамкой). – w00

+1

Что я имею в виду, так это то, что вы можете попытаться посмотреть ценность этих реестров (используя отладчик или просто распечатать их в функции hook) и угадать их смысл. – user685684

ответ

2

, что функции, которые вы подключаете это Borland __fastcall, не __usercall (на самом деле не существует на самом деле нет такой конвенции, ее просто версия IDA о «неизвестной конвенции»).

С точки зрения подключения этого встраиваемого ассемблере, ECX, EDX и EAX являются регистры нуля, поэтому нам не нужно, чтобы сохранить их, и вызов хорошо 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 float s, что обычно используется большинством приложений для векторных компонентов (а также большинство векторов имеют 3 компонента). Это также очень помогает, если вы действительно можете отлаживать вызов в действии, посмотреть, какие параметры являются указателями, посмотреть на сайты вызовов функций и т. Д. По этой причине я предпочитаю использовать ollydbg для RE, дополняя его графиками потока выполнения IDA для сложного перехода (думаю, 20+ goto s в функции: <)

+0

Спасибо за объяснение, это действительно помогло мне! – w00

Смежные вопросы