Sending Packets from WoW client menu

User Tag List

Results 1 to 5 of 5
  1. #1
    Dupheadss's Avatar Contributor CoreCoins Purchaser
    Reputation
    98
    Join Date
    Aug 2015
    Posts
    147
    Thanks G/R
    38/61
    Trade Feedback
    2 (100%)
    Mentioned
    1 Post(s)
    Tagged
    0 Thread(s)

    Sending Packets from WoW client

    I've finally managed to read all in-bound and out-bound packets from the client (3.4.5.xxx)



    While I've had fun dropping specific packets and seeing what effect it has on the client I figured it was time to try learn how to craft and send my own packets...

    My goal for the time being is to successfully send a CMSG_RANDOM_ROLL= 0x3657, and get a valid response in return.

    Code:
    	struct Packet {
    		void* VMT;
    		char _pad[0x18];
    
    		uint64_t Send() {
    			return ((uint64_t(*)(void*))(reinterpret_cast<__int64>(GetModuleHandle(nullptr)) + CLIENTSERVICES_SEND))((void*)this);
    	               	}
    	                       };
    
    #pragma  pack(0)
    	struct RandomRollPacket : Packet
    	{
    		int* rolls[2];
    		
    		RandomRollPacket(int min, int max)
    		{
    			this->VMT = (void*)(reinterpret_cast<__int64>(GetModuleHandle(nullptr)) + RANDOM_ROLL_PACKET_VMT);
    			this->rolls[0] = 0;
    			this->rolls[1] = 0;
    		}
    	};

    As you could likely make out from the code snippet . My attempt was to create the UserClientRandomRoll message and pass it through ClientServices::Send.

    This does in fact send the packet with the correct OP code as I can see it on my other hooked functions - However I suspect the packet is malformed as the server doesn't respond.

    It might be note worthy that if I pass rolls[0..1] = 0 (as in the above code) I do get a response from the server as if the player typed /roll 0 0 - however I've never managed to get any other response apart from that. If roll[0..1] is anything other than 0 the server simply doesn't respond regardless of how I attempt to structure the packet.


    I have dug around TC a bit in hopes of understanding this system a little better with mixed success :

    TC Random Roll


    I also attempted the CMSG_CHAT_MESSAGE_SAY = 0x37E7 but with even less success.


    At the moment I am hitting a bit of a wall, I suspect that either there is some sort of encryption that happens BEFORE ClientServices::Send is called and that is destroying the data in my packet or I am simply crafting the packets incorrectly.

    I think my next attempt will be to manually build out the CDatastore (I would really like to avoid this if possible) however I am still not sure how or where the client handles its packet encryption!

    Sending Packets from WoW client
  2. #2
    culino2's Avatar Elite User
    Reputation
    336
    Join Date
    Feb 2013
    Posts
    181
    Thanks G/R
    139/72
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Are you sure your _pad has the correct size? I don't have any access to my old sources at my current location, but iirc it was something like 0x10 where the packet data struct starts in x64 inside jam classes.
    It may have been changed over the years though.
    Last edited by culino2; 02-24-2024 at 09:44 PM.

  3. #3
    _chase's Avatar Established Member
    Reputation
    96
    Join Date
    Dec 2019
    Posts
    58
    Thanks G/R
    17/50
    Trade Feedback
    0 (0%)
    Mentioned
    5 Post(s)
    Tagged
    0 Thread(s)
    I investigated the Script_RandomRoll lua handler and came up with this.
    Your Random Roll packet looks to be 0x28 , while mine is 0x2C. Can you try with the structure I reversed?

    Also, I think you might just be hitting undefined behavior. Not an expert with c or c++ , but the structure field of "int* rolls[2];" makes no sense to me.
    Did you intend for a two capacity array of pointers? Or, is there some magic that auto creates an int array for you on struct initialization? Or isn't this just pointing to uninitialized memory???

    All from 3.4.3.52237 classic

    Code:
    00000000 RandomRollPacket struc ; (sizeof=0x2C, mappedto_562)
    00000000                                         ; XREF: Script_RandomRoll/r
    00000000 vmt             dq ?                    ; offset
    00000008 padding_0x18    db 16 dup(?)
    00000018 field_18        dd ?
    0000001C field_1C        dd ?
    00000020 field_20        dd ?
    00000024 minRoll         dd ?                    ; XREF: Script_RandomRoll+FB/w
    00000028 maxRoll         dd ?                    ; XREF: Script_RandomRoll+FF/w
    0000002C RandomRollPacket ends
    Code:
    __int64 __fastcall RandomRollPacket::Prepare(RandomRollPacket *rollPacket)
    {
      __int64 result; // rax
    
      rollPacket->field_18 = 0;
      rollPacket->vmt = (_QWORD **)sRollPacket::VMT;
      result = (__int64)rollPacket;
      BYTE1(rollPacket->field_20) = 0;
      return result;
    }
    Code:
    __int64 __fastcall Script_RandomRoll(__int64 luaState)
    {
      _BYTE *v2; // rax
      int v3; // esi
      int v4; // edi
      const char *v5; // rax
      int minRange; // edi
      _BYTE *v7; // rax
      const char *v8; // rax
      int maxRange; // eax
      int _maxRange; // ebx
      RandomRollPacket randomRollPacket; // [rsp+20h] [rbp-38h] BYREF
    
      if ( sub_2C4550() && sub_2C4550() )
      {
        v2 = (_BYTE *)sub_2C59E0(luaState, 1i64);
        v3 = 16;
        if ( !v2 || *v2 != 48 || (v4 = 16, ((v2[1] - 88) & 0xDF) != 0) )
          v4 = 10;
        v5 = (const char *)sub_2C59E0(luaState, 1i64);
        minRange = strtol(v5, 0i64, v4);
        v7 = (_BYTE *)sub_2C59E0(luaState, 2i64);
        if ( !v7 || *v7 != 0x30 || ((v7[1] - 88) & 0xDF) != 0 )
          v3 = 10;
        v8 = (const char *)sub_2C59E0(luaState, 2i64);
        maxRange = strtol(v8, 0i64, v3);
        _maxRange = maxRange;
        if ( minRange )
        {
          if ( minRange >= 0 )
            goto LABEL_15;
        }
        else if ( maxRange )
        {
    LABEL_15:
          if ( maxRange >= minRange && maxRange <= 1000000 )
          {
            RandomRollPacket::Prepare(&randomRollPacket);
            randomRollPacket.minRoll = minRange;
            randomRollPacket.maxRoll = _maxRange;
            ClientServices::SendPacket((__int64)&randomRollPacket);
          }
        }
        return 0i64;
      }
      lua::usageError(luaState, (__int64)"Usage: RandomRoll(\"max\") or RandomRoll(\"min\", \"max\")");
      return 0i64;
    }

  4. #4
    Dupheadss's Avatar Contributor CoreCoins Purchaser
    Reputation
    98
    Join Date
    Aug 2015
    Posts
    147
    Thanks G/R
    38/61
    Trade Feedback
    2 (100%)
    Mentioned
    1 Post(s)
    Tagged
    0 Thread(s)
    Thank you guys both for the replies the padding was correct my RandomRollPacket struct itself was incorrect :

    Code:
    	struct RandomRollPacket : Packet {	
    		 char unk_1 = 0x00;
    		 char unk_2 = 0x00;
    		 int Min;
    		 int Max;		
    		RandomRollPacket(int min, int max) : Min(124), Max(200) {
    			this->VMT = reinterpret_cast<void*>(reinterpret_cast<__int64>(GetModuleHandle(nullptr)) + RANDOM_ROLL_PACKET_VMT);			
    		}
    	};
    I can't say I fully understand why I needed to padd the Random packet with unk_1 & 2 but it got me there in end so I'll take it lol.

    @__chase

    I'd love to know how exactly you got to that RandomRoll structure I've tried generating my own in IDA but it just doesn't line up nicely at all...

  5. #5
    _chase's Avatar Established Member
    Reputation
    96
    Join Date
    Dec 2019
    Posts
    58
    Thanks G/R
    17/50
    Trade Feedback
    0 (0%)
    Mentioned
    5 Post(s)
    Tagged
    0 Thread(s)
    IDA will struggle to decompile most of the packet handler functions, because it only calls the packet's respective initialize function.
    IDA will attempt to decompile the function and auto define packet structure on the stack but it can only see as far as the initialization functions access, so IDA gets confused and gives you additional stack variables when really they are to be part of the packet structure. Undefine the incorrectly identified stack variables or extend the packet array and consume those variables then correctly define them. You can confirm packet structure by reversing any packet's VMT index 2 (method 3) . For Random Roll's vmt index 2 refer to below:


    Here's some insight into how i decided the size of the packet...
    Note the highest field access in the method... an unsigned int (4bytes) offset 0x28 into the packet, thus my packet must be (atleast) 0x28 + 0x04 = 0x2C.
    For more complex packet methods you will have to explore inner functions etc and make sure you're defining the structure properly.
    Lastly, you can xref the 'sub_2DB960' method and auto detect every packet's vmt initialization function. Just cross reference the second argument to TrinityCore's opcodes to tell what packet handler you're looking at.

    Code:
    char __fastcall sub_770600(__int64 packet, _DWORD *a2)
    {
      int v4; // ecx
      char v5; // al
      _DWORD *v7; // [rsp+20h] [rbp-18h] BYREF
      __int16 v8; // [rsp+28h] [rbp-10h]
    
      sub_2DB960(a2, 0x3657);
      v4 = *(unsigned __int8 *)(packet + 0x21);
      v5 = *(_BYTE *)(packet + 0x21);
      v7 = a2;
      v8 = 0;
      if ( v4 == (v5 & 1) )
      {
        LOBYTE(v8) = v4;
        HIBYTE(v8) = 1;
      }
      sub_6FEA90((__int64)&v7);
      sub_2DBA00(a2, *(unsigned int *)(packet + 0x24));
      sub_2DBA00(a2, *(unsigned int *)(packet + 0x28));
      if ( *(_BYTE *)(packet + 0x21) )
        sub_2DB8C0(a2, *(_BYTE *)(packet + 0x20));
      return 1;
    }

  6. Thanks Dupheadss, Razzue (2 members gave Thanks to _chase for this useful post)

Similar Threads

  1. [Tool] Sending mouse input to the WoW Client (specifically 2.4.3) with Windows API
    By sneakydick in forum World of Warcraft Bots and Programs
    Replies: 3
    Last Post: 01-28-2019, 11:06 AM
  2. [Guide] Sending Patches To The Client Through The WoW Application
    By stoneharry in forum WoW ME Tools & Guides
    Replies: 20
    Last Post: 09-01-2015, 06:44 AM
  3. Packet Tool for WoW client
    By Xecis in forum WoW Bots Questions & Requests
    Replies: 1
    Last Post: 10-17-2014, 07:38 PM
  4. sending packet to wow client
    By norowen in forum WoW Memory Editing
    Replies: 3
    Last Post: 02-02-2010, 05:50 PM
  5. Do you need to download a WoW client from eu to play on eu servers
    By Liquid Malfunction in forum World of Warcraft General
    Replies: 2
    Last Post: 10-11-2008, 12:58 PM
All times are GMT -5. The time now is 10:32 AM. Powered by vBulletin® Version 4.2.3
Copyright © 2024 vBulletin Solutions, Inc. All rights reserved. User Alert System provided by Advanced User Tagging (Pro) - vBulletin Mods & Addons Copyright © 2024 DragonByte Technologies Ltd.
Digital Point modules: Sphinx-based search