Friday, 21 September 2012

Finding GameSend and game crypt functions using OllyDBG

Generally most games will encrypt the data right before they send it.
With that knowledge we just have to find where the game sends it. Then we can look above it or before it to see where the game encrypt function is.

To analyse encryption/decryption used you can refer to this previous post on Packet Analysis there is also an IDA Pro plugin called Find crypt its quite cool and can be used to find things like blowfish tables and then you can find what code references that to find the decrypt/encrypt functions.

First we will tackle the send function. Most games tend to have just 1 spot for that calls it that we call the GameSend function. This is because game programmers like to use classes. If the game is older and uses C it may have send called in every function to send packets. Similarly send may be used elsewhere when they do certain operations. There are other api's for sending packets/information. But we will focus on send its in winsock WS2_32

Load up the game in ollydbg giving it any parameters required etc. I will assume you can bp with olly and that the game is loaded successfully. I suggest you run the game in window mode if possible and log into the game fully before attempting this stuff. Whilst it is possible the game uses the same function for login/character select it may not always be the case. However you can do the same steps to find it.

If you have the CMD Bar plugin you can write BP send in it.
If not lets do this manually click in the CPU window and press Ctrl+G to goto an address.
Type in send and hit enter. If this does not you may have to analyse the executable by pressing Ctrl+A
When you are on the send line it will look something like this.

Breakpoint this by pressing F2.

It may be hit instantly or it may take a while. Most games have a keep alive packet being sent or a game state being sent. To trigger it do something like send a chat message. Its best to trigger it your self by using a chat message as its easy to see. Just type Hey or something you can recognize.

When triggered you will see some values in registers and on stack.
You may want to press F2 to remove the breakpoint then F9 to continue running rather quickly to prevent dicing your self.

The stack is shown in the bottom right of the screen in it you can see the data passed to this api function as well as where it was called from and where code flow should return too afterwards. Just a side note in the screen shot I have gone to 005B2AA0 where my data lies. I wrote XD as my chat message.

As you can see the data is encrypted. Its obviously XOR and the key is most likely F3. A message of "XD" would be 2 bytes in string data. Were the data unencrypted we would see our XD text in this buffer.

We need to goto where this code is called from.
If execution is paused still you can continue executing to return Ctrl+F9 then F7 step into
We can also just use Ctrl+G and type in 00428CAE or we can left click that address in the stack and press Enter to Follow it in disassembler.

Now that we are at that address we need to scroll up slightly as we are under the call to send.
The encryption process is usually above this send either as a CALL function or just asm inside here.

I have put red lines where encrypt calls may be. And a red line with an arrow to where the XOR is.
Obviously this statement is for to crypt a byte. We know its using XOR so we should really look here first.
If we were to BP the top of this loop at 00428C4D we would see our buffer address as a register, and our size as a register, maybe even the key. We would goto the buffer in the dump window and see for each iteration of the loop 1 byte is encrypted. This is a simple for loop to xor each byte in the buffer for packet size.

Here is an example in C++
for (uint i=0;i<packetSize,i++)

^ is XOR in most languages.
We can see that there is this code.

00428C6A        |.  0FBE02        |MOVSX EAX,BYTE PTR DS:[EDX]
00428C6D        |.  0FBE0D E29B59>|MOVSX ECX,BYTE PTR DS:[599BE2]
00428C74        |.  33C1          |XOR EAX,ECX
00428C76        |.  8B55 E4       |MOV EDX,DWORD PTR SS:[EBP-1C]
00428C79        |.  0355 F4       |ADD EDX,DWORD PTR SS:[EBP-C]
00428C7C        |.  8802          |MOV BYTE PTR DS:[EDX],AL

If we look at it we can see that we move a byte from the PTR in EDX register into EAX.
We then move a byte from the PTR 599BE2 into ECX. This is the KEY
Then we XOR EAX by ECX. This crypts it.

Then we later move AL the encrypted byte back into the buffer at EDX.

If we look closely at the loop above we can see its +1 EDX each time. with EDX being the counter or i.

At this line 00428C59 EAX contains the spot in buffer that we are at. If we BP and step through we can see our data being encrypted.

So there we have the encrypt code/function of this game. This game does not have a decrypt routine as the packets from the server are not encrypted. So I will load up another game later when I find one to give an example of finding recv and decrypt. Lets scroll up to the top of this function and BP it this is the Game Send function. If we wanted to disable their encryption for example if we were making a pserver we would only have to set the key to 0 or nop out the loop that crypts it.

To label the line we can use the shortcut : and then we would write GameSend and hit enter.

If we BP it we can see the paramaters in the stack.
0018F398  |005340B0  RETURN to 005340B0 from <GameSend>
0018F39C  |0018F3AC  ASCII "XD"
0018F3A0  |00000001
0018F3A4  |00000037

So there is our chat message of XD
I have stepped out to where this is called from and scrolled up slightly to see what is pushed. As the CPU window gives a nice layout. I have also changed my message to Hello There to get a better look at it.

So we have an argument ECX which is a pointer to our data.
And after that is pushed we have moving a value into ECX. This sort of call is usually a this call or a fast call.
thiscalls are used when there is a class for sending. Which is probably the case in this game.

To call it we can write a typedef as a fastcall if you don't know what a function returns assume int return value is in EAX btw.

Stepping in further on the start of the encrypt loop I have gone to EAX in the buffer to show the whole packet before it is encrypted and then I went to the end of the crypt loop to see it encrypted.

As you can see the data before is the full packet. Its packet ID is 26 I saw a mov for 26 into that spot further up in the code. This is weird because we have not specified it. There for this game has a seperate call to send for this functionality of sending a chat message And prehaps every other event.

Looking around this area in memory we see other functions. By breakpointing them we can see what triggers them.

004261E0 GameSendKeepAlive

00426360 Unknown
00428B90 GameSendChatMessage
004264E0 GameSendAction
There are quite a few.

Each is a function we can pass arguments too and call.
For example we could call GameSendChatMessage, passing it the message and the pointer to buffer in ecx and the game would send that message for us. There is a trick to use fastcall to call functions with two paramaters were one is passed in ecx.
I think it is like this have not done it in quite a while so will have to double check later.
typedef int (__fastcall* TGameSendChatMessage(void* _this,char*Message));
TGameSendChatMessage GameSendChatMessage=(TGameSendChatMessage)0x00428B90 ;

You can also just use asm to call it.

void SendAChatPacket(char* Message)
    PUSH Message
    MOV ECX,0x044540; // That pointer to buffer object address *should probably acquire this using signitures.
  CALL GameSendChatMessage // Again we should acquire this address using signature scanning.

This is terrible. It means the developers have wasted space in memory by copy pasting code everywhere. Of course they could just have it like this. which would make editing code easier but also wastes space in memory/disk.

void inline EncryptPacket(void* Buffer);
void inline SendPacket(void* Buffer, int Length);

Then they could have a function for each thing like

const uint 
ChatMessageLength 60;
void GameSendChatMessage(char* Message)
  // This could have a makepacket function or something
  // other things for junk 8 bytes and packet count.
  // Move stuff into buffer

Who knows how they coded it but its terrible.
I will try to find a better game to use for an example and continue from this point.

--------------- To be continued -----------------------------------------------

After making a template function or skeleton function for Game Send

I would usually work out the packet header that is if it uses packetid, packetid and size and any other data. Then create a class that inherits from that and use that for my data. Then I would send that using the game send function.

typedef unsigned char PacketID;
class PacketHeader
  PacketID packetID;
  PacketID getID();
  setID(PacketID packetID_);
}; // Other packets can publicly inherit from this as their parent class.
const int ChatMessageLength=60;
class ChatMessagePacket : public PacketHeader
      char message[ChatMessageLength+1]; // A trick I picked up take the length and add 1 for the null terminator then all strncpy or sprintf or w/e know that the max message lenght is 60 excluding null terminator.
      ChatMessagePacket(); // Sets the packetID to the ChatMessage Packet ID
      ChatMessagePacket(char* message_);  // calls the first constructor and copys the message_ into the message
      setMessage(char* message_); // Copys the message
    // Protected functions here if any.

It would be possible to make other sorts of chat packets by inheriting from this one such as Normal chat, world chat, party chat, whisper etc. Or you could just make them like that one.

After such definitions are done I could do code like this in an injected dll, bot server etc.

ChatMessagePacket* testMessage = new ChatMessagePacket("Hello World!");
delete testMessage;

Finding game recv is easy just bp recv and wait for a message or get a friend to say Hello or say Hello your self most games just send back your chat message to you too.

If the packet is encrypted the game will most likely decrypt it after it knows the size of the data. Some games using xor encrypt just decrypt the whole data returned by the recv operation even if its tcp stream They store the decrypted data in a buffer and read through it till they can't no more.

We need to find out where the packet id is in the buffer after the decrypt/recv. And what reads that to determine what to do.

There are two ways I have seen for managing packet id's and working with them.
The first is a switch case

PacketID packetID =  (PacketID)buffer[0]; // Some position im assuming 0 but it might be after a size integer/short
switch (packetID)
  case SomePacketID:
   CALL GameFunctionToManageIt;

The other is an array of function pointers you need a functor type and then you just call w/e one for the packet id. You would want to check to make sure the packet id is in bounds and full any gaps with 0 and check if the function points to 0 if it is 0 then don't call it and discard the packet.

typedef int (__stdcall* GameRecvPacketFunctionT(void* Data)) // You might also pass a character/connection object or game object or just get it in the function.

int GameRecvChatMessage(void* Data); // handles the chat message reciving eg checking length of chat message and showing it in chat window.

const int MaxPacketFunctions=1;
GameRecvPacketFunctionT packetFunctions[1];
packetFunctions[0] = GameRecvChatMessage;
void somegamerecvpacketfunction()
  // has received data into buffer
  // Gets packet id
  // Checks lengths prehaps
  // if packetID <= MaxPacketFunctions
  if (packetFunctions[packetID]!=0) packetFunctions[packetID]();

So if you wanted to hook a packet function you would find out how to get its address and its function description. You could also just hook the function that works with the received data or detour around the packetID part. to alter data or ignore packets. Or to sniff the packet data and output it to a log file. You could also read the packet data and say check the item thats been dropped if its what you want you could pick it up. There are so many things you can do once you hook and can call the functions. Its up to you to find them out for your game.

Example send and where encrypt is in IDA pro.


  1. Thanks for the nice tut, can u make more?^^
    ; )

  2. Replies
    1. I'm trying your tut at this game ( kalonline, private-server) :

      But seems like SendFunction-adr is changing randomly, also the packet headers O.o, and actually I don't understand how to write a send function for it :\

      Thanks for help :)

  3. I havent really encountered a game where the functions change location other than when it patches. But you would just have to find the main one once and write a signiture to find it from a DLL you make to inject :)

    I guess its possible for a game to have polymorphic code or load dll's like Quake 2 & 3 do. But theres always a way to find the code.

    As for the packet headers make sure you are able to access the data thats put into the buffer before encryption. If possible even figure out how to encrypt and decrypt their data if they do crypt.

  4. Ty, can u make a tut for signiture making?

  5. I wrote about it breifly here.


  6. hi,thanks for the tutorial,but i got some problem,can you make a video please?

    1. Nawh, it doesn't get much simpler than this.
      You will have to know how to use your debugger of course :).

  7. Liam , I was seeing some tutorials that you did , I really don't finded anything so well explained how you did... what most struck me was see the date... 2010~2011 , Incredible how at that time some guys already knowed so about it , Liam I would like that , if you can , maked a tutorial of how find parameters of functions in Ollydbg , or how find most easily the parameters , it's frustating to me pass severals hours seeing ''The program stopped'' ... tutorials as this []] are the light at the end of tunnel to guys as me ... Sorry me for my bad english , I was forced to learn , in my language native don't exist anything about this things...

    1. Hi Derley, I no longer really use OllyDBG.
      x64dbg and its x32dbg program can tell me those arguments (best guess) via the Snowman Decompiler.

      IDA Pro can also do it with the hexrays decompiler and pressing F5 or Y on the function.

      Keep in mind its not always correct. The compunter can't tell the difference most of the time between 4byte signed integer and 4 byte unsigned integer or whatever.

      One way is to just check the arguments passed to the function call, the registers they go into and what they look like.

      Generally anything within a .data memory range is a pointer right :).