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:
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.
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 www.zlib.net 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.
OK So now I know they use zlib 1.2.3. So I headed over to zlib.net 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.
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
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.
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 www.zlib.net 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
unzip.c's password references
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.
.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!
Play Mega Truck Online
ReplyDeleteMega Truck Game
Ruthless Pandas
Play Ruthless Pandas Online