Reverse Engineering Gettysburg
Demos can be more than they seem
Not Assigned
25 July 1998
by +ReZiDeNt
Courtesy of Reverser's page of reverse engineering
Yeah! That's another proof of the fact that 'time' on the web is more a matter of tides that slowly flow to and fro than of 'days' or 'hours' or whatever. I love strategic games and I cracked Gettysburg as soon as I got the first demo, because I noticed that all scenarii were published (and brutally and silently stuck inside our own harddisks) inside a demo that theoretically allowed you to play only a couple of them. Since the now almost forgotten times of "Panzer General", all 'strategical afecionados' reversers know from experience that MOST demos contain (and actually install on your harddisk) the COMPLETE gameset, only -somehow- crippled. My own patching of this game was anyway made on the quickie, and I found it interesting to publish -long ago- a sort of 'public contest' on my link page, and so we all got -finally- this nice work by +ReZiDeNt!
Gettysburg is a very good strategic game and if you'll reverse it a little on your own you'll be able to build -and play- some very interesting scenarii (it's great tactical fun -for instance- to give enormous might to one particular corp in both camps). Enjoy!
There is a crack, a crack in everything That's how the light gets in
( )Beginner (x)Intermediate ( )Advanced ( )Expert

If you thought demos were too crippled to bother reversing them, you might be surprised...

Reverse Engineering Gettysburg
Demos can be more than they seem

Written by +ReZiDeNt


A while back I saw a little snippet about Gettysburg on reverser's page,
and I was intrigued - most game demos are ridiculously limited, with huge
chunks of the program code and/or data missing - but it seemed that
Gettysburg might be complete. I quite like strategy games, and I happened 
to see a magazine with the Gettysburg demo on its cover CD, so I thought 
I'd give it a go, and sure enough, the results were quite interesting. 
Although the demo only allows you to play three scenarios, the data files 
for the rest of the scenario files (gettyXX.scn, where XX is the number of 
the scenario) seem to be there, almost complete...

Tools required

W32Dasm (or IDA)
A hex editor (e.g. UltraEdit)

Target's URL/FTP

Umm...I don't have a URL for this target, but it can be downloaded from several shareware/demo sites, AFAIAA.

Program History

Well, this game was apparently written by Sid Meir of Civilisation fame...
but I wonder who wrote the protection?

First make a dead listing of the target, lee.exe, using W32Dasm (or IDA if
you desire), as we will use this quite a lot. I strongly suggest that you
configure SoftICE to use the Universal Video Driver (check the corresponding
box in Display Adapter Setup). This requires DirectX 5.0 (which is installed
along with Gettysburg anyway if I remember correctly) and displays SoftICE
in a window on the screen rather than in full-screen mode. SoftICE seems to
lock up occasionly (on my computer at least) when stepping through
full-screen graphical programs (e.g. games using DirectX) if the Universal
Video Driver is not being used, so if the same thing happens to you give it
a try.

Anyway, let's get started. Browsing through the string references in the
dead listing, we come across an interesting reference:

* Referenced by a Jump at Address:004237A7(C)
:00423806 55                      push ebp

* Possible StringData Ref from Data Obj ->"PICKSCENARIO"
:00423807 68845A4A00              push 004A5A84

* Possible StringData Ref from Data Obj ->"menu"
:0042380C 68945A4A00              push 004A5A94
:00423811 E85ADA0100              call 00441270
:00423816 83C40C                  add esp, 0000000C

Setting a breakpoint at 00423806 and running Gettysburg, we find that it
snaps whenever we go to play a scenario - thus we confirm that we are indeed
on the right track. Paging down through the dead listing we see a call to
USER32!SetRect before another very interesting string reference catches our

* Referenced by a  Jump at Address:004238A6(C)
* Possible StringData Ref from Data Obj ->"(CD) "
:004238DE BF9C5A4A00           mov edi, 004A5A9C

This is of interest to us because all of the disallowed scenarios have the
prefix "(CD)" before their names in the scenario menu - so this further
confirms our suspicions that we are headed in the right direction. Scrolling
down a little more we come across the following code, putting any lingering
doubts out of our minds:

* Referenced by a  Jump at Address:00423A90(C)
:00423979 E8323E0400           call 004677B0
:0042397E A1183E4D00           mov eax, dword ptr [004D3E18]
:00423983 85C0                 test eax, eax
:00423985 750E                 jne 00423995
:00423987 83FD18               cmp ebp, 00000018  ; there are 24 scenarios
:0042398A 7D09                 jge 00423995       ; in Gettysburg...
:0042398C 0FBE8D085A4A00       movsx ecx, byte ptr [ebp+004A5A08]
:00423993 EB02                 jmp 00423997

* Referenced by a  Jump at Addresses:00423985(C), :0042398A(C)
:00423995 8BCD                    mov ecx, ebp

* Referenced by a  Jump at Address:00423993(U)
:00423997 B867666666              mov eax, 66666667
:0042399C 6A01                    push 00000001
:0042399E F7E9                    imul ecx
:004239A0 C1FA02                  sar edx, 02
:004239A3 8BC2                    mov eax, edx
:004239A5 C1E81F                  shr eax, 1F
:004239A8 03D0                    add edx, eax
:004239AA 8BC1                    mov eax, ecx
:004239AC 80C230                  add dl, 30
:004239AF B90A000000              mov ecx, 0000000A
:004239B4 88542419                mov byte ptr [esp+19], dl
:004239B8 99                      cdq
:004239B9 F7F9                    idiv ecx
:004239BB 80C230                  add dl, 30
:004239BE 8854241A                mov byte ptr [esp+1A], dl
:004239C2 8D542414                lea edx, dword ptr [esp+14]
:004239C6 52                      push edx
:004239C7 E8140B0000              call 004244E0    
:004239CC 83C408                  add esp, 00000008
:004239CF 85C0                    test eax, eax
:004239D1 0F84B5000000            je 00423A8C
:004239D7 83FD01                  cmp ebp, 00000001 ; check to see if
:004239DA 7C05                    jl 004239E1       ; the selected scenario
:004239DC 83FD03                  cmp ebp, 00000003 ; is an allowed one
:004239DF 7E09                    jle 004239EA    

The above code loops through each of the 24 (25 if you count from 1)
scenario files, prefixing the scenario name with "(CD)" if it is not one of
the three allowed ones. This code snippet is only called once (the first
time you view the scenario menu), and only affects the way the scenario
names are displayed (e.g. changing the jle instruction at 004239DF will
*not* allow you to play any scenario, but will rather cause all the scenario
names to be displayed without the "(CD)" prefix, even those that are not
allowed). However, because we are +crackers we can "feel" that we are on the
right track, and we know that the protection is around, so we keep looking
for a little longer...and we see that the below code is executed for each
scenario as well, after the previous check (and after adding the "(CD)"
prefix to the scenario name, if appropriate):

:00423A48 8B8424C4000000          mov eax, dword ptr [esp+000000C4]
:00423A4F 8B4808                  mov ecx, dword ptr [eax+08]
:00423A52 8D8C0CC4000000          lea ecx, dword ptr [esp+ecx+000000C4]
:00423A59 E8720E0500              call 004748D0
:00423A5E A1842C5100              mov eax, dword ptr [00512C84]
:00423A63 8A15B43E4D00            mov dl, byte ptr [004D3EB4]  ; load number
:00423A69 3BE8                    cmp ebp, eax                
:00423A6B 8895202C5100            mov byte ptr [ebp+00512C20], dl ; store it
:00423A71 7519                    jne 00423A8C

The memory around the location [004D3EB4] shows the name of the scenario
that is currently being processed, so setting a breakpoint at 00423A5E we
can see that each scenario seems to given a number (from 1 to 3) that is
stored at the location [ebp+00512C20], where ebp is the number of the
current scenario from 0 to 24 (0x18). This number does turn out to be of
importance to us later, but for now we will continue our exploration. Using
the dead listing to trace the path of execution after the above code, we
soon come to the following:

* Referenced by a  Jump at Address:00424056(C)
:00424079 33F6                 xor esi, esi
:0042407B 8D8C24BC000000       lea ecx, dword ptr [esp+000000BC]
:00424082 8935448B4B00         mov dword ptr [004B8B44], esi
:00424088 89352C8B4B00         mov dword ptr [004B8B2C], esi
:0042408E E8AD100500           call 00475140
:00424093 A1842C5100           mov eax, dword ptr [00512C84]
:00424098 8B0D183E4D00         mov ecx, dword ptr [004D3E18]
:0042409E 83F801               cmp eax, 00000001             
:004240A1 8BE8                 mov ebp, eax                 
:004240A3 7C05                 jl 004240AA
:004240A5 83F803               cmp eax, 00000003  ; allowed scenario?          
:004240A8 7E63                 jle 0042410D       ; jump if good guy!            

This check is almost identical to the earlier one that decided whether or
not to add the "(CD)" prefix to the scenario name, except that this one is
executed every time we select a scenario (using SoftICE we can confirm this)
- so this is the main "good guy/bad guy" jump! If the scenario you selected
was one of the first three, the scenario will load and you can play,
otherwise you are returned to the opening screen ("Can't do that,
General!"). The alert reader will quickly conclude that the jle instruction
at 004240A8 needs to be changed to a jmp to allow any scenario to be played.
This is true, but only partly. If you patch the program at the above
location you will be able to play *some* of the disallowed scenarios, but
not all. So there is obviously a second check further down the line - using
SoftICE we trace past the above check (after patching it) firstly with a
previously disallowed scenario that we can now play and then with a
disallowed scenario that we still can't play. This allows us to hunt down
the second check, shown below:

* Referenced by a  Jump at Address:00424198(C)
:004241F7 80B8202C510001       cmp byte ptr [eax+00512C20], 01   
:004241FE 745D                 je 0042425D              ; jump good guy!               
:00424200 8D8C24540B0000       lea ecx, dword ptr [esp+00000B54] 

Well, well, well. The value that was stored for each scenario in memory
location [scenario number+00512C20] at line 00423A6B is important, it seems.
If the number is 1 the scenario will run (once you've patched the check, of
course), but if it was 2 or 3 (the other possible values) it will not. I
must confess that I'm not entirely sure what the different values mean
(could they be the diffent days over which the battle was fought?)...but in
any case, if you change the je at 004241FE to a jmp you will be able to play
*any* scenario (assuming you've already patched the check at 004240A8 of
course). The only caveat is that if you select one of the previously
disallowed scenarios you will occasionly start with an empty battlefield,
and no troops to command. I haven't yet been able to acertain exactly why
this is, but I suspect it may have something to do with the fact that apart
from the three allowed scenarios, the scenario files are not complete -
presumably the program tries to randomise the missing data if it can't find
it, and sometimes messes up.

Of course, if you have the scenarios from the full game they will run
perfectly, no problems at all. Alternatively you could download one of the
scenario editors available and make your own scenarios, which would also run

Good Hunting,

July 1998

Greetz to: reverser+, for first arousing my interest in this target and then 
reminding me to write this essay, all +HCUker's and those on the VisAsm team
and of course +ORC, without whom there would be no +HCU...

Final Notes
I have to say that the protection on this demo is quite fact,
I'm inclined to think they *wanted* it to be cracked, for whatever reason
- they even included all the scenario files, just to make things easier!
However, at least it goes to show that you can't take anything for granted
when it comes to protections, just because it's a "demo" don't assume that
it isn't complete. In fact, I'm beginning to wonder about all those other
strategy game demos I have on old CDs...perhaps they would be interesting
to study as well :-)

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. Anyway I'm not sure if a complete 'ob duh' applies here: after all the demo of this game CARRIES (and installs in our harddisk) all scenarii, so why should not we use something that has been installed on our harddisks?

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

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