packet monitoring menu

Shout-Out

User Tag List

Page 1 of 2 12 LastLast
Results 1 to 15 of 18
  1. #1
    lanman92's Avatar Active Member
    Reputation
    50
    Join Date
    Mar 2007
    Posts
    1,033
    Thanks G/R
    0/1
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    packet monitoring

    I've been looking at WoW's packets that it sends when I move. I've been comparing the data to the opcodes in the MangOS source code. I haven't seen any of the opcodes pointed to by the parameter. Any help here?

    packet monitoring
  2. #2
    Shynd's Avatar Contributor
    Reputation
    97
    Join Date
    May 2008
    Posts
    393
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    What method are you using to monitor packets?

  3. #3
    lanman92's Avatar Active Member
    Reputation
    50
    Join Date
    Mar 2007
    Posts
    1,033
    Thanks G/R
    0/1
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Not really much right now, I was just putting a bp in my detoured SendPacket function.

    EDIT: Ok, in the SendPacket() function, what is the data stored as? I know that kynox uses a certain class for his packet, CDataStore or something like that... I'm gonna start logging the packets and see if I can see anything different.
    Last edited by lanman92; 12-14-2008 at 04:19 PM.

  4. #4
    Cypher's Avatar Kynox's Sister's Pimp
    Reputation
    1358
    Join Date
    Apr 2006
    Posts
    5,368
    Thanks G/R
    0/6
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Headers are encrypted afaik, you sure you're not looking at the encrypted header for the opcode?

    If you hook the SendPacket and ProcessPacket functions you can avoid the encryption and dump out all the information you want (or modify it at will).

  5. #5
    lanman92's Avatar Active Member
    Reputation
    50
    Join Date
    Mar 2007
    Posts
    1,033
    Thanks G/R
    0/1
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    The address I'm detouring is 0x005843A0. I'm not sure if this is encrypted or not. In the case that it's not, where is the opcode located? I'd imagine it being right at the top...

  6. #6
    Nesox's Avatar ★ Elder ★
    Reputation
    1280
    Join Date
    Mar 2007
    Posts
    1,238
    Thanks G/R
    0/3
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    https://svn.sourceforge.net/svnroot/...game/Opcodes.h
    not sure where it's located but it shoud be in the start segments i guess

  7. #7
    lanman92's Avatar Active Member
    Reputation
    50
    Join Date
    Mar 2007
    Posts
    1,033
    Thanks G/R
    0/1
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I have the whole thing downloaded on my PC :P I'm about to give this another go with logging and hoping I find it eventually. For all I know right now, I could be looking at pretty little ENCRYPTED packets...

    EDIT: What logging lib do you guys use for VC++? I've googled but all I came up with is log4cxx, which appears to be for gcc.
    Last edited by lanman92; 12-15-2008 at 10:43 AM.

  8. #8
    Cypher's Avatar Kynox's Sister's Pimp
    Reputation
    1358
    Join Date
    Apr 2006
    Posts
    5,368
    Thanks G/R
    0/6
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Mangos/Ascent/Wcell/etc all detail the structures of packets (obviously they have to). I suggest checking them out.

    Logging lib? I just log info to a text file using the STL... I don't know why you need to download a 3rd party library just to log crap. Fstream ftw.

  9. #9
    BoogieManTM's Avatar Active Member
    Reputation
    52
    Join Date
    May 2008
    Posts
    193
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    The packet headers are indeed scrambled. They're xor'd with a key obtained by the SRP authentication. The key is 20 bytes long (Not sure where you'd find it in the client). Sent packets headers (Client->Server, AKA CMSG in emulators) are 6 bytes long, with a uint16 size, and uint32 opcode. Received messages (Server->Client, aka SMSG) are only 2 bytes, with just the opcode.

    Here's a C# sniplet of my class to handle this encryption.

    Code:
    /// <summary>
    	/// This class handles the encryption that is done on the headers of world server packets.
    	/// The Key is 20 bytes long
    	/// </summary>
    	public class WoWCrypt
    	{
    
            public class PacketKeyGenerator
            {
                static readonly byte[] SeedKey = { 0x38, 0xA7, 0x83, 0x15, 0xF8, 0x92, 0x25, 0x30, 0x71, 0x98, 0x67, 0xB1, 0x8C, 0x4, 0xE2, 0xAA };
    
                public static byte[] GenerateKey(byte[] sessionKey)
                {
                    byte[] firstBuffer = new byte[64];
                    byte[] secondBuffer = new byte[64];
    
                    memset(firstBuffer, 0x36);
                    memset(secondBuffer, 0x5C);
    
                    for (int i = 0; i < SeedKey.Length; i++)
                    {
                        firstBuffer[i] = (byte)(SeedKey[i] ^ firstBuffer[i]);
                        secondBuffer[i] = (byte)(SeedKey[i] ^ secondBuffer[i]);
                    }
    
                    Sha1Hash sha = new Sha1Hash();
    
                    sha.Update(firstBuffer);
                    sha.Update(sessionKey);
    
                    byte[] tempDigest = sha.Final();
    
                    sha = new Sha1Hash();
    
                    sha.Update(secondBuffer);
                    sha.Update(tempDigest);
    
                    byte[] finalKey = sha.Final();
    
                    return finalKey;
                }
    
                private static void memset(byte[] buffer, byte value)
                {
                    for (int i = 0; i < buffer.Length; i++)
                    {
                        buffer[i] = value;
                    }
                }
            }
    		private bool mInitialised = false;
    		
    		// Encryption state
    		private byte mEncPrev;
    		public int mEncIndex;
    		// Decryption state
    		public byte mDecPrev; 
    		public int mDecIndex;
    
    		public byte[] mKey;
    
    		public void Init(byte[] Key)
    		{
                mKey = PacketKeyGenerator.GenerateKey(Key);
    			mInitialised = true;
    		}
            public byte GetDecPrev()
            {
                return mDecPrev;
            }
            public void SetDecPrev(byte SetTo)
            {
                mDecPrev = SetTo;
            }
            public int GetDecIndex()
            {
                return mDecIndex;
            }
            public void SetDecIndex(int SetTo)
            {
                mDecIndex = SetTo;
            }
    		public void Decrypt(byte[] Data, int Length)
    		{
    			if (mInitialised == false) return;
    
    			for(int i = 0; i < Length; ++i)
    			{
    				byte x = (byte)((Data[i] - mDecPrev) ^ mKey[mDecIndex]);
    				++mDecIndex;
    				mDecIndex %= mKey.Length;
    				mDecPrev = Data[i];
    				Data[i] = x;
    			}
    		}
    
    		public void Encrypt(byte[] Data, int Length)
    		{
    			if (mInitialised == false) return;
    			
    			for(int i = 0; i < Length; ++i)
    			{
    				byte x = (byte)((Data[i] ^ mKey[mEncIndex]) + mEncPrev);
    				++mEncIndex;
    				mEncIndex %= mKey.Length;
    				mEncPrev = x;
    				Data[i] = x;
    			}			
    		}
    	}
    and the C++ version

    Code:
    class WowCrypt {
    public:
        WowCrypt(const unsigned int send, const unsigned int recv);
        ~WowCrypt();
    
        const unsigned int CRYPTED_SEND_LEN;
        const unsigned int CRYPTED_RECV_LEN;
    
        void Init();
    
        void SetKey(uint8 *, size_t);
    	void GenKey(uint8 *, size_t, uint8 *);
    
        void DecryptRecv(uint8 *, size_t);
        void EncryptSend(uint8 *, size_t);
    
        bool IsInitialized() { return _initialized; }
    
    private:
        std::vector<uint8> _key;
        uint8 _send_i, _send_j, _recv_i, _recv_j;
        bool _initialized;
    };
    
    #include <algorithm>
    
    WowCrypt::WowCrypt(const unsigned int send, const unsigned int recv) : CRYPTED_SEND_LEN(send), CRYPTED_RECV_LEN(recv)
    {
        _initialized = false;
    }
    
    void WowCrypt::Init()
    {
        _send_i = _send_j = _recv_i = _recv_j = 0;
        _initialized = true;
    }
    
    void WowCrypt::DecryptRecv(uint8 *data, size_t len)
    {
        if (!_initialized) return;
        if (len < CRYPTED_RECV_LEN) return;
    
        for (size_t t = 0; t < CRYPTED_RECV_LEN; t++) {
            _recv_i %= _key.size();
            uint8 x = (data[t] - _recv_j) ^ _key[_recv_i];
            ++_recv_i;
            _recv_j = data[t];
            data[t] = x;
        }
    }
    
    void WowCrypt::EncryptSend(uint8 *data, size_t len)
    {
        if (!_initialized) return;
        if (len < CRYPTED_SEND_LEN) return;
    
        for (size_t t = 0; t < CRYPTED_SEND_LEN; t++) {
            _send_i %= _key.size();
            uint8 x = (data[t] ^ _key[_send_i]) + _send_j;
            ++_send_i;
            data[t] = _send_j = x;
        }
    }
    
    void WowCrypt::SetKey(uint8 *key, size_t len)
    {
        _key.resize(len);
        std::copy(key, key + len, _key.begin());
    }
    
    WowCrypt::~WowCrypt()
    {
    }
    [edit]

    I've been thinking of doing a brute-forcer to brute force the key (fairly simple to do) on pcap's of wow's tcp stream. but that is another method of obtaining the encryption key without touching the client memory (but for you guys, whats the fun in that?). For example, capturing 20 or so ping packets (because they're sequential and easy to identify) would be sufficient data to brute the key. much like how WEP bruter's work.
    Last edited by BoogieManTM; 12-15-2008 at 02:02 PM.

  10. #10
    lanman92's Avatar Active Member
    Reputation
    50
    Join Date
    Mar 2007
    Posts
    1,033
    Thanks G/R
    0/1
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Ok, so I'm awfully confused. I'm detouring at 0x005843A0, is that even the correct address? I have it logging the value of the parameter and address everytime that it gets called, but it only logs once each time I log into WoW and inject... Here's my code.

    Code:
     
    void __declspec(naked) __stdcall SendPacket(DWORD *pDataStore)
    {
            __asm pushad;
            addLog(pDataStore);
            __asm popad;
            __asm jmp orig_SendPacket;
            __asm retn;
    }
    void __stdcall addLog(DWORD *pDataStore)
    {
            fstream fs;
            if(!opened)
            {
                    fs.open("C:\\Users\\Nick\\Documents\\wowlog.txt", ios::out | ios::app | ios::in);
                    opened = true;
            }
            DWORD data = *pDataStore;
            fs << data << endl;
            fs << pDataStore << endl;
            return;
    }
    Last edited by lanman92; 12-15-2008 at 04:46 PM.

  11. #11
    Cypher's Avatar Kynox's Sister's Pimp
    Reputation
    1358
    Join Date
    Apr 2006
    Posts
    5,368
    Thanks G/R
    0/6
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by BoogieManTM View Post
    The packet headers are indeed scrambled. They're xor'd with a key obtained by the SRP authentication. The key is 20 bytes long (Not sure where you'd find it in the client). Sent packets headers (Client->Server, AKA CMSG in emulators) are 6 bytes long, with a uint16 size, and uint32 opcode. Received messages (Server->Client, aka SMSG) are only 2 bytes, with just the opcode.

    Here's a C# sniplet of my class to handle this encryption.

    Code:
    /// <summary>
    	/// This class handles the encryption that is done on the headers of world server packets.
    	/// The Key is 20 bytes long
    	/// </summary>
    	public class WoWCrypt
    	{
    
            public class PacketKeyGenerator
            {
                static readonly byte[] SeedKey = { 0x38, 0xA7, 0x83, 0x15, 0xF8, 0x92, 0x25, 0x30, 0x71, 0x98, 0x67, 0xB1, 0x8C, 0x4, 0xE2, 0xAA };
    
                public static byte[] GenerateKey(byte[] sessionKey)
                {
                    byte[] firstBuffer = new byte[64];
                    byte[] secondBuffer = new byte[64];
    
                    memset(firstBuffer, 0x36);
                    memset(secondBuffer, 0x5C);
    
                    for (int i = 0; i < SeedKey.Length; i++)
                    {
                        firstBuffer[i] = (byte)(SeedKey[i] ^ firstBuffer[i]);
                        secondBuffer[i] = (byte)(SeedKey[i] ^ secondBuffer[i]);
                    }
    
                    Sha1Hash sha = new Sha1Hash();
    
                    sha.Update(firstBuffer);
                    sha.Update(sessionKey);
    
                    byte[] tempDigest = sha.Final();
    
                    sha = new Sha1Hash();
    
                    sha.Update(secondBuffer);
                    sha.Update(tempDigest);
    
                    byte[] finalKey = sha.Final();
    
                    return finalKey;
                }
    
                private static void memset(byte[] buffer, byte value)
                {
                    for (int i = 0; i < buffer.Length; i++)
                    {
                        buffer[i] = value;
                    }
                }
            }
    		private bool mInitialised = false;
    		
    		// Encryption state
    		private byte mEncPrev;
    		public int mEncIndex;
    		// Decryption state
    		public byte mDecPrev; 
    		public int mDecIndex;
    
    		public byte[] mKey;
    
    		public void Init(byte[] Key)
    		{
                mKey = PacketKeyGenerator.GenerateKey(Key);
    			mInitialised = true;
    		}
            public byte GetDecPrev()
            {
                return mDecPrev;
            }
            public void SetDecPrev(byte SetTo)
            {
                mDecPrev = SetTo;
            }
            public int GetDecIndex()
            {
                return mDecIndex;
            }
            public void SetDecIndex(int SetTo)
            {
                mDecIndex = SetTo;
            }
    		public void Decrypt(byte[] Data, int Length)
    		{
    			if (mInitialised == false) return;
    
    			for(int i = 0; i < Length; ++i)
    			{
    				byte x = (byte)((Data[i] - mDecPrev) ^ mKey[mDecIndex]);
    				++mDecIndex;
    				mDecIndex %= mKey.Length;
    				mDecPrev = Data[i];
    				Data[i] = x;
    			}
    		}
    
    		public void Encrypt(byte[] Data, int Length)
    		{
    			if (mInitialised == false) return;
    			
    			for(int i = 0; i < Length; ++i)
    			{
    				byte x = (byte)((Data[i] ^ mKey[mEncIndex]) + mEncPrev);
    				++mEncIndex;
    				mEncIndex %= mKey.Length;
    				mEncPrev = x;
    				Data[i] = x;
    			}			
    		}
    	}
    and the C++ version

    Code:
    class WowCrypt {
    public:
        WowCrypt(const unsigned int send, const unsigned int recv);
        ~WowCrypt();
    
        const unsigned int CRYPTED_SEND_LEN;
        const unsigned int CRYPTED_RECV_LEN;
    
        void Init();
    
        void SetKey(uint8 *, size_t);
    	void GenKey(uint8 *, size_t, uint8 *);
    
        void DecryptRecv(uint8 *, size_t);
        void EncryptSend(uint8 *, size_t);
    
        bool IsInitialized() { return _initialized; }
    
    private:
        std::vector<uint8> _key;
        uint8 _send_i, _send_j, _recv_i, _recv_j;
        bool _initialized;
    };
    
    #include <algorithm>
    
    WowCrypt::WowCrypt(const unsigned int send, const unsigned int recv) : CRYPTED_SEND_LEN(send), CRYPTED_RECV_LEN(recv)
    {
        _initialized = false;
    }
    
    void WowCrypt::Init()
    {
        _send_i = _send_j = _recv_i = _recv_j = 0;
        _initialized = true;
    }
    
    void WowCrypt::DecryptRecv(uint8 *data, size_t len)
    {
        if (!_initialized) return;
        if (len < CRYPTED_RECV_LEN) return;
    
        for (size_t t = 0; t < CRYPTED_RECV_LEN; t++) {
            _recv_i %= _key.size();
            uint8 x = (data[t] - _recv_j) ^ _key[_recv_i];
            ++_recv_i;
            _recv_j = data[t];
            data[t] = x;
        }
    }
    
    void WowCrypt::EncryptSend(uint8 *data, size_t len)
    {
        if (!_initialized) return;
        if (len < CRYPTED_SEND_LEN) return;
    
        for (size_t t = 0; t < CRYPTED_SEND_LEN; t++) {
            _send_i %= _key.size();
            uint8 x = (data[t] ^ _key[_send_i]) + _send_j;
            ++_send_i;
            data[t] = _send_j = x;
        }
    }
    
    void WowCrypt::SetKey(uint8 *key, size_t len)
    {
        _key.resize(len);
        std::copy(key, key + len, _key.begin());
    }
    
    WowCrypt::~WowCrypt()
    {
    }
    [edit]

    I've been thinking of doing a brute-forcer to brute force the key (fairly simple to do) on pcap's of wow's tcp stream. but that is another method of obtaining the encryption key without touching the client memory (but for you guys, whats the fun in that?). For example, capturing 20 or so ping packets (because they're sequential and easy to identify) would be sufficient data to brute the key. much like how WEP bruter's work.

    Omgawd its boogie!!1111oneoneone

    Sup?

    PS. Isn't the key stored in the CNetClient class or something? I can't recall.

  12. #12
    BoogieManTM's Avatar Active Member
    Reputation
    52
    Join Date
    May 2008
    Posts
    193
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by Cypher View Post

    Omgawd its boogie!!1111oneoneone

    Sup?

    PS. Isn't the key stored in the CNetClient class or something? I can't recall.
    yo yo, same shit diff day. I see you're having fun with the newbs 'round here, lol! some pretty entertaining reads.


    I wouldn't be surprised if it was in CNetClient, it would be a fitting place for it.. but as I do all the key generation myself, I never had to fiddle around with how the client deals with it much. Either way, grabbing it from memory, or just brute forcing the damn thing (a few proxies have implemented this method before), its fairly straight forward get around the header encryption.

  13. #13
    kynox's Avatar Member
    Reputation
    830
    Join Date
    Dec 2006
    Posts
    888
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I wouldn't be surprised if it was in CNetClient, it would be a fitting place for it.. but as I do all the key generation myself, I never had to fiddle around with how the client deals with it much. Either way, grabbing it from memory, or just brute forcing the damn thing (a few proxies have implemented this method before), its fairly straight forward get around the header encryption.
    Tis stored in CNetClient indeed. But if this guy can't even detour a function, i hardly see this helping him.

    PS: HAI BOOGIE

  14. #14
    Xeta's Avatar Member
    Reputation
    7
    Join Date
    Mar 2007
    Posts
    4
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Just wanted to add a bit more info

    BoogieMan, you can replace the C# PacketGenerator class with 1 line:
    byte[] mKey = new System.Security.Cryptography.HMACSHA1(EncryptionSeed).ComputeHash(SessionKey);

    The key generation is just HMAC sha1 seeded with those 16 static bytes.

    Also, packets can have either 2 or 3 bytes in the header for the size field, depending on how big the packet is. If the packet is over 32767 bytes, 3 bytes are used, and the first byte is OR'd with 0x80 as a marker

    if (size > 32767)
    {
    packetHeader[0] = ((size >> 16) & 0xFF) | 0x80;
    packetHeader[1] = (size >> & 0xFF;
    packetHeader[2] = size & 0xFF;
    }
    else
    {
    packetHeader[0] = (size >> & 0xFF;
    packetHeader[1] = size & 0xFF;
    }

    This goes for both server-sent and client-sent packets

    Now for some offsets
    At (ClientConnection + 0x27E4) is a pointer to the class that handles the actual communication with the server. I just called this WoWConnection, but it could be the CNetClient

    struct WoWConnection
    {
    int field_0;
    SOCKET Socket;
    int field_8;
    int field_C;
    int field_10;
    ClientConnection* ClientConnectionPtr;
    int field_18;
    char *InputBuffer;
    int InputBufferPosition;
    int InputBufferSize;
    int field_28[27];
    struct _RTL_CRITICAL_SECTION CS_field_94;
    int field_AC;
    int ProcessingThreadId;
    ClientConnection* SavedClientConnectionContext;
    int field_B8[9];
    WDSNode PacketQueue;// 0xDC - 0xE8
    struct _RTL_CRITICAL_SECTION CS_field_E8;
    int field_100[6];
    char IsEncryptionInitialized;// 0x118
    char EncKeyIndex;
    char EncKeyPrevious;
    char ClientOpcodeLen; // always 4
    char DecKeyIndex;
    char DecKeyPrevious;
    char ServerOpcodeLen; // always 2
    char EncryptionKey[20]; // 0x11F - 0x133 this is whats used to encrypt packets
    }

    Now if you need the full 40byte sessionkey for some reason, its at ClientConnection+0x288.
    The client still keeps this because its used to seed warden modules and hashed in one of the bot packets, but thats another matter

    And if you want to see the CDataStore class for the packets, go to https://starfish.westmont.edu/viewcv...tarblabIT/src/ and check out datastore.cpp/h. Its looks to be the exact same as what the client uses, based on some of the function names in the asserts of the ptr clients

    -Ralek

    Still waiting on my new account to activate, been a few days now. Had to grab this old one from way back

  15. #15
    kynox's Avatar Member
    Reputation
    830
    Join Date
    Dec 2006
    Posts
    888
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    About time we had someone with sense post in these forums. Welcome!

Page 1 of 2 12 LastLast

Similar Threads

  1. Packet Injecting Items
    By yungen2003 in forum World of Warcraft General
    Replies: 7
    Last Post: 08-07-2007, 07:02 AM
  2. WoW packets.. where are they?
    By Stretch in forum World of Warcraft General
    Replies: 0
    Last Post: 01-28-2007, 01:54 PM
  3. Baby Monitor with WOWglider
    By raunchy in forum World of Warcraft Bots and Programs
    Replies: 3
    Last Post: 10-28-2006, 10:50 AM
  4. Monitor Your glider
    By LightWave in forum World of Warcraft Bots and Programs
    Replies: 6
    Last Post: 07-15-2006, 11:43 PM
All times are GMT -5. The time now is 08:57 PM. 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