²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²
    ²²    ____                     __       __           ²²ßÛ
    ²²   /  _/_ _  __ _  ___  ____/ /____ _/ /           ²² ÛßÛ
    ²²  _/ //  ' \/  ' \/ _ \/ __/ __/ _ `/ /            ²² Û Û
    ²² /___/_/_/_/_/_/_/\___/_/  \__/\_,_/_/             ²² Û Û
    ²²   ____                          __          __    ²² Û Û     
    ²²  / __ \___ ___ _______ ___  ___/ /__ ____  / /____²² Û Û 
    ²² / /_/ / -_|_-</ __/ -_) _ \/ _  / _ `/ _ \/ __(_-<²² Û Û
    ²²/_____/\__/___/\__/\__/_//_/\_,_/\_,_/_//_/\__/___/²² Û Û
    ²²                                                   ²² Û Û
    ²²      Web: http://www.ImmortalDescendants.com      ²² Û Û
    ²²      Author: Lord Soth                            ²² Û Û
    ²²      Date:  11/03/1999 (mm/dd/yy)                 ²² Û Û
    ²²      Topic: A DOS paper protection, some basics	 ²² Û Û
    ²²      Level: Basic (as I said :)                   ²² Û Û
    ²²                                                   ²² Û Û
    ²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²² Û Û
      ÛÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÛ Û
        ÛÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÛ

A DOS based paper protection, a trip down memory lane :)
=========================================================

Introduction
=----------=
Ok, first of all, hello to everyone reading this text, the time is about
20 mins after midnight here, and yours truly is pretty beat, so I'll
be brief :)
The old famed DOS paper protection is one of the oldest protection primitives
that ever graced the computer/software world.
This protection, back in the early days posed a real threat to non-crackers
because those not possessing RCE skills couldn't usually obtain cracks for
these simple protections because of the internet wasn't that developed or
whatever reason you can think of.
In the end, this protection was very potent just because of that, and it was
pretty annoying, I remember it myself (before I got into cracking).
So, we said this is a primitive, but as +ORC stated in his excellent essays
on paper protections, a lot of today's protections still rely heavily on this
simple protection.

What we'll try to accomplish in this short essay is a comparison between a
DOS paper protection and today's normal serial protection. Also, this will
give us a good chance to review some differences in approach when cracking
in DOS as opposed to the linear memory map of Winblows.

The target selected is not hard to reverse or crack so this will just be a
demo crack, and most of you will not even want to follow it with the
program running. If any of you still want to try going over it, please contact
me and I'll give you a copy of the game.

Target : Empire, the WarGame of the century by Mark Baldwin, around 300KB..
Tools  : SI 2.8 (my choice for DOS), Hiew (or any other hexeditor)

Ok, some approachs to this whole thing
=------------------------------------=

Ok, so first lets see what we're up against, after we unzip the game to our
destination folder lets do a simple test run and see whats going on.
Some beeping and we finally arrive to a screen asking us to enter word number
X from line number Y or something similar to that.
We can enter a word, and when it is incorrect the program will launch in
a demo mode to show us what this game is all about.
We can of course choose Exit, but that will not get us anywhere :)
After a few tries it also tells us that we have a pirated copy of the game
and it gives us a chance to redeem our conscience. We'll soon see who redeems
whom from what :)

Step 1 - finding the text string we enter in the box, in memory
=-------------------------------------------------------------=

Ok folks, I don't have to repeat why exactly this step is a VERY important
step in cracking any password/serial protection do I ?
Even so, I'll give a good and solid reason to do so, and it is because we
want to see how the program manipulates our input and then determine if to
proceed or not.
That of course is our final goal, to see how it determines if to proceed and
force it to proceed always.

So, if this was a Winblows program, a typical move would be to place some
BPs on APIs that retrieve text from dialog box controls (assuming we're 
sitting infront the registration dialog). This is all neat, but in old DOS
such important stuff did not exist!
Even though M$'s Win32 APIs is an overbloated interface, it does support
important features quite easily, at least that hehe
In our program we don't have that luxury, so how are we gonna go about finding
our text string ?

There are more than one way to do this. If in Winblows we knew the address of
where the string is about to 'show', here we will have to work harder to get
it.
Now since DOS doesn't support things like GetDlgItemTextA, programmers had to
write their own retrieving routines. This of course involved a routine to scan
the keyboard for keys pressed (so they could be displayed on screen and then
taken to memory).
So one might think if we put a BP on INT 16 (there are actually several 
services that can do the same job), we'll find where a char is taken and stored
in memory.
This however my friends might not be so trivial as you might think. This is
because the char can only be used for display purposed and does not get stored
untill we click the OK button, or because the programmers incorporated their
KB routine into the normal interrupt routines that gets called a lot of times
per second :)
This last method is mostly used in games to get keyboard input. So if the
programmers coded such a routine, why not use it for this too ?
This makes our lives somewhat more annoying because we'll have to trace some
more code to determine where the string chars are stored (probably somewhere
in the caller's data segment). The last tracing and sniffing can sometimes be
very annoying/difficult, depending on the program involved.
This is a viable option, but lets not overlook more simple ways of doing the
same exact job!
If we were to enter a string that wouldn't have a chance to appear in the
computer's memory we'll be able to search it, plain and simple!
This also works in Winblows too, and preferably after a call to GetWindowText
and equivalents.
An immediate problem arises, since DOS does not have a FLAT memory module,
like Winblows has, we are left with the task of guessing in which segment this
string is at.
Lets type something unusual into the box, and then pop SI, and inside start the
search. A good place to start would definately be the current DS (Data Segment)

Why you ask ? this is because 16 bit routines *usually* don't require much code
to accomplish what they need to do (especially not something as simple as this
routine's job).
So if we'll search our string in SI : s ds:0 l ffff 'STRING'.
This line above looks in the current Data Segment from address 0 to FFFFh,
which is the whole segment, for the STRING string.
If any results are found, and here we will find only one (jee what a surprise!)
, the debugger will list their addresses.
Now lets display it so we can look at it with our own eyes : D xxxx:yyyy
Notice here that we are using segment addressing, this is of course because
we are in 16 bit mode (DOS).
SI though has the ability to display memory in any segment we want, so even if
we are in a different segment, we can always view data in any segment we like.
Ain't it nice of NuMega ?? :)

Step 2 - figure out what the program is doing with our input
=----------------------------------------------------------=
Alrighty then, we have a few options here. We can try tracing code and 
figure out whats going on, and this option is pretty good if the code that
manipulates our input is nearby, OR in the case that there is a certain
check on it. For example, when cracking the serial registration dialog of a
Winblows application you might put BPs on the input you put in the dialog
but only to discover that the only thing the program is doing is check the
length of the string!
Suddenly it pops a message box saying the registration information is invalid!
How come ? I'll tell you, maybe there has to be a minimum or maximum length
for the input, and if that condition is not met, there is no need to start
calculating the serial out of it!
In this case tracing code after we break on the first reading of the input will
probably be good to discover traps such as this.
However, back in our game, this is not the case, and we can set the BP:

bpm xxxx:yyyy r

Setting a BPM on that address for read access (the first char is needed, nothing
more actually). Lets continue execution and we'll immediately land in SI.
What we're looking at is a REPZ SCASB which is a loop to measure a strings
length, I'm sure you've all met it before. If not, trace it a bit and see
how the registers are handled.
We'll continue some tracing only to find out that this string length value is
placed somewhere and then we go back with a RETF.
Ok, now what ? after the RETF we don't see anything suspicious, so lets continue
the execution and see what SI will break on next :)
F5 and viola, we're back in SI. This time, we're stuck on a REPZ MOVSW. This
as you all know will move a string word (MOVSW) from DS:SI to ES:DI, and then
change SI and DI in incrememnts of 2 (because its a Word), according to the
direction flag's status. Just some basic Asm for you.
Lets quickly display the area pointed to by DS:SI, and we'll see our string
copied to there, and the remaining bytes. Afterwards it will remove any spaces
from the end of the string, but that is totally irrelevant to us.

So, now that the string has changed position in memory, it would be a good idea
to disabled the previous memory BP and place a new BP on the new location.
Lets continue and see what else SI will break on (this is starting to be fun!)
hehe

Immediately we land in something that looks like this :

			MOV AL,[BX]			;get char, this pops the BP
			OR AL,AL
			JZ 0C19
307D:0C08	SUB AL,61			;reduce ASCII of 'a'
307D:0C0A	CMP AL,1A			;check we are not above 'z'
307D:0C0C	JAE 0C12			;if we are, no good, bug out
307D:0C0E	ADD AL,41			;add 'A', making letter a capital letter
307D:0C10	MOV [BX],AL			;store back
307D:0C12	INC BX				;next plz :)
307D:0C13	MOV AL,[BX]			;get next char
307D:0C15	OR AL,AL			;is it the end ?
307D:0C17	JNZ 0C08			;no ? go back and convert this char too

Alright, this looks very suspicious right ?? WRONG!
This if you don't recognize is just a routine to convert a string from lowercase
to uppercase. It does it byte by byte too, see how cool it is :)
So , we gather this is not the right place to be at, and thus we'll continue
in hopes of finding what we want (hope has nothing to do with it really hehe)

So, ANOTHER F5, and SI breaks once more!! How amazing, it even looks the same
way the above routine looks, well, loo!, it IS the same, so annoyed at the
disturbance, we'll press F5 once again, and now comes a good part, one we've
been waiting for :-)

Now I'd like to take this opportunity to mention that since this is a text
string, it has nowhere to hide, and thus we can ALWAYS find it in memory before
any manipulation is done on it, and so far, nothing special has happened except
it got converted to uppercase.

However, now this is about to change.
Ok, lets back track a little to the paper protection scheme. We know that the
program has to somehow compare our input with the right word from the manual.
However, is the manual is stored in the program somewhere ? are the right words
stored in the program somewhere too ?
Yes, you can SEARCH for meaningfull words, but I guarantee you won't find any.
In most cases this is done so that you won't be able to see the right codes.
In addition it would be easier to find the right 'codes' just trying to reverse
the comparison routine, we'll see this soon.
Ok, how does the programmers hide the codes from us ? they can encrypt them!
Or they can manipulate the ASCII string somehow (kinda like encrypt tho hehe)
In the following snippet of code (our latest BP), we'll see just that :

1AA1:0716	LES AX,[BP+06]			;load address of string
1AA1:0719	INC WORD PTR [BP+06]	
1AA1:071C	MOV AL,ES:[BX]			;<<< This triggered the BP (get char)
1AA1:071F	CBW				;<<< and here WE ARE
1AA1:0720	NOT AX				;NOT the ASCII char
1AA1:0722	SUB AH,AH			;zero out high byte of value
1AA1:0724	ADD [BP-02],AX			;add the result to 'somewhere'
1AA1:0727	LES BX,[BP+06]			;next char's address
1AA1:072A	CMP BYTE PTR ES:[BX],00		;check if end of string
1AA1:072E	JNZ	0716			;repeat

So in this little calculation routine we see the loop takes a char, NOT its
value and add the lower byte to a variable (BP-02 in this case).
This is indeed worthy of our attention, it is a manipulation of some sort.
We'll keep that in mind and lets also write the result in BP-02 when the
loop is over (finished processing all the letters).
Well, a little tracing and we encounter a RETF (or was it RET ? hehe).
In any case, we go back to where we were called from.
Now this looks like this :

11F7:28B0	CALL 1AA1:06FB			;call the manipulation routine
11F7:28B5	ADD ESP,+04			;another DWORD on the stack, we are here!!
11F7:28B8	MOV CX,AX			;put something in CX
11F7:28BA	MOV AX,6			;6 in AX
11F7:28BD	IMUL WORD PTR [BP-10]		;multiply the contents of BP-10 by 6
11F7:28C0	MOV BX,AX			;also in BX
11F7:28C2	CMP [BX+0CAA],CX		;!!!AHHA!!!, this is it!, notice the value?
11F7:28C6	JZ 28CB				;good manual user
11F7:28C8	JMP 270B			;bad punk cracker

As you can see there is a little calcualtion here, something that depends
on the values returned from the previous call. Then at 28C2 we see our CMP
which will compare whats in memory and CX. Notice that CX holds the value
from the previous CALL that I asked you to remember. This value came from
our input and is checked again a value in memory!
Lets look at that memory location for a sec : d bx+0caa
This will show us something that looks like a table of Word values.
It doesn't seem to be just random data. In fact, it is most suspicious
because we saw a little calculation above the compare, and this might be
an index into a table of preserved values!!
Imagine they took every code we could enter and do that manipulation on them.
(I.E, the NOT and stuff from the previous snippet).
And walla!! We have found the way the programmers found to hide their codes!
They hide them by turning them into integers and when the user inputs a word
it will turn it in the same way. Now since the program knows where the 'good'
code's integer is in memory it will compare it to our manipulated string's
value and if they are equal that means everything is OK.
This eliminates the plain text code cracking some games are vulnerable to.

So, how will we go about patching this ?
We must remember to 'fix' the offensive conditions, IE, don't let the program
do the JMP 270B at line 28C8. Now lets imagine what would happen if the
right word would have been entered by a legit user. Then CX would hold the 
RIGHT value it is supposed to be. So why not we take the right value from
our table of integers and put it in CX just in case there is another check
somewhere ? This is good practice, although most protectionists are too lame
to backcheck the input.
So if we change the CMP [BX+0CAA],CX to MOV CX,[BX+0CAA], this will ensure
that the right value is in CX. Also this is just changing of the first byte
of the instruction (it is 4 bytes in memory, only need to change 1 hehe).
Now, we will also take care to that JZ so that we will always jump instead of
jump when equal.
Lets do the changes, use the A command, and let it run, and if you did it 
right you should see a dialog saying that the word is verified!
Continuing the game seems to go ok, doesn't it ? well it will :)

Now something has occured to me in all of this. I traced through the code,
(err more like stepped over) and I saw that I stepped over a CALL and
all of a sudden that verification dialog was up. I pressed ENTER and it
went away, and I went back to SI (JUST like modeless dialog boxes in Win!!)
This gave me another idea : since these are all "dialogs", I figured maybe
we can let the program think it asked the code and got a positive reply.
This is exactly nag removal from winblows.

Now, just a thought, in order for us to get back to the original caller
of the code dialog and be positive we're in the right place (returning
after a successful input), we will need to do a patch or change on the fly
and then return to the caller.
Maybe the program does not return to the same place on a bad input ??
So we'll do an on the fly patch and continue stepping till we get to a RETF.
(or use F12!! hehe)

Now we should see this :

0A96:0211	MOV ES,[7BDE]
0A96:0215	MOV WORD PTR ES:[636E],0001		;flag, should not be set
0A96:021C	CALL 11F7:268E				;call the input dialog
0A96:0221	OR AX,AX				;check return value, we are HERE!!
0A96:0223	JZ 0255					;if good, DONT jump, if not, JUMP

So, we see that if the function got a good input, AX equals 1 in return, so
this is something we'll need to make a permanent thing.
Also, if we let the program set the flag at 636E, the program will start as
demo, so lets skip over it.
I'll do that in the following manner :

0A96:0215	33C0	XOR AX,AX		;zero AX
0A96:0217	40	INC AX			;make it 1
0A96:0218	EB07	JMP 0225 		;(after the JZ at 0223)
0A96:021A	NOP
0A96:021B	NOP

As you can see the original line at 0215 will take up 7 bytes (Code on will
show this), so I replaced it with 7 bytes as well.

Now its time to make the crack and check it.
Backup the original file and patch in all the places I've mentioned.
This is done exactly like in Winblows. For DOS programs I suggest using
Hiew, it can search even by Asm instructions (it translates to op-codes).

Patch and run and the nag SHOULD be no more!! :)

Note: Its a good idea to patch the code check because maybe sometime in the
middle of the game there is another check of a code (seen it too often), so
its a good practice to make that check pass always (unless of course there
is another section coded in a different location).

To make a long story short, we have reversed this little game.
The main things to remember are that cracking in DOS might be much more
challenging. It all depends how the programmers hid the protection. They can
spread it over segments and you'll have a hell of a time coordinating between
all the segments and the data they contain!
Because of this DOS was always potentially better for protections than Winblows.

I hope you enjoyed this little lesson

For comments : 

LordSoth@ImmortalDescendants.com
lordsoth8@hotmail.com
or ICQ 5178515

Greetings goes to everyone I know, and those I don't, and since it is so late
I hope you guys will forgive me if I don't specify them all this time :)

Later boys and girls, and happy reversing!!

Lord Soth