Sunday, January 1, 2012

A bit of a detour but...

So I realized quickly that I will need to learn a lot about game programming, in particular I need to learn DirectX. I'll create a separate post on that later, but I wanted to set the scene for you. I wanted to see how other games packaged their assets (movies/textures/images etc) so I downloaded a few demo games from Steam. I will not name names here as it would be possible that I could get in trouble for it. Let's call it, Another Stupid Shooter, or ASS for short. So I installed ASS, and took a look at it's installation folder and found this:

the game assets

Disregard the VLC icon that's not actually correct, but this is clearly the packaged assets. Of course they're most likely compressed in some fashion so I load one of the files up in 010editor and notice the file starts with PK... which usually indicates a ZIP file. Just in case I run the ZIP template against it and yes, it is indeed a zip file.

pkzip'd assets

Add Image
So I rename the file to .zip and attempt to extract it, but my zip application prompts me to enter a password. OK Things just got interesting. So I stopped my directx research and focused my attention on figuring out the password. Not because I really need it, but I figure it'll be another good exercise for me in RE'ing.

So I loaded up the ASS.exe in IDA Pro and started looking around. I usually head to the strings window or the .rdata section to see what constants I can pick out. You'll find a LOT of applications use inflate/deflate which is part of and it stuffs a bunch of identifiers inside of the binary. Knowing some of the strings it references, I started my search. It didn't take long before I found the version and some strings that I've seen before. Usually, you'll find entire copyright messages, but this was just the first batch of strings I found.

known zlib string/version info

OK So now I know they use zlib 1.2.3. So I headed over to and downloaded the source tree and built it in visual studio. I did this so I'd have a known disassembly that I could use for reference against the ASS.exe's assembly. So now that I have the source, a known disassembly and the target's disassembly I can start to figure out how zlib takes a password and what it looks like in x86 asm. Looking at the source I did a search for 'password' to see what unzipping functions reference it.

unzip.c's password references

So this is the function that will most likely be called to unzip the assets. So this is what i'll look for in my disassembly. Unfortunately, depending on how the zlib project is compiled is going to create very different looking assembly. You can never expect a direct comparison even if the code is exactly the same.
So what I want to do is try to find some constants or something about the function in question that will be a 'dead giveaway.' This is probably just because I suck at RE'ing, but that's my technique there's probably way better ones I'm unaware of. Anyways, looking at the disassembly of the unzOpenCurrentFile3 there's a few things I noticed. Usually I look for references to constants or strings that will be a giveaway, but i didn't find any so the next was looking at function calls, arguments etc. I did notice a few calls in my disassembly to malloc (which allocates memory) of a specific size:

.text:1000F7B3 loc_1000F7B3:                           ; CODE XREF: unzOpenCurrentFile3+67j
.text:1000F7B3                 push    90h             ; size_t
.text:1000F7B8                 call    ds:malloc
.text:1000F7D4 loc_1000F7D4:                           ; CODE XREF: unzOpenCurrentFile3+88j
.text:1000F7D4                 push    4000h           ; size_t
.text:1000F7D9                 call    ds:malloc

Unfortunately the ASS.exe must have inlined it's memory allocator because I didn't find any references to malloc. Even if I did they're would probably be millions of calls. So OK, kind of stuck now. I took another look at the unzip.c source to see if there were any other clues to look for. After a few seconds of looking at calls I found call to a function called init_keys that actually takes our password. Opening that function up we see:

yay constants

As you can see there's three constants that will most likely be easy to find... So switching back to my disassembly I find my constants.
.text:1000E673                 mov     eax, [ebp+arg_4]
.text:1000E676                 mov     dword ptr [eax], 12345678h
.text:1000E67C                 mov     ecx, [ebp+arg_4]
.text:1000E67F                 mov     dword ptr [ecx+4], 23456789h
.text:1000E686                 mov     edx, [ebp+arg_4]
.text:1000E689                 mov     dword ptr [edx+8], 34567890h

That's my ticket, so I do a search text search (finding all occurances) of 1234678h. I find two. Not sure why, but the init_keys seems to be directly inline'd twice into ASS.exe. Looking at the function that calls init_keys I see this in the disassembly:

.text:00745699                 mov     eax, 90h
.text:0074569E                 call    sub_73D9F0
.text:007456AB                 mov     eax, 4000h
.text:007456B0                 call    sub_73D9F0
Look familiar? Yeah, those are basically malloc calls (using registers to pass variables instead of push'ing them on the stack).

 OK, so I have my function and I know it's address. So I load up steam and load the demo. While the game is loading, I start up WinDBG and attach to the process. At first I set a breakpoint on the unzOpenCurrentFile3, but I quickly realized that it gets called many times *without* the password. So I remove that breakpoint and instead I set one on the init_keys function. It is hit almost immediately. You can see in the below image that the password was found in the value contained in the EAX register. So that's it, that's my password. 

finding the key in windbg.

I opened up the asset file again and copied in the password and proceeded to extract the assets...

putting in the password

And as you can see, it worked.

yay assets!

The password is also found in clear text in the .rdata section , but don't count on just finding passwords in binaries as usually people try to obfuscate them a bit more. So yeah, that was my detour for a day or so, I guess I should get back to learning DirectX.

1 comment: