[Question] Detouring and calling SendPacket C++ menu

Shout-Out

User Tag List

Page 1 of 2 12 LastLast
Results 1 to 15 of 21
  1. #1
    Azzie2k8's Avatar Member
    Reputation
    11
    Join Date
    Apr 2009
    Posts
    190
    Thanks G/R
    0/0
    Trade Feedback
    1 (100%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    [Question] Detouring and calling SendPacket C++

    So, I am currently trying to detour SendPacket for obvious reasons. So far I have been able to get the detour working. The Problem is actually when calling the original SendPacket function ( throws an access_violation error at 0x538 ).
    I am assuming that this error is caused by either a wrong argument passed to that function or a false calling convention.

    Now the issue I had was that SendPacket has the thiscall convention, meaning that I cannot simply detour it since i cannot declare my function as thiscall as well. So if I understood it right then the thiscall basicly stores the This pointer within ecx but the rest of the parameters (pointer to the CDataStore Object) is passed as usual.

    This is why I declared my function as stdcall (basicly default but wth) and just saved the ecx register as you can see.

    Now if the DataStore pointer is actually valid (it seems that way) I have to assume that the error is caused by my calling convention. The only way I could think of is declaring my function as declspec(naked) meaning i will have to write my own prolog and epilog.

    But before doing that I wanted to ask if someone knows why this is hapenning and whether my thoughts are correct. I am sorry if I broke any rules but as far as I can tell I did alot of research and am just asking a question. Comparing to some of the other threads this seems to be okay to post.

    Code:
    typedef void (__thiscall *SendPacket_t)(void*);
    
    void __stdcall My_SendPacket(void*);
    
    void* pSendPacket = reinterpret_cast<void*>(Base::Rebase(0x90670));
    
    SendPacket_t Real_SendPacket = (SendPacket_t)DetourFunction((PBYTE)pSendPacket,(PBYTE)My_SendPacket);
    
    void __stdcall My_SendPacket(void* Arg1)
    {
    	DWORD This;
    	__asm mov This, ecx;
    
    	Real_SendPacket(Arg1); // Access violation
    
    	__asm mov ecx, This;
    }
    Last edited by Azzie2k8; 12-30-2010 at 07:57 AM.

    [Question] Detouring and calling SendPacket C++
  2. #2
    andy012345's Avatar Active Member
    Reputation
    59
    Join Date
    Oct 2007
    Posts
    124
    Thanks G/R
    0/7
    Trade Feedback
    1 (100%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Detours includes sample code of putting a detour on a thiscall. Maybe you should start there.

  3. #3
    LordJZ's Avatar Member
    Reputation
    11
    Join Date
    Jan 2009
    Posts
    28
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    You can easily detour the function yourself:
    Code:
    void DetourSendPacket()
    {
    	int address = 0x490670; // this won't work with ASLR
    
    	DWORD dwProtect = PAGE_READWRITE;
    	VirtualProtect((void*)address, 5, dwProtect, &dwProtect);
    
    	*((char*)address) = 0xE9; // jump opcode
    	*((int*)(address+1)) = &SendPacketJump - address - 5;
    
    	VirtualProtect((void*)address, 5, dwProtect, &dwProtect);
    }
    Code:
    void __declspec(naked) SendPacketJump()
    {
    	__asm
    	{
    		// from original function, bytes 1-3
    		push	ebp
    		mov		ebp, esp
    
    		// call our function
    		mov		eax, [ebp+8]
    		push	eax
    		push	ecx
    		call	SendPacketHook
    
    		// from original function, bytes 4-5
    		push	ecx
    		push	ebx
    		jmp		0x490675 // this won't work with ASLR
    	}
    }
    Code:
    void __stdcall SendPacketHook(void* connection, void* dataStore)
    {
    	// do your stuff here
    }
    (I didn't test it)

  4. #4
    andy012345's Avatar Active Member
    Reputation
    59
    Join Date
    Oct 2007
    Posts
    124
    Thanks G/R
    0/7
    Trade Feedback
    1 (100%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    It's really easy to do this with detours.

    Code:
    class MyDetouredClass
    {
     void SomeFunction(int lolarg) {}
    };
    Then you just use say:
    DetourAttach((PVOID*)&memloc, (PVOID)(&(PVOID&)MyDetouredClass::SomeFunction));

  5. #5
    Azzie2k8's Avatar Member
    Reputation
    11
    Join Date
    Apr 2009
    Posts
    190
    Thanks G/R
    0/0
    Trade Feedback
    1 (100%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Thanks a lot +rep to both of you. Allthogh LordJZ I think your approach will lead to a loop if I dont break it within my Hook ?

  6. #6
    MaiN's Avatar Elite User
    Reputation
    335
    Join Date
    Sep 2006
    Posts
    1,047
    Thanks G/R
    0/10
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Also, you don't need to save the ECX register. Intel's ABI states that EAX, ECX and EDX do not need to be preserved within functions. You've already had your answer, but the problem was probably that the compiler was already overwriting the ECX register with some temporary values. You should have tried to declare it as naked.
    [16:15:41] Cypher: caus the CPU is a dick
    [16:16:07] kynox: CPU is mad
    [16:16:15] Cypher: CPU is all like
    [16:16:16] Cypher: whatever, i do what i want

  7. #7
    LordJZ's Avatar Member
    Reputation
    11
    Join Date
    Jan 2009
    Posts
    28
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by Azzie2k8 View Post
    Thanks a lot +rep to both of you. Allthogh LordJZ I think your approach will lead to a loop if I dont break it within my Hook ?
    No, because i do "jmp 0x490675".

  8. #8
    Azzie2k8's Avatar Member
    Reputation
    11
    Join Date
    Apr 2009
    Posts
    190
    Thanks G/R
    0/0
    Trade Feedback
    1 (100%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by LordJZ View Post
    No, because i do "jmp 0x490675".
    Ah got me there... I am sorry allthough this still causes a Access violation at 0x538 and I only changed the code a little. I currently have no more time for this for the next few hours since I am learning for school so maybe I should just take a look at it tomorrow. I just do not want you to do all the work for me. Dont get me wrong if you do then I am fine with it but I think you get my point Anyways Thanks a ton

    Code:
    void* pSendPacket = reinterpret_cast<void*>(Base::Rebase(0x90670));
    void* paSendPacket = reinterpret_cast<void*>(Base::Rebase(0x90675));
    
    void __stdcall SendPacketHook(void* connection, void* dataStore)
    {
    	// do your stuff here
    	MyLog->Add("Test",Debug);
    }
    
    void __declspec(naked) SendPacketJump()
    {
    	__asm
    	{
    		// from original function, bytes 1-3
    		push	ebp
    		mov		ebp, esp
    
    		// call our function
    		mov		eax, [ebp+8]
    		push	eax
    		push	ecx
    		call	SendPacketHook
    
    		// from original function, bytes 4-5
    		push	ecx
    		push	ebx
    		jmp		paSendPacket
    	}
    }
    
    
    void DetourSendPacket()
    {
    	int address = (int)pSendPacket; 
    
    	DWORD dwProtect = PAGE_READWRITE;
    	VirtualProtect((void*)address, 5, dwProtect, &dwProtect);
    
    	*((char*)address) = 0xE9; // jump opcode
    	*((int*)(address+1)) = (DWORD)(&SendPacketJump) - address - 5;
    
    	VirtualProtect((void*)address, 5, dwProtect, &dwProtect);
    }

  9. #9
    Azzie2k8's Avatar Member
    Reputation
    11
    Join Date
    Apr 2009
    Posts
    190
    Thanks G/R
    0/0
    Trade Feedback
    1 (100%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by MaiN View Post
    Also, you don't need to save the ECX register. Intel's ABI states that EAX, ECX and EDX do not need to be preserved within functions. You've already had your answer, but the problem was probably that the compiler was already overwriting the ECX register with some temporary values. You should have tried to declare it as naked.
    I tried both ways now. my old approach with the differences and the new one and both crash with the access violation at 0x538...I am kinda lost atm so if anyone wants to help please hit me with your knowledge wtf I am doing wrong

    I guess something in the asm code is a little wrong... allthough everything looks alright
    Last edited by Azzie2k8; 12-30-2010 at 04:22 PM.

  10. #10
    caytchen's Avatar Contributor
    Reputation
    138
    Join Date
    Apr 2007
    Posts
    162
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by Azzie2k8 View Post
    I tried both ways now. my old approach with the differences and the new one and both crash with the access violation at 0x538...I am kinda lost atm so if anyone wants to help please hit me with your knowledge wtf I am doing wrong

    I guess something in the asm code is a little wrong...
    Help yourself. Attach a debugger (I'd recommend ollydbg) and check if the original function is detoured correctly, if your trampoline is correct and if your actual hook is correctly jumped to. And most important, single stepping will make the culprit very clear to you.

    I have not looked in your code that much, but your trampoline and detour function aren't general - that is, they work for this specific function, but thats it. Also, 0x538 is afaik the offset to the connection state (edit: its 0x55C, so ignore that, but the thing about ECX still applies) - and that is usually checked at the very beginning of the networking functions. So your problem most likely is that by the time your hook returns to the original function, ECX was modified, which is a perfectly valid thing for the compiler to do since your hook is __stdcall (and he doesn't know about your inline asm, anyway). So either extend your trampoline to preserve ECX correctly or try and reset it in your hook with some more ugly inline assembler and hope the compiler won't tack any stack cookie or other crap on to the end. Point being, circumventing your compiler rarely helps you.
    Last edited by caytchen; 12-30-2010 at 04:38 PM.

  11. #11
    Azzie2k8's Avatar Member
    Reputation
    11
    Join Date
    Apr 2009
    Posts
    190
    Thanks G/R
    0/0
    Trade Feedback
    1 (100%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by caytchen View Post
    Help yourself. Attach a debugger (I'd recommend ollydbg) and check if the original function is detoured correctly, if your trampoline is correct and if your actual hook is correctly jumped to. And most important, single stepping will make the culprit very clear to you.

    I have not looked in your code that much, but your trampoline and detour function aren't general - that is, they work for this specific function, but thats it. Also, 0x538 is afaik the offset to the connection state (edit: its 0x55C, so ignore that, but the thing about ECX still applies) - and that is usually checked at the very beginning of the networking functions. So your problem most likely is that by the time your hook returns to the original function, ECX was modified, which is a perfectly valid thing for the compiler to do since your hook is __stdcall (and he doesn't know about your inline asm, anyway). So either extend your trampoline to preserve ECX correctly or try and reset it in your hook with some more ugly inline assembler and hope the compiler won't tack any stack cookie or other crap on to the end. Point being, circumventing your compiler rarely helps you.
    You were right, ecx was changed...

    Here is the ugly inline assembler
    Code:
    void __declspec(naked) SendPacketJump()
    {
    	DWORD This;
    	__asm
    	{
    		// from original function, bytes 1-3
    		push	ebp
    			mov		ebp, esp
    			//preserve ecx
    			mov This, ecx
    			// call our function
    			mov		eax, [ebp+8]
    		push	eax
    			push	ecx
    			call	SendPacketHook
    
    			//restore ecx
    			mov ecx, This
    			// from original function, bytes 4-5
    			push	ecx
    			push	ebx
    			jmp		paSendPacket
    	}
    }
    Thanks a lot but I will try to find a cleaner approach. I think this might become an issue but I am not completely sure

  12. #12
    Azzie2k8's Avatar Member
    Reputation
    11
    Join Date
    Apr 2009
    Posts
    190
    Thanks G/R
    0/0
    Trade Feedback
    1 (100%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    So after this hook I tried to get the movement packets and with Robskes help i actually got somewhere but in general this data doesnt make any sense

    the movementPacket struct could look like this

    Code:
    struct MovementPacket
    {
    unsigned int opcode;
    unsigned __int64 guid;
    unsigned int Flags1;
    unsigned int Flags2;
    unsigned int time;
    float x;
    float y;
    float z;
    float orientation;
    bool optional;
    }
    but for some reasons I get for the Hearbeatpackets while running some strange values.

    for example the positions are not the same as the ones I am getting by the object manager.

    The guid seems different. z-coordinate is like -1100 facing never changes...what am i doing wrong ?

    Also the time is for some reason not in milliseconds...I am confused but maybe someone knows what is wrong...

    Edit: This is actually what I get as packets. As you can see at the time values there has to be something wrong-...

    Code:
    [Debug] Heartbeat
    [Debug] 17137666 // guid
    [Debug] 1966991488 //Flags1
    [Debug] 4292399361 //Flags2
    [Debug] 2809568836 //time
    [Debug] -2045.333496 //x converted to float from int
    [Debug] 318.669891 //y converted to float from int
    [Debug] 0.000063 //z converted to float from int
    [Debug] 0.000000 //orientation converted to float from int
    [Debug] false // optional
    [Debug] 
    [Debug] Heartbeat
    [Debug] 17137666
    [Debug] 1967119488
    [Debug] 1797377
    [Debug] 2813555781
    [Debug] -2079.616211
    [Debug] 318.669891
    [Debug] 0.000063
    [Debug] 0.000000
    [Debug] false
    [Debug] 
    [Debug] Heartbeat
    [Debug] 17137666
    [Debug] 1967247488
    [Debug] 4878849
    [Debug] 2817542469
    [Debug] -2111.866211
    [Debug] 318.669891
    [Debug] 0.000063
    [Debug] 0.000000
    [Debug] false
    [Debug] 
    [Debug] Heartbeat
    [Debug] 17137666
    [Debug] 1967375488
    [Debug] 7960321
    [Debug] 2821529413
    [Debug] -2143.505371
    [Debug] 318.669891
    [Debug] 0.000063
    [Debug] 0.000000
    [Debug] false
    [Debug] 
    [Debug] Heartbeat
    [Debug] 17137666
    [Debug] 1967503488
    [Debug] 11041793
    [Debug] 2825516101
    [Debug] 2090.715576
    [Debug] 318.669891
    [Debug] 0.000063
    [Debug] 0.000000
    [Debug] false
    Edit2: I have just been told that the guid isnt 8 bytes in the packets which changes alot...back to trying to make sense out of this data
    Last edited by Azzie2k8; 01-02-2011 at 12:44 PM.

  13. #13
    Flushie's Avatar Master Sergeant
    Reputation
    -13
    Join Date
    May 2010
    Posts
    72
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by LordJZ View Post
    You can easily detour the function yourself:
    Code:
    void DetourSendPacket()
    {
    	int address = 0x490670; // this won't work with ASLR
    
    	DWORD dwProtect = PAGE_READWRITE;
    	VirtualProtect((void*)address, 5, dwProtect, &dwProtect);
    
    	*((char*)address) = 0xE9; // jump opcode
    	*((int*)(address+1)) = &SendPacketJump - address - 5;
    
    	VirtualProtect((void*)address, 5, dwProtect, &dwProtect);
    }
    Code:
    void __declspec(naked) SendPacketJump()
    {
    	__asm
    	{
    		// from original function, bytes 1-3
    		push	ebp
    		mov		ebp, esp
    
    		// call our function
    		mov		eax, [ebp+8]
    		push	eax
    		push	ecx
    		call	SendPacketHook
    
    		// from original function, bytes 4-5
    		push	ecx
    		push	ebx
    		jmp		0x490675 // this won't work with ASLR
    	}
    }
    Code:
    void __stdcall SendPacketHook(void* connection, void* dataStore)
    {
    	// do your stuff here
    }
    (I didn't test it)
    Yeah you cant do that...

  14. #14
    Azzie2k8's Avatar Member
    Reputation
    11
    Join Date
    Apr 2009
    Posts
    190
    Thanks G/R
    0/0
    Trade Feedback
    1 (100%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by Flushie View Post
    Yeah you cant do that...
    That works so...

    Code:
    *((int*)(address+1)) = (DWORD)(&SendPacketJump) - address - 5;

  15. #15
    TOM_RUS's Avatar Legendary
    Reputation
    914
    Join Date
    May 2008
    Posts
    699
    Thanks G/R
    0/52
    Trade Feedback
    0 (0%)
    Mentioned
    1 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by Azzie2k8 View Post
    Edit2: I have just been told that the guid isnt 8 bytes in the packets which changes alot...back to trying to make sense out of this data
    flags2 is 2 bytes, not 4 and guid is packed.
    https://github.com/mangos/mangos/blo...e/Unit.cpp#L71

Page 1 of 2 12 LastLast

Similar Threads

  1. [Question] Noggit and me
    By Demonshade in forum WoW ME Questions and Requests
    Replies: 4
    Last Post: 12-03-2007, 07:22 PM
  2. [Question] sound and changable hair
    By ovre in forum WoW ME Questions and Requests
    Replies: 2
    Last Post: 10-07-2007, 06:37 PM
  3. Question: TOS and Model Changing
    By Sergioz in forum WoW ME Questions and Requests
    Replies: 1
    Last Post: 07-22-2007, 05:25 PM
  4. [Question] Action and change of race ?
    By Werteur in forum WoW ME Questions and Requests
    Replies: 0
    Last Post: 06-06-2007, 06:20 AM
All times are GMT -5. The time now is 10:09 AM. Powered by vBulletin® Version 4.2.3
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved. User Alert System provided by Advanced User Tagging (Pro) - vBulletin Mods & Addons Copyright © 2025 DragonByte Technologies Ltd.
Google Authenticator verification provided by Two-Factor Authentication (Free) - vBulletin Mods & Addons Copyright © 2025 DragonByte Technologies Ltd.
Digital Point modules: Sphinx-based search