BEGINNERS: Slowly cracking a paranoid protection
(The importance of a methodological approach and an 'hidden file' scheme)
by Indian_Trail
(20 November 1997)
Courtesy of fravia's page
of reverse engineering
Well, a very interesting lesson for beginners: serial, time, CRC... a nasty little protection scheme on a completely useless target. I may add that some of the 'minor' shareware games offer very interesting overprotections: some of these shareware authors have devised count downs, smearing techniques, annoying nags all over the place in order to protect programs that nobody in his right mind would ever come to the idea to use (not to mention the idea to register them). This is GOOD: beginners are well advised to buy a couple of magazine cd-roms with MANY of these pathetically programmed 'readers contributions'... they will have a LOT of crack material for next to nothing. For beginners there is nothing better, to flex reversing muscles, than these tiny overprotected programs :-)
Slowly cracking a paranoid protection
Serial numbers are very easy to crack. this is well known by most
programmer so therefore they do everything they can do bore the cracker
to death, making him fall asleep before he has fished anything. New
shareware programs also utilize time limits more than serial number and
some have hidden the registration dialogue so it must be enabled before
registering the program.
A friend asked me if I could crack a game for him that was protected
with a username/regcode protection and it turned out to be quite
an overbloated protection scheme, with a lot of string altering.
I used another approach than the usual bpx GetDlgItemText.
This method is very logical, yet it can take a while, for the beginners
among you, to figure out that you can use other approaches.
The Target is Sink Sub Pro written by Anders Wihlborg.
Available from:
http://www.gamesdomain.ru/directd/pc/windows/arcade/sspro.html
This is a simple (but quite fun) arcade game where you shall sink
submarines with a Swedish patrol boat. It doesn't offer deadly graphic
but it's a nice waste of time.
The first thing we'll do is to run sink sub and look for clues. A nag
screen pops up in the beginning reminding us of registering the
software. It also tells us that we can "Evaluate" sink sub for 30 days.
Here we have two buttons one is OK and the other one is Register. We
press ok for now. Lets look in the help file. Here we can read that it
besides the time limit also have disabled some levels. If we pay for our
license we can play 50 levels and get the highest rank. Its also says
under registering that we will receive a code based on our name after we
have paid our license, that will unlock the crippled features.
Before we proceed we must know some basics about debugging windows. In
dos we had interrupts that we put breakpoints on in windows we have API
function which we can breakpoint on. This means that we'll have to study
the Windows API reference to know what we can breakpoint on. If you have
any compiler for windows programming like Borland's C++ or Microsoft
Visual C++ you probably already have it. If you dont It's available from
the net AND from Micro$oft's Homepage.
Lets Register this Game:
As you can see when you choose register you are given two dialog boxes.
One for your name and one for your regcode. When we press ok the text we
entered in these boxes are passed to windows by some API function. A
quick glimpse in the API Reference we find that Getdlgitemtext(A) and
getwindowtext(A) can be used for that purpose. The (A) is used for 32Bit
programs. Sink Sub is 16Bit. OK let enter Softice and put a breakpoint
on Getdlgitemtext. If this doesn't work we will try getwindow text,
should that fail too we could try HmemCpy. Just study the API Reference
all you questions will be answered.
Bpx getdlgitemtext
As you read in the API REF some parameters are passed to getdlgitemtext
one of them is the address of the buffer where the text are passed. Enter
some words in the Name Box and some numbers in the Regcode box. Now when
Softice breaks we will be in the GetDlgItemText function to get out of
it we press f11.
6A65 push 0065
16 push ss
8D46D4 lea ax, [bp-2C] ;Username Stored Here
50 push ax
6A28 push 0028
9AFFFF0000 call USER.GETDLGITEMTEXT
57 push di ;Ice pops up Here!!
6A66 push 0066
16 push ss
8D46C0 lea ax, [bp-40] ;Reg code Stored Here
50 push ax
6A14 push 0014
9AFFFF0000 call USER.GETDLGITEMTEXT
16 push ss
68FD09 push 09FD
16 push ss
68B002 push 02B0
16 push ss
8D46D4 lea ax, [bp-2C]
50 push ax
16 push ss
68FE56 push 56FE
As you see you'll need to scroll up a bit to see the parameter passed to
GetDlgItemText. Now dump the address where the regcode is stored.
D bp-40
You should see your code. The normal approach would be to breakpoint on
that adress and see what's done with it and look for the real serial
number that the computer calculated for us. That approach is what I call
'Serialnumber fishing'. We could try that approach. Here's what happens.
Our code is copied from ds:7B40 to ds:7A9C
Our code is changed from numbers to letters by a routine which writes the
new calculated code at ds:7A9C
The length is calculated at least five times.
The new code consisting of letters are changed to a new number
etc
etc
I personally got bored to death using this method. You'll grow old and
ugly before you'll get to the compare where the real serial number is
displayed. There are at least four different codes made from our input
which is being transferred all over the town and the length of every code
is being calculated at least three times. I'm kinda lazy and eager to
crack this program. when I have cracked it I can relax and study the
protection and break it down to pieces, but until then I just want to
overview the scheme to get a hum of what is going on. I think that the
author did this to confuse the cracker and make him bored. Guess what he
succeeded. what we see here is the two locks on the front door, lets see
if the backdoor is open.
Disable all breakpoints and you'll be staring at messagebox telling you
that you have entered an invalid serial number. Aha! That's the programmer's
mistake (as you are about to see). Lets put a breakpoint on the API
function MESSAGEBOX. Enter some new values in the boxes and press ok.
Softice pops up in the API function MESSAGEBOX step out of it and scroll
up a bit 'til you see this.
56 push si
16 push ss
68BF11 push 11BF ;Registration Failed.....
16 push ss
683E12 push 123E
6A10 push 0010
9AFFFF0000 call USER.MESSAGEBOX
EB1A jmp 382D
If you dump ss:11BF you'll see the message the Messagebox told us. As
you can see there is a lot of messagebox functions. Here is the whole
routine:
9AFFFF0000 call USER.DIALOGBOX
0BC0 or ax, ax
7466 je 382D
833E4A5600 cmp word ptr [564A], 0000 ;A Flag
7412 je 37E0 ; correct code entered if
56 push si ; jump to beggar off
16 push ss
68DD10 push 10DD
16 push ss
681E11 push 111E ;Registration Successful
6A40 push 0040
9AFFFF0000 call USER.MESSAGEBOX
EB4D jmp 382D
6A09 push 0009
E8DFDE call 16C4
83C402 add sp, 0002
833E485600 cmp word ptr [5648], 0000
7412 je 3801
56 push si
16 push ss
683811 push 1138
16 push ss
68A911 push 11A9
6A10 push 0010
9AFFFF0000 call USER.MESSAGEBOX
EB2C jmp 382D
56 push si
16 push ss
68BF11 push 11BF
16 push ss
683E12 push 123E
6A10 push 0010
9AFFFF0000 call USER.MESSAGEBOX
EB1A jmp 382D ;Here's where you land
Look at this. A flag is compared with 0. If the value at [564A] is not
zero we will get alot of evil messsages. Alright Lets see where this
flag is set.
BPMB SS:564A
We will land here:
lea ax, [bp-48] ;Our code
50 push ax
16 push ss
8D46A4 lea ax, [bp-5C] ;correct code
50 push ax
9AFFFF0000 call USER.LSTRCMPI ;who could have figured?
F7D8 neg ax ; returns zero if match
1BC0 sbb ax, ax
40 inc ax
A34A56 mov [564A], ax
833E4A5600 cmp word ptr [564A], 0000
7403 je 1D50
E99400 jmp 1DE4
Look what we found! An echo of the correct Code (HIP HIp HURRAY). Isn't
this
odd. A programmer that tries so hard to confuse the cracker by coping
and altering our input string and then he use A simple LSTRCMPI function
to determine if our strings are correct. I Must admit I never thought he
could be that Stupid. It could perhaps be that He never thought we would
try a bpx LSTRCMPI. Well Well... you learn as long as you live.
Let's try to use the correct code as regcode.
I was as surprised as you, it doesn't work.
Hmmn!
Let us put a breakpoint on the line above call USER.LSTRCMPI. Run anew
and see what [bp-48] is.
D bp-48
Strange it's our fake code, but we entered the correct code. Ok lets
change the Neg AX and SBB AX to NOP's. I know it's not a good idea to
use NOP's but we are just doing it to check if we get registered.
There's probably some mirror checks so lets keep our BPMB ss:564A. As
you'll discover there are six mirrors check, just change the NEG AX and
SBB AX,AX where needed and continue execution. Look we got registered.
So lets change the exe file.
When you try to run the patched file you'll get an evil message that
claims one of sspro files has been damaged. Where did he get that
from??!??. Oh well it seems that there is a patch check as well that has
to be cracked. Man this programmer must be paranoid. Oh well lets go to
work.
BPX on MessageBox. Here is where you'll land:
55 push bp
8BEC mov bp, sp
FF7604 push word ptr [bp+04]
16 push ss
684460 push 6044
16 push ss
68824C push 4C82
6A10 push 0010
9AFFFF0000 call USER.MESSAGEBOX
C606446000 mov byte ptr [6044], 00 ;We are here (after F11)
5D pop bp
C3 ret
So this was a small routine and it must be called from somewhere. We
trace further and proceed with ret.
56 push si
E8CD0D call 1431 ;????
83C402 add sp, 0002
0BC0 or ax, ax
7538 jne 06A3 ;well if ax is non zero we skip the
16 push ss ;error routine
687903 push 0379
E84EB0 call B6C0
83C404 add sp, 0004
6A00 push 0000
E82AB0 call B6A4 ;display error message
83C402 add sp, 0002
As you see we have a JNZ after a call 1431. If ax is zero we get the
error message. Lets take a look at the call 1431. The first conditional
jump is right after a call, very suspicious.
E85A1E call 32B3
0BC0 or ax, ax
7504 jne 1461 ;ax non zero and we are good guys
33C0 xor ax, ax
EB79 jmp 14DA ;this jump takes us out of the ;routine without setting AX to 0001
The JNZ 1461 make us leave the routine with ax set to 0001. This is
good, lets invert that jump, change it to a JMP 1461. And let the
program run. Wow it worked we didn't get the error message and we are
registered.
Ok now I am Relaxed, now I can go for a correct serial number and see why
it didn't work. I'll spare you unnecessarily code. What I did was that
I put a breakpoint on bp-48 which was the address where our input was
stored for the LSTRCMPI.
I found out That it got that code from a file in my window directory
called queparam.inf.
Looking at that file with a texteditor I saw the first change from
my input to letters (the first altering with the input code).
So I simply erased that code in queparam.inf.
Changed back sspro.exe to an uncracked file and tried again to register
it with the serial number found at bp-5C.
It worked fine.
Greetings and thanks to the +HCU and +ORC
(c) Indian_Trail 1997. All rights reversed
You are deep inside fravia's page of reverse engineering,
choose your way out:
homepage
links
anonymity
+ORC
students' essays
academy database
tools
cocktails
antismut CGI-scripts
search_forms
mail_fravia
Is reverse engineering legal?