guix Posted February 14, 2013 Share Posted February 14, 2013 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
Jusonex Posted February 14, 2013 Share Posted February 14, 2013 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
guix Posted February 14, 2013 Author Share Posted February 14, 2013 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 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
Jusonex Posted February 14, 2013 Share Posted February 14, 2013 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
Recommended Posts