Reversing an algorithm to ensure gameing success and fame on the internet.
Reversing the Drug pricing algorithm in Dopewars version 1.2
Not Assigned
08 October 1999
by smeggett
Courtesy of Reverser's page of reverse engineering
slightly edited
by reverser+
A quite interesting 'applied reversing' essay for beginners. In fact I believe we should begin a small 'dedicated' section for online gaming and (eheh :-) for online gambling. I never analyzed the various gambling programs (that are mushrooming all over the net) but I would bet that reversers in need of money could apply our knowledge with profit at least in some cases...
There is a crack, a crack in everything That's how the light gets in
(x)Beginner ( )Intermediate ( )Advanced ( )Expert

"An essay designed for beginners to show how an algorithm can be reversed in order to 'cheat' the game and pwerhaps register yourself on the worldwide high score list...
Of course you will still need your skill to do this - the reversing only makes the job easier."
Reversing an algorithm to ensure gameing success and fame on the internet.
Written by smeggett

I received my copy of Dopewars via email and was (almost) hooked on it quite quickly, trying to obtain higher and higher scores. During the course of play I noticed that some drug prices became exceedingly high (or low) on the odd occasion, whilst the rest of the time they fluctuated only minorly.

It was at this stage that I decided to look further into the game and see if it was possible to manipulate the pricing algorithm so that the game would throw up the exceedingly high prices every second turn (so you can buy low, sell high of course...)

So look further I did and found that after rewriting some of the code for the routine it was possible to achieve this goal.

Tools required
WDasm 8.9

PS Edit (or any other hex editor)

and that'll about do you...

Target's URL/FTP

File: Dopewars.exe

Size: 526,848 bytes

Program History
None really - started as a MSDOS game in 1984 - has had a windows frontend put on.

The first step in this game is to try and find the algorithm which sets the drug prices, so load the program into WDasm and do a string search for the text used in the message boxes to notify you of an exorbitantly high price (or low price). Select this and you will land in the middle of the pricing routine. The routine is fairly long (about three printed pages in all), but also fairly easy to follow.

The first part of the routine (beginning at 45D120) saves some values and the initializes a few variables. Address 45D13E is where the fun begins. You will notice the call at 45D142 (CALL 402ACC) is repeated quite a bit throughout this routine - this is the price generator which is 'seeded' by the values in eax and edx. (esi stores the drug count - there are 13 in all)

45D13E 8B4304                  mov eax, dword ptr [ebx+04]	;set seed value
45D141 40                      inc eax				;add one
45D142 E88559FAFF              call 402ACC			;set price
45D147 0303                    add eax, dword ptr [ebx]		;modify price with fixed value
45D149 894308                  mov dword ptr [ebx+08], eax	;store price
45D14C B808000000              mov eax, 00000008		;seed price generator
45D151 E87659FAFF              call 402ACC			;set price
45D156 40                      inc eax				;do sod all
45D157 48                      dec eax				;perhaps set the Zero flag
45D158 7506                    jne 45D160			;goto cheap (buy) drug routine
45D15A C6431600                mov [ebx+16], 00			;set no cheap (buy) drugs
45D15E EB04                    jmp 45D164			;goto next
* Jump at Address45D158(C)
45D160 C6431601                mov [ebx+16], 01			;set cheap drugs (buy)
* Jump at Address45D15E(U)
45D164 807B1400                cmp byte ptr [ebx+14], 00	;if 0 then no super expensive drugs
45D168 0F8488000000            je 45D1F6
45D16E B814000000              mov eax, 00000014		;seed price gen
45D173 E85459FAFF              call 402ACC
45D178 40                      inc eax				;pehaps set Zero flag
45D179 48                      dec eax				
45D17A 757A                    jne 45D1F6			;goto no super expensive drugs
45D17C 807B1600                cmp byte ptr [ebx+16], 00	;see settings above
45D180 7474                    je 45D1F6
45D182 B802000000              mov eax, 00000002
45D187 E84059FAFF              call 402ACC
45D18C 6685C0                  test ax, ax			;and ax,ax (set message - Cops or Addicts)
45D18F 752F                    jne 45D1C0			;jmp to addicts message
The routine continues on, but this is where the decisions are made and this is predominantly where we will have to rewrite the code. I first began modifying the jumps at 45D17A and 45D17C (by NOPping them), but this was clumsy and did not force the pricing every second turn as I wished it to.

So I decided that I would need to set up a variable which would flip-flop every second turn (probably from 0 to 1 to 0, etc) which i could use to force a low or high price for drugs. Looking at the code it seemed that it would be possible to use a global variable pointed to by [ebx + offset]. A quick scan of the code reveals that the following variables are used by the program:
	[ebx+04]		dword
	[ebx+08]		dword
	[ebx+14]		byte
	[ebx+15]		byte
	[ebx+16]		byte
My first hunch was to try something in the middle (ie not reuse and existing variable, so I chose [ebx+0C] as my new variable. The next step was to decide where to put our new code. The idea was to modify the program by replacing existing code, but what?

Looking at the code section above I decided that i could replace all the conditional jumps and intervening code. This means the code from 45D156 to 45D181, which gives us 43 bytes to play with.

So I wrote my routine, and then had to translate it into Opcodes to check the length and make sure that it would fit into the required space. For those of you that have done your homework and traced this routine through with a debugger (I used WDasm, 'cos I foolishly installed NT Service Pack 5 which has screwed with my version of SoftIce :( ) you will realise that the routine loops 13 times - once for each drug on the list, and that the base pointer (ie ebx) is adjsuted at the end of this routine to point to the price data for the next drug. This is good, since it means that the variable we assign a 0 or 1 to [ebx+0c] will be preserved for each turn.
My new code looks something like:

45D156	cmp byte ptr [ebx+0C], 00	;check variable
45D15A	je 45D162			;flip it
45D15C	mov [ebx+0C], 00		
45D160	jmp 45D166
45D162	mov [ebx+0C], 01
45D166 	cmp byte ptr [ebx+0c],00	;if variable = 0 then no exp drugs
45D16A	je 45D1FC
45D170	mov eax, 14			;seed pricing gen (existing code)
45D175	call 402ACC
45D17A	inc eax
45D17B	dec eax

The code for this looks as follows:

45D156	807B0C00
45D15A	7406
45D15C	C6430C00		
45D160	EB04
45D162	C6430C01
45D166 	807B0C00
45D16A	0F8486000000			;32 bit jmp
45D170	B814000000
45D175	E85259FAFF
45D17A	40
45D17B	48
So now you can patch the program using PSEdit (or whatever else you fancy) and run it.

You have a problem? So did I! It seems our variable [ebx+0c] is used elsewhere and our use of it causes an overflow and the program crashes (luckily whoever wrote this code initially put in an error handler routine so we wont cause too much damage...)

OK, wrong variable - how about we use one of those byte variables already used for our own purposes? I chose [ebx+16] to accomplish this task - we keep the patch the same, just modify the 0C bytes to 16 in the code above. Patched? Good, now try this...lots of messages and hugely expensive drug prices - but wait - we go to a new day, and we have no drug prices, no drugs, nothing!! Odd! Take the train somewhere, new day and horrendously expensive drugs. So half our job is done.

I spent a lot of time tracing through this routine and the program trying to find out why this happened (ie tracking the cause) but I could not find it (well, I didn't look that hard). Logic suggested that our old [ebx+16] variable must have been causing this, since this was all that we modifed. I thought about this and decided to change the condition checks from 0 and 1 to 2 and 3. Well, what do you know, it worked!! The game opens with cheap drugs, the next day you have expensive drugs, and the day after cheap drugs. Whoo-Hoo!!!

Now, before you go and try for those high scores you might like to NOP the jumps at 45D20E and 45D208 and also modify 45D1F6 to read:
45D1F6  807B1602
45F1FA  756B
so that you will be guaranteed cheap cheap drugs on your fisrt turn. Now, go bombard to web site with your high scores (they have a register there...)

Final Notes
This is my first real attempt at truly reversing software, apart from some lazy crappy cracks, 
and i must say that it has taught me a lot when it comes to understanding the function of various
items of code. It is a truly great feeling when it suddenly dawns on you how and why everything is
happening. There is always method in the madness....

Ob Duh
I wont even bother explaining you that you should BUY this target program if you intend to use it for a longer period than the allowed one. Should you want to STEAL this software instead, you don't need to crack its protection scheme at all: you'll find it on most Warez sites, complete and already regged, farewell, don't come back.

You are deep inside reverser's page of reverse engineering, choose your way out:

redhomepage redlinks redsearch_forms red+ORC redhow to protect redacademy database
redreality cracking redhow to search redjava-script wars
redtools redanonymity academy redcocktails redantismut CGI-scripts redmail_reverser
redIs reverse engineering legal?