Lesson #3

By

Indian_Trail

Crack,snap and pinball Fantasies.

In the previous lesson I showed you the basics of assembly language and how to find a byte in memory using softice. This method is very fast and reliable if you wanna add some lives in a game in a fast way the snapping method is probably the best. One side affect with this method (so far) is that the changes in the game are made permanet unless you have softice running while playing the game. Once the *.exe file has been patched the only way to get back the # of lives the programmer gave us is changing the file back.

Since quite along time game programmers (appz even) include hidden features. In games such features are usually cheat codes that you type in during the game (or at the main menu of the game). In this lesson I'll show you how to obtain these cheat code in two diffrent ways. I'm using Pinball Fantasies here becuse it's ideal for cracking and cheating studies. It's fairly spread and should be availbale on the web or on some warez channel on IRC. I like to stress the importance of using Softice 2.62 cracked Marquis de Soiree. When searching for softice (if the links in lesson #2 have died) use a Ftp search engine. You'll find hundreds of sites containing Softice 2.80. That version is USELESS for our purposes, because it doesn't snap (the snap function doesn't work), you'll have to find softice 2.62. Only use the dos version of softice as the window version (though it allows you to debugg dos boxes) is more complex.

Ok lets start:

Before we can crack a protection scheme we must understand how it works. As you probably already discovered Pinball Fantasies (PF from now on) is protected with a manual protection scheme ie "please enter the word # 3 on page # 4 in your manual". These schemes are usually very ease to defeat (it took me less than 5 minutes). This is how it works:

  1. Get users input from keyboard buffer and store it in memory
  2. Load the real password and store it in memory
  3. compare user input with real password

This is a logical conclusion of what should happen. The weak spot of the protection here is the comparsion of the user input and the true password. A normal approach would be to enter "cheat" as a password and then as we press enter and the "sorry incorrect password, try again" message pops up, we would search for our input in memory to find out where the program stores our input, and then trace through the program using breakpoints until we find the cmp user,password.

A protection scheme like this can compare the input string from the user with the correct string in two different ways. The first is by simply comparing the strings using CMPSB usually like REPZ CMPSB which would compare the string that ds:si points at with the string pointed with es:di. The B in CMPSB stands for byte and could as well be a W like CMPSW which would then mean Word.

The second way of comparing the two strings is by byte, like loading the first char in the user input string in AH and the first char of the correct password in AL and then simply do a CMP AH,AL and then loop back until the end of the correct string is reached or as soon as the AH doesn't match AL.
To load a char in a register like AL, the command LOADSB is very suitable. It will load the byte that DS:SI points at in AL. And to load AH with a byte a simple MOV AH,[BX] would do. the [BX] means that the data at the adress of BX is being accessed.
Like if BX is 3010 and at adress 3010 the char A is stored, MOV AH,[BX] means load AH with 'B'. The assembly language can seem hard to understand at first, but after you have debugged some programs or written some own (in assembler) you'll get the hang of it. ASSEMBLER IS PRETTY EASY CAUSE IT IS USUALLY THE SAME COMMAND OVER AND OVER. There all phoney fakes who keep screaming in my ear that assembler is hard got what they deserved ( or became deaf at least). So LODSB and CMPSB and MOVSB can be used for string operations.

Now when we know some basic string operations in assembler we shall go on and crack PF. One thing though the manual protection scheme is not used anymore as frequent, therefor if you find a program that's has a manual scheme CRACK IT even if you have the CRACK FILE. That's the best way of learning, studing the past. If you have a cracked manual protected game you could try to uncrack it, that's basically the same thing.
Alright lets move on.

CRACKING PINBALL FANTASIES

Pinball.exe is the exe file that will start the game. The size of pinball.exe is very small, only 1.7K. Therefor it's not very likely that it contains the code for the main program. Pinball.exe is a loader which will access other files. In one of these files the protection scheme is hiding so therefore lets have a look in our directory where PF is installed.


D:\games\pf>Dir *.exe

Pinball.exe
Setsound.exe

D:\spel\pf>Dir 

will show alot of files where one is very interesting

INTRO.PRG	Hmmn lets see if there's more .prg files

D:\spel\pf>Dir *.prg

Intro.prg
Table1.prg
Table2.prg
table3.prg
table4.prg
It seems that the loader pinball.exe accesses these .prg files and that table is the flipper table file and intro is probably where the protection dwells. Looking at the memory mapping you soon find out that "INTRO" is the current program that running ( if you have executed pinball.exe). So the first INTRO is in 0E98:0000 and ends at 0E98:000B. Remeber that the segment adresses is diffrent from computer to computer but the offset is always the same. This section of INTRO is obviously too short, only 11 bytes, so we keep looking. The next INTRO section is found (in my computer) at 1101:0000. This section is alot larger it ends at 1101:3B91. This is where we should look for our input. So type in something unsual like "hell" or "qwert" for a password and then search for your input in the 1101 sector. Again the adress wont be 1101 in your computer, just look for the section of INTRO that has the start offset 0 and the end offset 3B91. Lets search:

S 1101:0 L FFFF 'QWER" ; your command to softice

1101:5ADF ; softice response

So the inputs are stored at offset 5ADF. Lets dump that location:

D 1101:5ADF

Now you should see your input string in the data window. Since "QWERT" is not the correct password PF asks us again to type in the correct password. Type one letter and change back to softice and see if that letter has been stored at 5ADF, it should have been. You may be wondering why we are using capital letters in our search string, that's because PF changes our inputs to capital letters as you can see while you are typing them in. Another question that might hit you is why we aren't searching for all the chars we typed. That because if PF only stores the first four letters we wont find any match while searching for five letters. So now you know that :)

We have now found the keyboard buffer so lets put a breakpoint on that location:

BPR 1101:5ADF 1101:5ADF+4 R

Press enter and BOOOM you're in softice. We are now in the code that manipulates our input. You should see this CODE:

	MOV	AH,[BX]		; Mov a letter in AH
	INC	BX		; BX points to the next letter
	LODSB			; Store encrypted letter in AL
	CMP	BX,51E7		; Check if BX is a space (20 in hex)
	JAE	3DF4		; If so then jump
	ROR	AL,1		; this is the first instruction to decrypt AL
	XOR	AL,A2		; and now we have a letter stored in AL
	CMP	AL,00		; Checks to see if it was the last letter in 				; the correct password
	JZ	3DEF		; If so then jump here
	CMP	AH,AL		; Compare user letter with correct password 				; letter
	JZ	3DB8		; if the same then jump and go on with next 				; char

Wow! What does this mean? Well the important thing here is the CMP AH,AL. Don't be nervous if you dont understand all of the above code, time and practise will educate you. I've read some cracking tutorials and I didn't understand much the first times I saw the code of the protection routines. So how do we crack this?

When a program makes a CMP it subs the the operands and the Zero flag will indicate if the two operands were equal or not. JZ mean jump if zero wich means it jumps if the zero flag was set, if it wasn't it wont jump. So to crack this we simply change the JZ into a JNZ or a JMP. JNZ=jump if not zero and JMP is jump anyway.


	LODSB			; Store encrypted letter in AL
	CMP	BX,51E7		; Check if BX is a space (20 in hex)
	JAE	3DF4		; If so then jump
	ROR	AL,1		; this is the first instruction to decrypt AL
	XOR	AL,A2		; and now we have a letter stored in AL
	CMP	AL,00		; Checks to see if it was the last letter in 				; the correct password
	JZ	3DEF		; If so then jump here
	CMP	AH,AL		; Compare user letter with correct password 				; letter
	JMP	3DB8		; if not the same then jump to next char

Now it doesn't matter if AH and AL are the same, the program will always work. Another way of defeating this protection would be to compare true password with true password like this:


	LODSB			; Store encrypted letter in AL
	CMP	BX,51E7		; Check if BX is a space (20 in hex)
	JAE	3DF4		; If so then jump
	ROR	AL,1		; this is the first instruction to decrypt AL
	XOR	AL,A2		; and now we have a letter stored in AL
	CMP	AL,00		; Checks to see if it was the last letter in 				; the correct password
	JZ	3DEF		; If so then jump here
	CMP	AL,AL		; Compare correct password letter with 				; correct password letter
	JZ	3DB8		; if not the same then jump to next char
This way the zero flag will always be set. You could experment with this alot.

Snapping.

Let us find the adress that stores the players ball and then find the increaser or decreaser. Start the game and play some pinball. Switch back to softice and snap save the ds register.

Snap s ds:0 ds:ffff

Loose the ball and switch back and snap compare. Look for changes from 1 to 2 since pinball tells us that we from the start are at ball 1 and after loosing a ball we are on ball 2. Therefor look for changes from 1 to 2. There's not many changes in memory with these values.

2DB4:000D 2DB2:000B 2DB2:000E 2DFF:000F 2E02:000E

Dump these areas to see if they change as you loose a ball. If they change without you loosing then they are not the correct adresses. We are looking for a change in memory that ONLY change when we loose a ball. You quickly realise that the 2E02:000E is the correct storage of the number of balls we have left. It's an increaser. We start with the value 1 and then it increases until the value is 3 and is about to change to 4. I dont think I have to remind you that the Segment adresses will be different for you. Alright lets put a value on that adress.

E 2E02:000E ; change it to 9

Ah it didn't work, I new it wouldn't did you? As I said this adress hold the players balls and it will be compared with a predefined value. If you want more balls you gotta find the predefined value. That's very easy, just breakpoint om memory access at 2E02:000E

BPM 2E02:000E RW

The next time softice pops up will be when you loose a ball and you will see this code:

	MOV AL,[33DF]		; predefined value
	CMP [33DE],AL		; users value
	JA 0B4D			; Jump if above to end session	

Lets change the predefiend value:

e ds:33DF ; change it whatever you fancy

And it works just fine. Use a hexeditor as usual to patch it. Now this way of making cheats is very nice and fun. But a more elegant way would be to make a trainer. So eveytime we press "+" we increase our ball limit with 1 ball. Trainers involves pretty complex assembler programming. There are some trainer tutorials on the web, but they assume that you are at least on an intermediate level of assembler programming. Dont worry I will eaxplain this for you in a later lesseon (if there's a demand) in detail how you write trainers, I explain the whole set, how to write TSR programs which is basically the same as writing a trainer. For those of you who can't wait for that lessons here's some clues.

The program has to be memory resident. It has to read the keyboard on every cycle of the processor to see if a key has been pressed and if so which key was pressed. To make a program resident you'll have to hook a interrupt and redirect it to your program.

Cheat Codes where????

As I said in the beginning almost all of the games released from +1992 contains built in options wich can be triggered. In PF there are some cheat codes that the programmers put in. I will now show you the basics of finding these codez.

There are two way of finding them both of them can be usefull in different cases. The first one is simply dumping the file in a hexeditor and read all the strings you find. The otherway is to debugg the game (what else) and put a breakpoint on keyboard reading usually Interrupt 09, and see what the program is looking for. Lets try the first method.

Load table1.prg in a hexeditor. Search for "cheat", "is" and everything else you can think of if you come up empty.

When I searched PF for the string "cheat" it was found on three places. Here is what i found.

JOHAN$		CHEAT$
TECH$		EARTHQUAKE$
TSP$		EXTRA*BALL$
DANIEL$		SNAILS$
GABRIEL$	FAIR*PLAY$
ROBBAN$		STEIN$
GREETS$


And just below them are the messages you'll get when you have typed them in.
_________________
I would rather be a sparrow than a snail
----------------------------------------
You will now get 7 balls dude
----------------------------------------
All cheats have now been reset
----------------------------------------
The tilt feature is now disabled
----------------------------------------
There are alot of nasty cheats in this game....
----------------------------------------
The dot machine system.....coded by JOHAN
----------------------------------------
Music......................coded by DANIEL
and so on.

Obviosly there are cheat codes here, you can get 7 ball and disable the tilt function. And you can reset the cheats. I call this an inbuilt trainer (almost). I'll leave it up to you to try these codes. For method #2 I'll leave it up to you as a homework to study debugging techniques to find the cheat codes by tracing trought the keyboard routines.

Thats all for now friends


Please E-mail me with your work (the cheats you have made, write an essay on it, on how you approached the program etc etc) Your questions and remarks on my work is also welcomed

Best cracking regards

Indian_Trail

1