Serializer

Reconstruction of a deadlisting

by Harlequin

  March  2001

 

  

Tools Used:

 
 W32Dasm V 8.93
ProcDump
Uedit Text/Hex Editor
Softice (briefly:-)

 

 

Introduction

A simple name serial crackme written by Code_Inside. Available at the crackmes site http://crackmes.cjb.net

The Essay

Ok try disassembling this one and we get a buffer error, I could just go with softice but why make life so easy.
Open up Serializer.exe in your hex editor. It is pretty apparent that Code_Inside has been playing with the PE header. Lets take a look :-)

The standard size for the optional headers in a PE file is 224 bytes. The optional headers start 24 bytes after the begining of the PE header and start with the Magic Number 10Bh. In serializer we see the optional headers are 288 bytes in size, 64 bytes to big. While this is not a problem for the system as long as the correct optional header size is noted. However it is a problem for W32Dasm and many other programs. So lets remove the 64 bytes.

In Uedit simply place the cursor at offset 160h and delete 64 bytes. Of course now the file alignment is incorrect so place the cursor after the section headers and delete the 64 bytes.

Now we have to correct the optional headers size in the PE header. This value is the word value 20 bytes from the begining of the PE headers. In serializer this is 120h it should now be E0h so change it.

Thats it now while we are here we may as well edit the section attributes. We will change them all to E0000060h so edit this value in (in reverse remember so = 600000E0h) at offsets:

19Ch / 1C4h / 1ECh

Thats it now we can disassemble it in W32Dasm. A quick glance at the code tells us all is not well. Why??? well lets go to the program entry point and have a look.

:00401200 BF00104000              mov edi, 00401000
:00401205 57 push edi
:00401206 33C0 xor eax, eax
:00401208 33C9 xor ecx, ecx

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00401213(U)
|
:0040120A 8A07 mov al, byte ptr [edi]
:0040120C 3CC7 cmp al, C7
:0040120E 7405 je 00401215
:00401210 FE07 inc byte ptr [edi]
:00401212 47 inc edi
:00401213 EBF5 jmp 0040120A

* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:0040120E(C), :00401220(U)
|
:00401215 47 inc edi
:00401216 8A07 mov al, byte ptr [edi]
:00401218 3CC7 cmp al, C7
:0040121A 7406 je 00401222
:0040121C 800704 add byte ptr [edi], 04
:0040121F 90 nop
:00401220 EBF3 jmp 00401215
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0040121A(C)
|
:00401222 33C0 xor eax, eax
:00401224 33C9 xor ecx, ecx
:00401226 33D2 xor edx, edx
:00401228 33F6 xor esi, esi
:0040122A 58 pop eax
:0040122B FFD0 call eax
:0040122D C3 ret

These two little routines are decoding the data at offset 401000h the start of our code. The first part adds 1 to all the bytes until a value C7h is detected then the second part adds 4 to each byte until the value C7h is detected.

So how do we get around this??? simple we let serializer do it for us.
Just like we would do with a packed program edit the call to the decoded code at 0040122Bh to jump to itself by changing it to EBFEh
Now we run serializer and open up procdump. Try to dump it and Procdump crashes, this is becuase all the headers are still a little messed up. Never mind we will dump without the headers. Instead of going for the full dump do a partial dump and accept the defaults of 400000h and 3000h. Now we have the dumped file but we have yet another problem The program will now encode itself instead of decoding itself we need to stop the two decode routines from running. This is pretty simple serializer pushes the address 401000h onto the stack for us so if we place a ret directly after this at 0401206h we solve our problem.

Now we still have some problems! the C7h values are still in the code and cause W32Dasm to disassemble incorrectly so lets change them to nops. The first C7h is at offset 1064h the second doesn't matter as it is outside our code since we inserted the ret.

Now if you were observant you will have noticed that although the code starts at offset 1000h there are a few bytes just prior to this at FF0h. We also find this line:

:00401062 EB8C                    jmp 00400FF0

Mmmm seems Code_Inside has tried to hide a little of his code :-).
How do we get to see this code??? The easiest way is in Softice by placing a bpx getdlgitemtexta then enter a name and serial click Check F11 and u 400FF0h to see our instructions:

mov byte ptr [00401112], 30
jmp 004011D8

And that I think is everything now we have a deadlisting. Easier to use Softice mayby but more interesting this way and experience is what makes us better :-)

Now for the serial number......

I am not going to attempt to reverse the serial algorithm as to be honest I cannot immediatly see how you would do this.
Due to the rotating of eax and the placing of the result in 401431h (with the runtime patch) this means that the first and last digits of the serial result will always be the same.

The way that the name is calculated I cannot see an instance where this would be possible while the two central numbers are different.
Anyway I found some bugs in the program which permit us to have a valid serial number.
Due to the way the program checks for a value in the name box a name of a single character will always give a result of zero. Also due to the way that the serial calculation routine strips away the lower byte in the character, a single character in serial with an ascii value of #Fh will always give a good result.

So for example:

name: H (or any other single char)
serial: / or ? or O or _ or o ..........etc will all be accepted.

After the serial is accepted you will get a messagebox telling you what a good cracker that you are then the program will crash.
Now I could be wrong here (but I have scoured the program looking for some self patching code and I do not think so) but the crash is caused by the incorrect handling of the stack. If you look at the bad serial messagebox you will see two pop ebp instructions following it. In the good boy we only have one and an xor eax,eax.
If we correct this by changing the xor eax,eax to nop pop ebp (905D) then the program returns correctly.
One final bug is that the program is supposed to display the Congratualtions in the title but because the stack is out of alignment the value [ebp+8] does not contain the window handle. To overcome this simply change the 8 to Ch and all will go well.
The same thing is happening for the Bad boy message but as the text is already Code_Inside it will not show any differently.

So mayby I cheated a little but Code_Inside did not stipulate any rules apart from no patching. I have not patched the program to make a successful serial just to stop it from crashing afterwards.

Please note that I mean nothing derogotory to Code_Inside by pointing out these bugs, his little crackme has a lot to offer and I certainly learnt something new about the PE headers. Bugs will happen but in this case they leave a big opening in an otherwise pretty good serial protection.

Final Notes

Thanks go to:

 Muad'dib for the crackmes site

Code_Inside for writing this crackme

 

 

Essay by:      Harlequin
Page Created: 7th March 2001