May 1998
"Add/Remove Cleaner V2.01"
( And Page Host V1.0  )
Win Code Reversing
by The Sandman 
Code Reversing For Beginners 
Program Details
Program Name: Addrmclr.exe
Program Type: Win'95 Utility
Program Location: Here or  Here
Program Size: 271K 
Tools Used:
Softice 3.2 - Debugger
W32Dasm V8.9 - Disassembler
Easy ( X )  Medium (   )  Hard (    )  Pro (    ) 
There is a crack, a crack in everything. That's how the light gets in.
Add/remove Cleaner V2.01
( And Page Host V1.0  )
Written by The Sandman
We're going to crack two programs in this essay. I'll  explaining how to crack Add/remover Cleaner and since the code is almost identical in their other program Page Host we can crack that too...:)

The author(s) of this utility can be found at:
The author says:

"This program was created in Delphi 3.0, version 1.0 was released on 6/15/97. It only took about 30 minutes to  complete. It was created after I realized I had about 50-70 bad entries to uninstallers in my Add/Remove Programs  Window. Version 2.0 was released on 2/1/98."
About this protection system
Registration is via selecting the 'Register' button once you've by passed the initial nag screen box that show's each time this program is run while unregistered.
Here you will be asked to enter:-

Registration  Name          :
Serial Number:
Once registered, the program saves the registration info within your System Registry file, at:
HKEY_CURRENT_USER\Software\ChemicalDistortions\Add Remove Cleaner
RegName  "The Sandman"
SerNum:    "T11132TE"
Don't be lame and use my registration serial number, read this essay and learn to create your own!
The Essay 
First things first, lets get a dead listing of this program,  we want to see where we're going and how best to get there.  Use W32Dasm to create our dead listing and when that's done lets check out the String Data Resources within this babe, you never know, it might have a single hard coded serial number for us to use..

OK, if you've checked the String Resources then you'll see there wasn't any likely serial numbers for us to use, never mind, it just means we will go onto plan 'B'.
Plan 'B' requires us to locate the 'Beggar off Cracker' routine, the one that tells us our serial no was invalid..

Did you find it?, it's located at:
:00434FE8 E9EBE1FCFF              jmp 004031D8
:00434FED EBF0                    jmp 00434FDF

* StringData Ref from Code Obj ->"Thank you for registering!"
:00434FEF B8BC504300              mov eax, 004350BC
:00434FF4 E8D7CFFFFF              call 00431FD0
:00434FF9 EB0A                    jmp 00435005

* Referenced by a (C)onditional Jump at Address: :00434F42(C)
* StringData Ref from Code Obj ->"Invalid registration information"
:00434FFB B8E0504300              mov eax, 004350E0
:00435000 E8CBCFFFFF              call 00431FD0

Look at this, our 'Thank you for registering' routine is here as well.  Now take a look at the above code snippet, lets see what information we can get from these two routines, starting with the:
'Thank for registering' message.

1.  There is no information available to us that tells us where in the program, this routine gets called!.  This tells us that it's highly likely that the program will use an 'indirect' address method, it will calculate the address by using a register with a known value then
adding a displacement value to get the final address.  In plain English this can be explained by this example:-

Suppose the eax register represents a letter that someone sent you, and that inside this letter is the full postal address of where you can collect your 1st prize of £100,000 for winning the lottery.

mov ecx, dword ptr [eax] ;First we 'take' the letter,
                         ;this is the mov part of this

                         ;We 'open' this letter, this is the
                         ;ecx part of this instruction.
                         ;We then 'read' what the letter to
                         ;to see what kind of letter it is,
                         ;this is the dword ptr part of this
                         ;'Inside' this letter is the
                         ;telephone number of the person
                         ;who will give us our cheque.
                         ;This is the [eax] part of our

call [ecx+44]            ;Dial the telephone number by first
                         ;adding 44h (the dialing code to
                         ;the telephone number we've just
                         ;'read' from our letter.

2. From the mov eax, 004350BC instruction we know where this message is stored in the computer's memory while the program is running.

'Invalid registration information' message
1. We can find out where within the program this routine is called from, in this particular case if we examine the dead listing at: 00434F42 we should see this line:-
:00434F42 0F85B3000000            jne 00434FFB ;If serial No is wrong then jump
                                                                                        ;to the routine at memory loc
                                                                                        ;00434FFB  and show the
                                                                                        ;Beggar off cracker' message.
                                                                                        ;continue with the next
                                                                                        ;instructions and update the
                                                                                        ;Registry file with user Name &
                                                                                        ;Serial Number.

Some of you might see a *possible* way to *crack* this babe with the jne instruction, by simply Nop'ng (90h) the whole instruction so that the program will ALWAYS continue on
and update the System Registry file with our user Name & Serial No.  If you thought this then your beginning to think like a *cracker* but if we could understand Assembler then a closer examination of how of the surrounding code associated with this program's protection system *might* show you that this method of attack won't work.  However, as newbies we won't know this, but while 'testing' our *crack* we shall see the beginnings of yet another way to crack this program, one that looks very promising.

Enough talking, lets do get into this program's code and place a Softice breakpoint at location: 00434F42
Run Add/Remove Cleaner and go into the 'Registration Screen', and type in your User Name & a fake serial number.

Before pressing the 'Done' button press 'Ctrl-D' to re-enter softice, we want to try and break into the program's code. Normally we can set a breakpoint on messageboxa or messagebox system functions but it won't work in this case, so we will use the hmemcpy function instead.  Hmemcpy is a system function that just about every program that I know uses and which, is used in to copy information (such as text) from one memory location to another.

Type: bpx hmemcpy then x to return back to Add/Remove Cleaner.

Now you can press the 'Done' button.
Almost immediately softice breaks and since we need to get Softice back into target program's code we now press the following keys in Softice.
F11 then F12, F12, F12, F12, F12, F12

To locate our our jne 00434FFB instruction at offset 00434F42 we now type:
u 00434F42  this will display the code at this memory location.

Now we type bc * to clear all of softice's breakpoints then type bpx 014F:00434F42 to set a new breakpoint on our jne 00434FFB instruction.  Now type x to leave Softice so that the program runs as normal and display's the 'Invalid Registration Information'.
Click 'OK' to clear this messagebox then press the 'Done' key again, we want to re-run the program's Protection system again so that Softice can break at the moment where the program decides to either go and print the 'Beggar off cracker' message or to update our System Registry file with our User details.

At this point Softice is telling us that if we continue the program from here it will jump to our 'Beggar off cracker' message routine, well we don't want that to happen, so we will type r eip=00434F48 which in plain terms simply tells your computer to 'ignore' this jump instruction completely and begin execution FROM the next line below the jump instruction. This is almost exactly what would happen IF we had Nop'd (90h) this jump out.

:00434F42 0F85B3000000            jne 00434FFB ;Softice 1st stopped here
:00434F48 B201                    mov dl, 01 ;now we begin here
While we're here, lets examine the important sections of code we're about to analyze, step by step using the F10 key.. Begin pressing the F10 key UNTIL you get here.

:00434FBA  mov ecx, dword ptr [ebp-0C];place in the ecx register the
                                      ;memory location of our 'fake'
                                      ;serial number

:00434FBD  mov edx, 004350AC          ;place in the edx register the
                                      ;memory location of the text 'Sernum'
:00434FC2  mov eax, dword ptr [ebp-08];
:00434FC5  call 0043295C              ;Update the System registry File.

If you were to now let the program run as normal it will display the 'Thank you for registering' message, however, the program is still unregistered.  All we've done is to get the program to save our User name and 'fake' serial number to the system registry file but the program knows it's still invalid and so will ignore this entry and proceed as though it's still unregistered.

Take a look at this line again:-
:00434FBA  mov ecx, dword ptr [ebp-0C];place in the ecx register the
                                      ;memory location of our 'fake'
                                      ;serial number

Here's where the problem lies, the program is saving to the System registry file our 'fake' serial number instead of the 'real' one.  This is common practice in *almost* every program that uses a serial/registration key, and is just one of many 'little' barriers the programmer will put in our way.  Learn and study these barriers well, it will save you a lot of wasted time.
What do we need to do now?.  We could 'patch' this line so that it 'read's the 'real' serial number instead of the one typed in by the User, but if we do that then we will ALSO have to either Nop (90h) out the whole of the jne 00434FFB at memory location 00434F42
OR change the jump address so that it 'jumps' to line next instruction below, instead of to the 'Beggar off cracker' routine in order to make this *crack* work.

Since 'Key Generators' are quite popular at the moment lets crack this babe and turn it's protection system into a useful aid to registering it..:)

Before we can anything else we MUST locate where in memory the program creates the 'real' serial number, this is vital if we are to *crack* this babe.
Let us once again think about what we have so far done.  We located the routine that display's our 'beggar off cracker' message and through that, we back-tracked through the code to locate the jne 00434FFB instruction at memory location 00434F42, so far so good.  We've established that this jne instruction decides which message to show the User (you and me) depending on wether the serial number we entered was valid for the User Name we chose to use.  So it looks clear then that we must back-track a little further through the program's code to find out where it checks our 'fake' serial number against the one that is generated for the User Name we used.  In our dead listing of this program If you look at the section of code ABOVE  the jne 00434FFB instruction you will see this section of code:-
:00434F1C     mov eax, dword ptr [ebp-14]
:00434F1F     push eax
:00434F20     lea edx, dword ptr [ebp-0C]
:00434F23     mov eax, dword ptr [ebx+000001E8]
:00434F29     call 0041AE68
:00434F2E     mov eax, dword ptr [ebp-0C]
:00434F31     lea edx, dword ptr [ebp-1C]
:00434F34     call 00406698
:00434F39     mov edx, dword ptr [ebp-1C]
:00434F3C     pop eax
:00434F3D     call 00403AC0
:00434F42     jne 00434FFB
Since this code comes before our jne instruction it's highly likely that we will find the location of our 'real' serial number.

If your not already in Softice then press 'Ctrl-D' then type bc * to clear away any previous breakpoints in Softice then type: bpx 014f:00434FC to create an new breakpoint.  Then x to leave Softice.
Re-run the 'Registration Screen' again, type in a handle/name and for the serial number type in some random characters of your choice.  Press the 'Done' key to finish.
Wham, Softice breaks as expected at memory location 00434F1C.

So now use the 'F10' to single step through these instructions until you get to the jne 00434FFB.  After each line you execute type D followed by eax or edx depending on which one of these registers is used.


Once you've executed this line: :00434F1C     mov eax, dword ptr [ebp-14] you will type: d eax

Then when you execute this line: :00434F20     lea edx, dword ptr [ebp-0C you would then need to type: d edx

We're looking for something that resembles a serial number, a sequence of characters consisting of numbers or letters or both. By typing d followed by a register name we're 'seeing' what these registers hold as they are processed by the target program.
OK, if you've examined this code (you might need to do this once or twice with DIFFERENT User names to make sure) and taken notes, here's what you should have for this section of code.
:00434F1C     mov eax, dword ptr [ebp-14] ;eax = the memory location of our
                                          ;'real Serial No
:00434F1F     push eax                    ;Save eax address for later use.
:00434F20     lea edx, dword ptr [ebp-0C]
:00434F23     mov eax, dword ptr [ebx+000001E8];
:00434F29     call 0041AE68               ;eax = length of our fake serial

:00434F2E     mov eax, dword ptr [ebp-0C] ;eax=the memory location of our
                                          ;fake serial number.

:00434F31     lea edx, dword ptr [ebp-1C] ;2nd location of our fake serial

:00434F34     call 00406698               ;Returns with:
                                          ;edx = end of our serial Number

:00434F39     mov edx, dword ptr [ebp-1C] ;reset edx to start of our fake
                                          ;serial number.

:00434F3C     pop eax                     ;Restore eax so now points to
                                          ;back to the memory location of
                                          ;of our 'real' serial number.

:00434F3D     call 00403AC0               ;Now check both the fake & real
                                          ;serial numbers.
                                          ;Returns with:
                                          ;edx=Length of our fake serial No
                                          ;eax=Length of our real serial No

:00434F42     jne 00434FFB                ;jump if serial No's not equal.
Right, we found out where our real serial No can be found, but more importantly than this we know HOW the program is able to retrieve this regardless of where in memory it is. It uses the mov eax, dword ptr [ebp-14] instruction to locate the serial No so why don't we use this instruction as well for our *crack*.
Where shall we use this instruction?, well, if we deiced to Nop (90h) out the jne 00434FFB instruction at memory location 00434F2 we could then make the program save our 'Real' serial number when it updates our System Registry file, instead of it saving our 'fake' serial number by default.
Or, we can turn this babe into our own Serial Number Generator when the User gets the serial number wrong. It will then churn out 1000's of valid serial numbers for us to use..:)
It's settled then, that's what we're going to do..

Locate the 'Invalid registration Information' routine.
* StringData Ref from Code Obj ->"Invalid registration information"
:00434FFB B8E0504300              mov eax, 004350E0
:00435000 E8CBCFFFFF              call 00431FD0

You see that mov eax,004350E0 instruction, well as explained earlier it 'points' to that 'beggar off cracker' message, so lets change it so it prints the 'real' serial number instead.

Our new routine now looks like this:-
* StringData Ref from Code Obj ->"Invalid registration information"
:00434FFB 8B45EC                  mov eax, dword ptr [ebp-14]
:00434FFE 90                      Nop ;Spare empty byte
:00434FFF 90                      Nop ;Spare empty byte
:00435000 E8CBCFFFFF              call 00431FD0

Job Done.....
The 'Crack' 
Load up addrmclr.exe into your favorite hex editor and SEARCH for the hex string: "FFEB0AB8E0504300"

000343E0 45F8E879 DCFCFFC3 E9EBE1FC FFEBF0B8 E..y............
000343F0 BC504300 E8D7CFFF FFEB0AB8 E0504300 .PC..........PC.
00034400 E8CBCFFF FF33C05A 59596489 10684750 .....3.ZYYd..hG

Now REPLACE the following HIGHLIGHTED bytes with:
000343E0 45F8E879 DCFCFFC3 E9EBE1FC FFEBF0B8 E..y............
000343F0 BC504300 E8D7CFFF FFEB0A8B 45EC9090 .PC.........E...
00034400 E8CBCFFF FF33C05A 59596489 10684750 .....3.ZYYd..hG
Final Notes 
I found this program quite interesting to follow, I know I've only scratched the the surface in what *cracks* can be applied to it so I'll leave it to you to see if you can find some more.  Hint, you could try examine the code that runs at the beginning when the program is first run, perhaps where it checks to see if there is a valid serial number for it to read?.
One last item of news... The same author has another product called Page Host V1.0 which allows you to use your computer as a server, so anyone knowing your IP address can access your computer online just as though it was a normal web server.
They use almost an identical protection system as Add/Remove Cleaner so cracking it is a doddle.

Load Pagehost into your  hexeditor.
Search for:= 'FFEB0AB8E0624400" then
Replace   := 'FFEB0A8B45E89090"
My thanks and gratitude goes to:

Fravia+ for providing possibly the greatest source of Reverse Engineering
knowledge on the Web.
+ORC for showing me the light at the end of the tunnel.

Ob Duh 
Do I really have to remind you all that by buying and NOT stealing the software you use will ensure that these software houses will continue to  produce even *better* software for us to use and more importantly, to continue offering even more challenges to breaking their often weak protection systems.
If your looking for cracks or serial numbers from these pages then your wasting your time, try searching elsewhere on the Web under Warze, Cracks etc.

 Next   Return to Essay Index   Previous 

Essay by:          The Sandman
Page Created: 28th May 1998