Reversing an algorithm to ensure gameing success and fame on the internet.
Reversing the Drug pricing algorithm in Dopewars version 1.2
08 October 1999
||Courtesy of Reverser's page of
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
Reversing an algorithm to ensure gameing success and fame on the internet.
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.
PS Edit (or any other hex editor)
and that'll about do you...
Size: 526,848 bytes
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:
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:
45D16A 0F8486000000 ;32 bit jmp
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:
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...)
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....
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:
how to protect
how to search
Is reverse engineering legal?