Chapter III - Revealing a hidden gameplay
In the previous chapter we reversed the comparison routine of two doublewords in memory. We got its disassembly with Softice. When I looked at the whole "function" I wondered what's going on with all the other addresses the routine is dealing with:
017F:00401C37 5E POP ESI 017F:00401C38 5B POP EBX 017F:00401C39 C3 RET 017F:00401C3A 833D8C45410000 CMP DWORD PTR [0041458C],00 <- What is going on here ? 017F:00401C41 7530 JNZ 00401C73 017F:00401C43 A1742F4100 MOV EAX,[00412F74] <- Copy scorepoints to eax 017F:00401C48 3905A82F4100 CMP [00412FA8],EAX <- and compare it with the value stored inside 412FA8 017F:00401C4E 7723 JA 00401C73
Look at the code at 401C3A. I do not know what it is for so far... so let's just try it out. The code compares the value inside 41458C to zero. So we could patch it with any value different from zero. Let's rerun the game, and just patch the address with a value different from zero. I took "1". Use the map32 command again to get the data segment:
:map32 loogie LOOGIE .text 0001 017F:00401000 0000DB9F CODE RO LOOGIE .rdata 0002 0187:0040F000 00000340 IDATA RO LOOGIE .data 0003 0187:00410000 00004714 IDATA RW LOOGIE .idata 0004 0187:00415000 00000EA4 IDATA RW LOOGIE .rsrc 0005 0187:00416000 00026BB4 IDATA RO LOOGIE .reloc 0006 0187:0043D000 000017EE IDATA RO
And patch it with the value "1" (you can do this by typing "e
<address> <value>" in Softice):
:e 187:41458c 1
If you switch back to the game you will notice that the display of the game changed a bit:
from
to
And not only the display, also the gameplay !! You can play as long as you want.. until you hock the headmaster/principal with a loogie. He will then run into the school and catch you, as the game will quit then (maybe it was supposed to be a debug-version or an earlier version of that game). Wow, amazing what you can find out by just patching a memory address and see what happens - this would be nearly impossible without knowledge of asm in combination with a debugger or disassembler ;) Great, now we need a new function which will be able to poke a value or some bytes into an address (in our example "1" to 41458C). I extended the engine a bit again with Engine_Pke:
Engine_Pke Proc lpWndCap: DWORD, lpBaseAddress: DWORD, nNewVal: DWORD lpWndCap is a pointer to a string containing the window's caption (e.g.: WndCap db 'Beavis & Butt-head Hock-a-Loogie',0). lpBaseAddress is a pointer to the address holding the value we want to patch. nNewVal is the new value to be poked into *lpBaseAddress. invoke GetAsyncKeyState,VK_F9 ;Was F9 pressed? .IF eax==TRUE invoke Engine_Pke,addr WndCap, GamePlay,1 ;Ok, so poke some value into some memory .endif
You see above that I didn't use F10 as hotkey. Why? That's simple.. F10 is
used by Windows as a "shortcut" to the main-menu in a window. Have
a look at the sources - sources
and binaries.