Serializer Reconstruction of a deadlisting by Harlequin March 2001
|
|
|
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