Thursday, 20 September 2012

Packet Analysis

You will want a way to sniff packets perhaps WPE Pro or wireshark, could use ollyDBG or code your own sniffer/logger.

And also a way to check out whats in the packets hex and do simple operations like XOR. I suggest 010 Hex Editor its amazing.

Packets are the things that hold data to be communicated between the server and client, or client too client(s).


Since it is a communication each packet can be thought of as a message.

The message has information, but the information is only useful if the other end knows what the message is about. So that the receiver knows what the context of the message is there is usually a PacketID.

In binary based protocols there is usually 1 byte or 2 byte sometimes even 4 that are prefixed to the data of the message. This says what the packet is for. In text based protocols there is usually just a command. For example in HTTP there is the action command of GET or POST or whatever.

If the data is sent over UDP then the packet when/if it is received will always be the exact size it was when sent. With TCP since it is a stream not all data may be at the endpoint after a RECV similarly more data might be there.

So it is common when using TCP to use fixed sized packets or to have a unsigned short or unsigned int that is in the first spot of the packet that says how much data the other end should read for the message. In this case its often before any packet id and the other end makes sure it receives >= that amount of data before it can be processing the message.

So we now know that there is usually an ID or a Size and ID.

Both ends of the communication agree on packet id's there is usually an order to them.
Either its one end sends 01 and other end sends 01+1 for the reply
Or one end sends 01 and the other end replys with 01.

But it might also be possible for them to reply with something else depending on the type of command. Or even replying with nothing. No reply is still communicating :) Just like in real life if someone says Hey and you don't like them or are mad at them and ignore them. Thats still communicating a message of I don't wanna talk to you.

What about the message that the packet has the data after these?.
Well not all packets require data some might be an instruction for example a Keep Alive packet that most games send might be the client sends a 04 and the server sends a 05 in reply. Keep Alive's are an important feature in UDP where packets are not reliable. or Reliable UDP even. But in TCP I think its rather useless as its a stream it sends underlying packets that the OS handles to let you know the state of the connection. UDP is connectionless you just send the data and hope it makes it.

However in some things it might be handy to send a keep alive on TCP for example you might want to detect speed hacking. If the game client sends a packet every 10 seconds and all of a sudden you are getting them quicker than expected the user is probably speed hacking or spamming the packet. You have to take latency into account of course.

Oh and before I forget. TCP the packets end up at the other end in the order you sent them. In UDP your packets can end up in a mixed order. So it may be a good idea to have a sequence or a CommandNumber which is just the packet count or command count respectfully. The sequence number can be used to reorder the packets or perhaps ignore older ones. And a CommandNumber can be used when you send a command packet but don't expect it to be processed by the server sequentially. For example when you login to a server it would probably be sequential *We send packet server replys we send another etc* but when in game you would want to be able to send packets asyncronously that means in any order. With a CommandNumber you can send a command to the server and when it replys you can note that the reply has happened for that action. For example file transfer or a request for cam in a chat client would use this method. Similarly it might just ask the server for permission to create a request ID which you would get back and then the server sends you the reply for that ID and all communications might have that ID in it. MSNP for exmaple uses that for their switchboard sessions.


So onto the data and of course Cryptography.
If the data is not encrypted you will see the same data each time. An easy test is to get the game or software to send a packet for something you know like a username or a chat message. If you see the text in your sniffed packet you know its plain text there for no encryption.

If you cannot see the message at all in plain text or unicode plain text then the data is most likely encrypted.
If you send the same message twice and see the same data in the sniffed packets apart from perhaps a sequence number or command number then you can be sure the data is encrypted with something that is symmetric. That means the same every time.

If the data is different then it might just be a different key or perhaps a slightly trickyer crypt.

Another test I like to do is send my message with all 1 character apart from the last.
For example I might send a message like this.




In this example its plain text. You can see the packet id is 0C and that its a dynamic message. The size of the chat message is next as a unsigned short. 25 characters. And then there is the chat message with null terminator. *The prefix of message size is for speed knowing it rather than looking increases speed of the operation to copy/use it for something.

If the data were encrypted like this and its the same each time


Then I can be sure that the encryption is most likely 1 operation in a for loop for the size. Possibly XOR
If it is XOR then 00^EA would == EA so we would know that the key is EA. We can see it twice in this packet where the 00 would be.

You see the pattern of 83's were the i's would be.
If they are not like that and it was 83 84 85 86 83 84 85 86 then it would be xor but it would add 1 each time to the key to a point then reset it to the start.

If it is something like 83 91 23 14 83 91 23 14 then its a pattern still. Either its - or + the base key of EA or its another key altogether.  It is also possible for a block cipher to be used. This changes a block. Blowfish is quite a common one. I won't show the data here but basically all the data in blocks of 4 is encrypted. if theres any remaining its not encrypted thats an easy way to tell if you send a plain text message of uneven size.

In a block cipher the data may even look something like this
83 83 83 83 85 85 85 85 81 81 81 81 82 82 82 82

There are also obfuscating techniques that can be done to the data like rearranging it. I won't go into detail on these but if you step through the ASM code for the encrypt/decrypt you can most likely reverse it.

If they use XOR then its budget and cheap and basically not even worth it. It only prevents noobs wanting to make packet hacks, server side emulators or bots. If you are a noob and couldn't get around this before well you have information right here to get past it.

char Key=0xEA;
for (int i=0;i<buffersize;i++)
{
    buffer[i]=buffer[i]^Key;
}

XOR encrypt and decrypt are the same.

Next in the series will probably be  using OllyDBG to find the GameSend GameRecv Encrypt and Decrypt functions. As well as identifying what encryption a game uses. And maybe even how to call the functions from a DLL.

I might write more here later for other things to do with packets.

1 comment:

  1. Firstly understand the packet headers, where the ID is, where the Data is. And understand basic data types.

    Know your data, you should probably know something you expect in the packet for the action you want to figure out the structure for. Look for obvious text or values you would expect to be there.

    Such as character name guild name etc all 13 in length.

    If in doubt and its 4 bytes put integer 32. Short is 2 byte or int16 and byte is int8.

    If its a long length, you don't understand split it out into smaller types.

    Keep in mind, a lot of actions have a status byte after the packet id if its not dividable by 4, is the (length - 1) dividable by 4? if so, then maybe there is an int8 then the rest of data.

    Keep in mind there could be repeating structures, or re-used structures from other things. If the packet is a variable length from multiple captures, then it may have a count of records, or the record count might be size-sizeof(packetID) / sizeof(Record). Or if dealing with a text protocol NULL terminated or new line delimited between packets. (Not the case in this game.)

    Guess the data types for unknowns, and put them in as Unknown1, Unknown2, Unknown3 etc...

    Another thing to notice is packet length after the packet id. This is the length of data for the parameters of the packet.

    If it can be divided by 4 as a whole number then the data types are most likely all 4 byte types. (int, float or two shorts or 4 bytes etc)

    Float is likely to be used for x,y,z or x,z and direction or rotation, a percentage such as how far through a tween or position on a line.

    The only way to know is to look at the float value in 010 Hex Editor and see if it makes "Sense" as a number you might expect to see used.

    If all the floats are numbers like this 7.112851e-41 in scientific notation then its likely not a float?

    If it looks like an XYZ its either going to be float or int

    If it looks like a direction its between 0 and 360. (Probably)

    I think the steps above^ could be generalized into a program to process packets and attempt to guess at the structure but even if it does guess :D it would still need human to confirm and tweak :) would that be helpful if I coded such a program?

    its really just a list of various steps I would do....

    Good Luck!

    ReplyDelete