Search This Blog

Wednesday 21 September 2016

Money crack in an old PC game

The following post was written for educational purposes only. Please don't ask for any cracked executables from me.

In a recent article of mine, I’ve shown you how WinDbg can assist you in cheating. Today, I wanna show you how to go one step further, i.e. to modify your executable in order to circumvent some logic, like the one decreasing your gold when buying something. Of course, this could be easily achieved by attaching WinDbg to DOSBox and creating a breakpoint at the address where the money is stored with an automatic command that rewrites the value. However, my intention is to circumvent the logic that subtracts the cost of items from our money without a debugger attached.
The game of my choice is Gods from 1991 by The Bitmap Brothers. What an awesome game it was. My brother and I used to play it a lot when we were kids. We knew most of the levels by heart. Even today it is a game I can enjoy. If you don’t know it, you have to give it a try, trust me!

DOSBox

As this is an old game running in 16-bit real mode, you won’t be able to start it on modern systems w/o an emulator so I decided to use the most popular one – DOSBox. If you’re not a command-line geek, you might want to check the available frontends for it. I can only recommend D-Fend as it is very easy to use and exposes many configuration options via a nice GUI.
Okay, let’s start the game in DOSBox. I’ve already played thru the 1st part of the game, so I had the password for the temple region. Enter DYJ and we’re in the shop. That’s exactly what we need for testing. And WinDbg. Attach to the dosbox process and as our starting money is 80000, let’s look for that value in memory.
0:000> !address -c:"s -d %1 %2 0n80000"
005c12f0  00013880 7d81187f 01388010 8b0f7f00  .8.....}..8.....
005c13cc  00013880 458b0f7f 1c450320 0186a03d  .8.....E .E.=...
005c1420  00013880 7d81187f 01388028 8b0f7f00  .8.....}(.8.....
08af3324  00013880 0018000e e646ffff 020dffff  .8........F.....
08af33e4  00013880 000cffff 01c20000 00000000  .8..............


There are 5 occurrences. But what if I buy a fireball for 12500 and check again?
0:000> !address -c:"s -d %1 %2 0n67500"
043240b0  000107ac 000009bc 000004e4 00000000  ................
08af3324  000107ac 0018000e e646ffff 020dffff  ..........F.....
08af33e4  000107ac 000c00c2 01c20000 ffffd1b6  ................


Still 2 matches compared to the previous results? Okay, I got it! As the money gradually (not instantly) decreases from 80000 to 67500, I figure the game stores the "from", "actual" and "to" values and when "actual" becomes "to" over time, "from" is set to "to". Makes sense, right? :-)
So let’s choose the first address and reset the value it holds to 80000.
0:000> ed 08af3324 0n80000
0:000> g


Great, the money rolled back to 80000. So this is the memory address of "to". Now we need to find the code that modifies it.
0:000> ba w4 08af3324
0:000> g


Buy the same item again, and….
Breakpoint 0 hit
eax=08ae0020 ebx=00013304 ecx=000007ac edx=00000013 esi=00000304 edi=00000304
eip=00487cc1 esp=0028b460 ebp=000031a0 iopl=0         nv up ei pl nz na po nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000202
DOSBox+0x87cc1:
00487cc1 8b35c8b07400    mov     esi,dword ptr [DOSBox!LoadDLS+0x194828 (0074b0c8)] ds:002b:0074b0c8=0000008a


As cs:Eip now points to the instruction after the one triggering the breakpoint, let's find the one that caused the bp hit.
0:000> u eip-4 L2
DOSBox+0x87cbd:
00487cbd 66890c18        mov     word ptr [eax+ebx],cx
00487cc1 8b35c8b07400    mov     esi,dword ptr [DOSBox!LoadDLS+0x194828 (0074b0c8)]


Hmm… the instructions use 32-bit registers. That’s pretty unusual for a 16-bit game.. what’s going on here?! After doing some research I realized that DOSBox works as an interpreter, i.e. it reads the instructions from the original executable and translates them to 32-bit protected mode stuff. The callstack also confirms this, as there’s no sign of gods.exe or game.exe in it.
0:000> k
# ChildEBP RetAddr  
WARNING: Stack unwind information not available. Following frames may be wrong.
00 0028b478 00567c60 DOSBox+0x87cc1
01 0028b498 004acbb7 DOSBox+0x167c60
02 0028b4a8 6813eb12 DOSBox+0xacbb7
03 0028b4b0 76c6149d SDL!SDL_RegisterApp+0xaeb2
04 0028b518 76c614d0 KERNELBASE!WaitForSingleObjectEx+0x98
05 0028b588 0040129f KERNELBASE!WaitForSingleObjectEx+0xcb
06 0028b5d8 00401646 DOSBox+0x129f
07 0028b5e8 004162d7 DOSBox+0x1646
08 0028b5f8 0058b179 DOSBox+0x162d7
09 0028b5fc 00000000 DOSBox+0x18b179


Conclusion: it makes no sense to look for the opcode bytes in the game executable(s). We have to find a way to debug the original code, not the transformed one. This is where the DOSBox Debugger comes into play.

The DOSBox Debugger

In order to use the debugging features of DOSBox, you have to either re-compile it for yourself with some special switches or be smart and download it from somewhere. :-) I went for the 2nd approach.
http://source.dosbox.com/dosbox-74-debug.exe
Now let’s start the game from the debugger and navigate to the shop screen again. Then press Alt+Pause to break into the debugger.

We need to find 80000 (0x00013880) in memory…hmmm..there seems to be no built-in support to search for data in memory. You have to dump the contents of a memory region to a binary file and look for the value with your favourite hex editor.
-> MEMDUMPBIN DS:0 10000

This command dumps 64K data to a file named "memdump.bin".


The fact that there are 2 memory addresses again holding this value nicely corresponds with what we've seen in WinDbg. We can adjust the data overview region to start with this address:
-> D 1317:194

Now let’s buy a fireball and… the value changes at 1317:194 accordingly. Good, so now we know the address of "to" for sure, let’s reset it to 80000.
-> SM 1317:194 80 38 01 00

Now we define a breakpoint for this address.
-> BPM 1317:194

Buy the fireball again and the breakpoint is hit. Check the previous and current instructions in the code overview area.

Gotcha'! These two instructions are responsible for decreasing our money. All we have to do is find the opcode bytes (0x29 0x06 0x94 0x01 and 0x83 0x1E 0x96 0x01 0x00) in the executable and replace them with nop instructions (0x90).
I've already noticed that even though the game is started with gods.exe, there's also a game.exe. I wanted to make sure and scanned through all files in the game folder for the opcodes but no luck. Hmm… I feel so close to the solution, what now?
Checking the game.exe header revealed the last piece of information missing. Game.exe was packed with pklite, a common exe packer from that era.


There are several tools to unpack / repack, let's use unp for this purpose. After that the opcodes finally reveal themselves. Change them all to 0x90 and don't bother with repacking. Now run the game and…. EVERYTHING IS FOR FREE IN THE SHOP! YAAAAYYYYY!!!!
How cool is that? ;-)

References:

http://www.vogons.org/viewtopic.php?t=7323
http://www.vogons.org/viewtopic.php?t=3944
https://defuse.ca/online-x86-assembler.htm
https://www.onlinedisassembler.com/odaweb/

No comments:

Post a Comment