Jump to content

Need a little ASM help


Recommended Posts

Hello,

I try to make a hook in CAutomobile::ProcessWheel (it's how I named sub_6AA290), however I can't make it work, it crash the game as soon as I join my server.

In IDA disassembly, the part I want to hook is this:

push    eax               ; f3   // 0x6AA666 
push    eax               ; f2   // 0x6AA667 
push    ecx               ; f1   // 0x6AA668 
lea     ecx, [esp+0F8h+m] ; this // 0x6AA669 
fstp    [esp+0F8h+var_F8]        // 0x6AA66D 
call    CMatrix__SetScales       // 0x6AA670 

CMatrix__SetScales is how I named sub_59AF00, the function prototype is (from what I understand):

int __thiscall CMatrix__SetScales( CMatrix *this, float f1, float f2, float f3 ) 

My goal actually, is to set custom values for f1, f2 and f3

So in \MTA10\multiplayer_sa\CMultiplayerSA.cpp, I did:

#define HOOKPOS_CAutomobile_ProcessWheel_Size 0x6AA666 
DWORD RETURN_CAutomobile_ProcessWheel_Size = 0x6AA669; 
  
void HOOK_CAutomobile_ProcessWheel_Size(); 
  
void CMultiplayerSA::InitHooks() 
{ 
    ... 
    // I'm not sure to understand the last parameter, 
    // I've set it to 1 because from what I understand, 
    // it must be the size of the instruction at the pos that is hooked. 
    // So "push eax" is only 1 byte (opcode 0x50)... but is this correct? 
    HookInstall ( HOOKPOS_CAutomobile_ProcessWheel_Size, (DWORD)HOOK_CAutomobile_ProcessWheel_Size, 1 ); 
    ... 
} 
  
float fTest; 
void _declspec(naked) HOOK_CAutomobile_ProcessWheel_Size() 
{ 
    fTest = 0.5f 
  
    _asm 
    { 
        // f3 
        push fTest 
  
        // f2 
        push fTest 
  
        // f1 
        push fTest 
  
        // useless in my case? 
        jmp RETURN_CAutomobile_ProcessWheel_Size 
    } 
} 

So as I said, it crash the game with this code.

I tried many different things, the best result I had was a flickering screen and the front-right wheel with width 0, and the 3 other wheels with weird width.

Please help a ASM beginner, tell me what is wrong in my code and if possible, how to fix it. Thanks :)

PS: Here is the crash infos:

  
Version = 1.4-custom.0.000 
Time = Thu Feb 14 13:12:14 2013 
Module =  
Code = 0xC0000005 
Offset = 0x4CF7F7BB 
  
EAX=3F800000  EBX=00B2C701  ECX=00B201D5  EDX=BF0CCCCE  ESI=155BD698 
EDI=00000003  EBP=00000004  ESP=0028FBFC  EIP=4CF7F7BB  FLG=00210297 
CS=0023   DS=002B  SS=002B  ES=002B   FS=0053  GS=002B 
  

Link to comment

The minimal size you have to pass to HookInstall is 5 (the jmp opcode has 5 bytes).

But push has only 2 bytes. In that case you could use a size of 6 bytes to hook/override all these pushs.

To find the length of an opcode and its arguments out, just click in IDA on the instruction you want to hook and select the assigned Hex-View. Finally the amount of selected blocks/bytes is the size of the opcode.

Link to comment
To find the length of an opcode and its arguments out, just click in IDA on the instruction you want to hook and select the assigned Hex-View. Finally the amount of selected blocks/bytes is the size of the opcode.

Yes, that's how I found that push eax's length was 1 byte. I don't understand why you say 2 bytes? And I tried to change that number to 3, 6, really anything between 1 and 10, it's still crashing :(

Also, by looking at other hooks in the same file, I see things like this in comments, for example:

  
HookInstall ( HOOKPOS_CEventVehicleDamageCollision_Bike, (DWORD)HOOK_CEventVehicleDamageCollision_Bike, 6 ); 
... 
void _declspec(naked) HOOK_CEventVehicleDamageCollision_Bike ( ) 
{ 
    // .006B8EC6 DC 1D F8 9E 85 00                       fcomp   ds:__real@0000000000000000 < Hook > 
    //  006B8ECC 8B F1  
  

Another example:

  
HookInstall(HOOKPOS_CPed_IsPlayer, (DWORD)HOOK_CPed_IsPlayer, 6); 
... 
void _declspec(naked) HOOK_CPed_IsPlayer () 
{ 
    /* 
    005DF8F0  mov         eax,dword ptr [ecx+598h]      <hook> 
    005DF8F6  test        eax,eax                       <return> 
    */ 
  

Which is why I think that number is the size of the first instruction at the hook position. I'm confused :S

I can successfully disable the wheels by doing:

  
#define HOOKPOS_CAutomobile_ProcessWheel_Size 0x6AA666 
DWORD RETURN_CAutomobile_ProcessWheel_Size = 0x6AA675; 
  
void _declspec(naked) HOOK_CAutomobile_ProcessWheel_Size() 
{ 
    _asm 
    { 
        jmp RETURN_CAutomobile_ProcessWheel_Size 
    } 
} 

But I can't find how to push those floats! I tried:

  
#define HOOKPOS_CAutomobile_ProcessWheels 0x6AA666 
DWORD RETURN_CAutomobile_ProcessWheels = 0x6AA669; 
  
float fTest1, fTest2, fTest3; 
  
void _declspec(naked) HOOK_CAutomobile_ProcessWheel_Size() 
{ 
    fTest1 = 0.5f; 
    fTest2 = 0.5f; 
    fTest3 = 0.5f; 
  
    _asm 
    { 
  
        mov    eax, offset fTest3 
        push   dword ptr [eax] 
        mov    eax, offset fTest2 
        push   dword ptr [eax] 
        mov    ecx, offset fTest1 
        push   dword ptr [ecx] 
  
        //mov    eax, fTest3 
        //push   [eax] 
        //mov    eax, fTest2 
        //push   [eax] 
        //mov    ecx, fTest1 
        //push   [ecx] 
  
        jmp RETURN_CAutomobile_ProcessWheel_Size 
    } 
} 

Amongst other things, but it always crash -_-... Can you tell me how to fix it please.

Link to comment
Yes, that's how I found that push eax's length was 1 byte.

You're right, my fail (selected wrong hex-view window). But that's not the problem. If you want to override all the stuff, just override these lea instruction, too. (See code snippet below)

The installation of the hook isn't the problem, if the size is higher than or equal to 5.

The problem is the expression fTest = 0.5f.

In assembly fTest = 0.5 looks like the following:

fld [address] // Load value from the given address to the floating point register st0 
fst(p) [destinationAddress] // Copies the value in st0 to the given address 

That's because we can't copy between addresses directly.

That means that the previous expression changes the value in st0. The solution is pushing all relevant registers to the stack and "pop" them back after execution of your code. The instructions pushad and popad push/pop all general cpu registers to the stack.

The following works for me.

    #define HOOKPOS_CAutomobile_ProcessWheel_Size 0x6AA666 
    DWORD RETURN_CAutomobile_ProcessWheel_Size = 0x6AA66D; 
      
    void HOOK_CAutomobile_ProcessWheel_Size(); 
      
    void CMultiplayerSA::InitHooks() 
    { 
        ... 
        HookInstall ( HOOKPOS_CAutomobile_ProcessWheel_Size, (DWORD)HOOK_CAutomobile_ProcessWheel_Size, 7 ); 
        ... 
    } 
      
    float fTest; 
    void _declspec(naked) HOOK_CAutomobile_ProcessWheel_Size() 
    { 
        _asm pushad 
        fTest = 0.5f; 
        _asm popad 
      
        _asm 
        { 
            // f3 
            push fTest 
      
            // f2 
            push fTest 
      
            // f1 
            push fTest 
             
            // Execute overriden instruction(s) 
            lea    ecx, [esp+0F8h-0A4h] 
  
            // Jump back to continue the normal control flow 
            jmp RETURN_CAutomobile_ProcessWheel_Size 
        } 
    } 

Link to comment
Guest
This topic is now closed to further replies.
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...