06 June 2003

Finding UOLog values by Folko

Win Code Reversing

Target File:
client.exe
Target Type:
Game
Target URL:

www.owo.com

Target Size:
-
Tools:
IDA, UltraEdit, OllyDbg, any emulator

Level:

Easy [ ]  Medium [X]  Hard [ ] 


 

1. Preface

Some people asked me how to find the values for UOLog's clients.cfg.
This tutorial will show you how to find the client's Encrypt and uncompress routines.
The first part shows the difficult approach, it requires no knowledge about the client's internals.
The second part is based on the first part and shows you how to find the values for any client in a few seconds.
If you're new to reversing or just want to find the values quickly, skip part 2 and move on to 3.

 

 

2. The difficult approach

Ok, let's go. Open your client (Assuming 4.0.0l) in IDA. Use default options and let IDA work. Eat some pasta in the meantime.
When IDA is done, save the database. We'll need it later, not now.
Now start any server emulator (My favourite is POL) and open your client (One *with* encryption!).
Next, open up OllyDbg and attach it to the client. Set a breakpoint on "send".
To do so, press ctrl+g and enter "send". To set the actual breakpoint, press F2.
Now enter any login and password and hit enter. Olly will break and popup.
In the calling stack window in Olly (lower right), you can see the stack for send. "DataSize" is 0x3E, that's the correct length for the login packet. But look at "Data", it's encrypted, and that's not how we want it in UOLog.
The TOS (Top of Stack) always shows the return address of a call, ie. the location from where the call was made. Remove the breakpoint (F2) and go to that location with ctrl+g (419A08 in 4.0.0l).
Ok, we're direct on the send call. The packets are encrypted there. If you scroll up a bit, you'll see the message "dunno, select with invalid socket". Looks like we're in the client's send function. Set a breakpoint on top of that function (419980) and login again to make Olly break there.
When it breaks, you'll notice that the function has no calling stack, ie. it's func(void);. Trace down using F8 and observe the register window. You'll notice that 4199E6 ECX contains the length. The next line puts the address of the encrypted send buffer into EDI.
We put our breakpoint too late, the data is encrypted there already.
Hmm, what can we do? Right! We put a breakpoint on the address of the encrypted send buffer. Right click on the first byte of the encrypted datastream in the dump window and select "Breakpoint -> Memory, on access". Now resume the client. Olly will break immediately, you'll see a rep stosd, that cleans up the memory by setting it to 00 00...Resume the client, login again, and olly will break again.
Wow, this time we're in a loop (You'll recognize loops by black borders around them in olly). The loop is using shr, shl and some other binary operators. That really looks like the encryption loop, nice. Remove the memory breakpoint, but don't resume the client yet.
Instead, place a breakpoint on top of the encrypt function (41A360) and then resume the client.
Login again, and olly will break. Look at all the registers, EDX contains the length already. But the data isn't in the registers yet, so let's trace (F8) over the call which is right below the function header.
Look at the registers! Great! EAX contains the length and ESI contains our packet! That's all we need for send.
We have:
Address where we have the plain packet: 41A370
Register with the length: EAX
Register with the packet: ESI

Now for recv.
We can't use the crypt client anymore because the server doesn't send back anything since our login packets aren't valid (Well, encrypted). So let's fire up a no-crypt-client and attach Olly to it.
Login and go to a location without any NPCs and anything so you don't receive any packets.
Remember that the client used "select" to check if there are packets ready to be received? Let's set a breakpoint on select.
Of course Olly breaks immediately because the client constantly checks for packets (Btw, that's one reason why it needs 100% CPU all the time, but that's another story, PeekMessage). Go to the calling address (419803) and you'll see the check if select returned -1.
Scroll down a bit and you'll see a call to recv inside a loop. If you know how TCP/IP works then you know that the packets arrive as a stream, not at once, that's why they're received in a loop. Place a break on top of that loop (41985C) and resume the client.
It will break soon because it receives a ping reply packet. Go to the location where Olly displays "Buffer". That's where recv will store the received data. Display it in the dump window, step over recv and then set a memory breakpoint on it.
You'll notice that the memory just gets cleaned, so a memory on write breakpoint isn't correct. Set a "On access" breakpoint instead.
If you did it right, you'll end up in some loop at 419BC0. Place a break on top of that function.
When the client breaks, remove the breakpoint and go to the calling address (419D0C). You will see a big loop below the call. Trace a bit into that loop and you'll see that it builds the packet and calls 41A4A0 after building the packet.
Trace into that function and look at the registers, EDI contains the length and ESI contains the packet. Done.
Now we have all the information for recv:
Address where we have the plain packet: 41A4A0
Register with the length: EDI
Register with the packet: ESI

Now all we have to do is getting the timestamp of the client. Open client.exe in UltraEdit and search the PE header. It is on top of the file and starts with "PE", in 4.0.0l it's at 0x0138. Skip the next WORD and the next DWORD and you'll have the TimeStamp in Little Endian. To convert it to human readable Big Endian, reverse the bytes, resulting in 3EBFECC0.
That's it, we have all the required information for UOLog!

 

3. The easy approach

1) Open the client in IDA
2) Scroll up to the top, press alt+t and search for "], 33h"
3) Scroll to the top of that function. The address is the one UOLog uses for the RecvBuffer.
4) Scroll to the top of the function above and find the "mov bp, ax". That address is the one for the SendBuffer.
5) To get the timestamp, open the client in y0da's PE editor and copy the timestamp.
6) Play with the register numbers until it works. Usually, you can copy the numbers from the previous client.

 

4. The End

Well, this tutorial was harder than my first one, I hope you still managed to understand it.
If you have any questions, feel free to contact me:
ICQ: 59280495
Mail: folko@elitecoder.net

Greets to: All x90 members, especially Arog and NecroPotence.

Final words:
If you like the American Way Of Life, then I can't help you.
Insprinc haptbandum, inuar uîgandun!
Bên zi bêna, bluot zi bluoda, lid zi geliden, sôse gelimida sin!

 


Tutorial by: Folko
Page Design:      29 April 2000 by ChiLlar163