[go: up one dir, main page]

0% found this document useful (0 votes)
115 views11 pages

Reversing Decryption

This document provides instructions for reversing the packet encryption and decryption keys used by the Xiah game client. It begins by attaching a debugger to capture packets being sent and received. The encryption function is analyzed to understand how it works. A decryption function is then created by reversing the observed decryption routine. Testing shows the decryption function properly decrypts encrypted packets. Next, a tool is used to log packets and the encryption key is found being sent on connection. The source code for encrypting, decrypting, and an encryption test program are included.

Uploaded by

Christian Muro
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
115 views11 pages

Reversing Decryption

This document provides instructions for reversing the packet encryption and decryption keys used by the Xiah game client. It begins by attaching a debugger to capture packets being sent and received. The encryption function is analyzed to understand how it works. A decryption function is then created by reversing the observed decryption routine. Testing shows the decryption function properly decrypts encrypted packets. Next, a tool is used to log packets and the encryption key is found being sent on connection. The source code for encrypting, decrypting, and an encryption test program are included.

Uploaded by

Christian Muro
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 11

Reversing Packet Decryption and Encryption Key

by zarut

Be sure you read this first:


Reversing Packet Encryption

Required Tools:
OllyDbg v1.10
Xiah
Visual Studio or Visual C# Express
Basic Asm Arithmetic Operators
Cheat Engine
WPE PRO
Lets begin
We start by opening Xiah, at this point it doesn’t really matter whats being send
before we are in game so choose any world / channel you wish.
Once you are in game launch the OllyDbg and attach it to XiahGXClient.exe

but be quick, once the olly is attached to a process it will freeze the process
so you will have to press F9 to make it active again.

We will now see that we are in wrong module called ntdll, press ALT + E
to see all the modules within the process and select XiahGXCl the one that has
base address of 00400000.

After that we pretty much land on the base address, what we do now is to
right click the CPU window, and do a search for 'all intermodular calls'
From here we look out for the WS2_32.recv

Once you find it double click the text and we will land on the recv() function of
this process. The alternate way to do this is by clicking ALT + F1 and type in
bp recv, after that once recv is called it will land you there.

This is where the fun begins, in the picture below we see the function,
its in assembly so i hope you know at least the basics of asm.

Unlike with the previous tutorial where we reversed the encryption function
this time we wont go upwards instead we go below and see the calls after recv call
We start like last time and set a break point here, but this time we set it over the
receive call, after this we say “Hello world” fast in game as there’s plenty more
packets received than being send.

Once the recv function is called OllyDbg will stop and pause the process here,
this time we cant be sure if the received packet is right one so we just have to
have some faith in this and start reversing.

We start by pressing F8 like last time till we get to the first call.
The very first and second call seems to be too short to be a decryption function so we
will continue and check the calls until we find something that has a loop in it.

The third call takes one argument, just like the encryption function did. And it also
seems to have a loop inside the call so this is probably the decryption function.
The picture below is the function.

Looking familiar? It should since the encryption function was almost the same.
Now we will have to analyze this again. Unlike last time I will not explain what
the add,subs and moves mean instead I will just analyze this and post a picture of it.

You should already be able to do this by yourself, so try first and then look how I
analyzed it. See if you got it right.
Here is picture of the analyzed function.

Here is the packet that we decrypted:


54 4A 53 00 02 37 2B 00 2E 8F F7 17 00 18 00 48 TJS.#7+.. ÷#.#.H
00 65 00 6C 00 6C 00 6F 00 20 00 77 00 6F 00 72 .e.l.l.o. .w.o.r
00 6C 00 64 00 00 00 0A 00 4A 00 61 00 63 00 6B .l.d.....J.a.c.k
00 00 00 75 01 01 00 59 7B 07 01 00 5F 00 00 00 ...u##.Y{##._...

We will use the decrypted packet and the packet we send before for another tutorial
on how to analyze the packets.
Lets continue our console application “EncryptionTest”
we want to add a new static function into Cryption class called Decrypt.

Lets create a static function:


public static byte[] Decrypt(byte[] buffer, byte key)

The reason is same as last time, we want to the function to decrypt our packet
and return us a decrypted byte array.

We can use the same variables from old tutorial which were AL,BL,CL,DL.
byte AL, BL, CX, CL, DL;
short LENGTH = (short)(buffer.Length - 4);

Now we assign the values for these variables based on what we reversed from the
decryption function before:
BL = key;
CL = buffer[0];
AL = (byte)(LENGTH + 4);
DL = CL;

I am using the AL for length in this one as well since I don’t really see a reason why
we would need another variable just to hold the length.

After that we start to changing those variables depending on how we reversed


the code before:
DL -= AL;
DL -= BL;
buffer[0] = DL;
DL = buffer[1];

BL = DL;
BL -= AL;
BL -= CL;
BL -= key;
buffer[1] = BL;

for (int i = 0; i < LENGTH; i++)


{
BL = buffer[i + 4];
BL -= AL;
BL -= DL;
BL -= key;
DL = buffer[i + 4];
buffer[i + 4] = BL;
}

return buffer;

Now we have the decryption function ready. Lets see it in action.


We can use the older key and packet for this. We just add few new lines to the
Program.cs:
byte[] EncryptedPacket = Cryption.Encrypt(Packet, 0x67);

byte[] DecryptedPacket = Cryption.Decrypt(EncryptedPacket, 0x67);

for (int i = 0; i < DecryptedPacket.Length; i++)


Console.Write("{0} ", DecryptedPacket[i].ToString("X2"));

We know the chat packet was:


01 37 23 00 00 00 00 00 00 18 00 48 00 65 00 6C #7#......#.H.e.l
00 6C 00 6F 00 20 00 77 00 6F 00 72 00 6C 00 64 .l.o. .w.o.r.l.d
00 00 00 00 00 00 02

So when we encrypt this packet it turns into:


8F 54 23 00 E2 70 FE 8C 1A C0 4E 24 B2 A5 33 2D
BB B5 43 40 CE 7C 0A 0F 9D 9A 28 28 B6 B0 3E 30
BE 4C DA 68 F6 84 14

And when we decrypt it again it turns into (hopefully same as the chat packet is):
01 37 23 00 00 00 00 00 00 18 00 48 00 65 00 6C
00 6C 00 6F 00 20 00 77 00 6F 00 72 00 6C 00 64
00 00 00 00 00 00 02

Once again its PERFECT! So now we have the encryption and decryption what we
are missing is how the client gets the encryption key.

Getting the encryption key is quite simple we either set break point in the encryption
or the decryption function and see what it is, after this we will use cheat engine to
find the key.

We know the key is loaded from a pointer so we will have to do a pointer search
once we find the key.

So my encryption key is 0x90, we will search byte in hex value at cheat engine with
90.

The problem is it found 507, 623 results for this, but it doesn’t really matter
as we know the encryption key changes when we re-log so lets choose change
channel and connect here again.
Once we done that we will have to set new break point in either send or recv to
see the encryption key again, so before I had 0x90 now I have 0x72.

We press the Next Scan in cheat engine with value of 72, and BANG
we are now down to 250 different addresses. We will do the channel change trick
once more to see if the green address is right.

So my new key is 0x89, and the green address is 0x89. This is weird though
as it loads the key from a pointer and green means static address. But we wont care
about this we now know the encryption key is held on at 0064D378.

So now if we wanted to create a packet logger we could make it read memory


and get the encryption key from here. But we want to see where client actually
acquires this key, we will now open WPE PRO in order to see.

We open WPE PRO and click the Target Program button, from there we select
XiahGXClient.exe

Once that’s done press the View -> Options and change logging options to log
Recv and RevcFrom disable the Send and SendTo.
Now we will think for a few seconds, we know the encryption key changes
every time we connect so we will go back to channel screen, press the little play
button in wpe to make it record all packets.

Once you received around 10 packets press the small stop button and it will show
you what it has captured.

Lets look on Cheat Engine what the new encryption key is. For me it was 0x3B
this means we will now look from the packets wpe logged if theres 3B in any packet.

It turns out the very first packet being received has 3B in it, which pretty much
means its the packet we are looking for.
As for pro tip I can tell you in Xiah every time you connect to any of the servers
you get a new encryption key.

So we know the packet has id of 0, length of its data is 1 and the data itself is the
encryption key.

If you wish to create a packet logger you would either make it wait until this packet
is received in order to decrypt all packets being send/received or you could read
the key from memory.

I will end this tutorial here, I will make small tutorial how to analyze the two packets
we send and received in previous tutorials, but I wish you all the best of luck and
hope you learned something about reversing the encryption and decryption.

In last two pages you can see the source code of the EncryptionTest program.
Source Code of the Program:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace EncryptionTest
{
class Program
{
static void Main(string[] args)
{
byte[] Packet = new byte[] {0x01, 0x37, 0x23, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x18, 0x00, 0x48, 0x00, 0x65, 0x00, 0x6C, 0x00, 0x6C, 0x00,
0x6F, 0x00, 0x20, 0x00, 0x77, 0x00, 0x6F,
0x00, 0x72, 0x00, 0x6C, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02};

byte[] EncryptedPacket = Cryption.Encrypt(Packet, 0x67);

byte[] DecryptedPacket = Cryption.Decrypt(EncryptedPacket, 0x67);

for (int i = 0; i < DecryptedPacket.Length; i++)


Console.Write("{0} ", DecryptedPacket[i].ToString("X2"));
}
}
}

Cryption class

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace EncryptionTest
{
public class Cryption
{
public static byte[] Encrypt(byte[] buffer, byte key)
{
byte AL, BL, CX, CL, DL;
short LENGTH = (short)(buffer.Length - 4);

AL = key;
BL = buffer[0];
CX = (byte)(LENGTH + 4);
CL = CX;
DL = CL;

DL += AL;
BL += DL;
buffer[0] = BL;

DL = BL;
DL += CL;
DL += AL;
DL += buffer[1];
buffer[1] = DL;
for (int i = 0; i < LENGTH; i++)
{
BL = CL;
BL += DL;
BL += AL;
BL += buffer[i + 4];

buffer[i + 4] = BL;
DL = BL;
}

return buffer;
}

public static byte[] Decrypt(byte[] buffer, byte key)


{
byte AL, BL, CL, DL;
short LENGTH = (short)(buffer.Length - 4);

BL = key;
CL = buffer[0];
AL = (byte)(LENGTH + 4);
DL = CL;

DL -= AL;
DL -= BL;
buffer[0] = DL;
DL = buffer[1];

BL = DL;
BL -= AL;
BL -= CL;
BL -= key;
buffer[1] = BL;

for (int i = 0; i < LENGTH; i++)


{
BL = buffer[i + 4];
BL -= AL;
BL -= DL;
BL -= key;
DL = buffer[i + 4];
buffer[i + 4] = BL;
}

return buffer;
}
}
}

You might also like