Solution for [RET]'s first challenge
by the_dux

Well, we've this little program to play with this time.
Fire it up and see what happen...

Wow, a nice dialog box say to us that we're not registered and show
us a little nice logo.
Fire up your preferred disassembler and let's see what happen (the
program isn't packed and hasn't any protection against debuggers or
disassemblers): we have our code right there. With little fantasy
reach the EP and then look at the code; there is a call to
GetModuleHandle and then one to DialogBoxParamA. If you look at your
API reference you'll see that 4th parameter is the pointer to your
dialog box code. Here we can see that looking to 401016 with the
code push 401095. This is where the dialog box related routines are.
Now, go to 401095 and look around to see what happen: you can see some
stacks arrangement and then a cmp instruction. Skip over this, they
don't care to us (but they've a meaning that is outside the goals of
this text), and fall to 4010A5 where you can see a call. Go exploring
it and you'll see this:

:004012B4 60                      pushad
:004012B5 8D0500304000            lea eax, dword ptr [00403000]
:004012BB 8A18                    mov bl, byte ptr [eax]
:004012BD 80EB07                  sub bl, 07
:004012C0 8818                    mov byte ptr [eax], bl
:004012C2 40                      inc eax
:004012C3 8A08                    mov cl, byte ptr [eax]
:004012C5 80C120                  add cl, 20
:004012C8 8808                    mov byte ptr [eax], cl
:004012CA 40                      inc eax
:004012CB 8A10                    mov dl, byte ptr [eax]
:004012CD 80F22D                  xor dl, 2D
:004012D0 8810                    mov byte ptr [eax], dl
:004012D2 83C002                  add eax, 00000002
:004012D5 8A18                    mov bl, byte ptr [eax]
:004012D7 80C307                  add bl, 07
:004012DA 8818                    mov byte ptr [eax], bl
:004012DC 40                      inc eax
:004012DD 8A08                    mov cl, byte ptr [eax]
:004012DF 80E920                  sub cl, 20
:004012E2 8808                    mov byte ptr [eax], cl
:004012E4 40                      inc eax
:004012E5 8A10                    mov dl, byte ptr [eax]
:004012E7 80F22D                  xor dl, 2D
:004012EA 8810                    mov byte ptr [eax], dl
:004012EC 61                      popad
:004012ED C3                      ret

What is this code for? Simple: take a look at data references at 403000
and you'll see a nice string: RET.key. If you read all the code you'll
note that this little routine simply modify that string and make it
something like key.ret, that is the keyfile the program use to get our
registration infos.
Well, now return back from that call and go down the code 'till you reach
SendMessageA: as you can see the dialog box is created here and then, after
SendMessageA we have another call followed by a typical protection-like
scheme:

:00401158 E8DF000000              call 0040123C               
:0040115D 803D0830400001          cmp byte ptr [00403008], 01
:00401164 7405                    je 0040116B      ;test if we're registered
:00401166 E818000000              call 00401183

Now you can imagine that this is not the case where you can simply invert 0x74
with 0x75. This crackme it's a little bit harder.
Go to 40123C and take a look at the code: you'll notice that the Registry is
used here. How?
The program try to open a key (HKCU\Software\RET\Re-Venge\) and if successfull
it try to get the value (hex) of [RET] and close the key.
So what you've got to do now is create a binary value named [RET] under
HKCU\Software\RET\Re-Venge\ (beware: don't create [RET] as a string, it won't
works!).
A little precisation: if you look at the return value of RegOpenKeyExA and
RegQueryValueExA you'll see that an unsuccessful query is translated to
a mov byte ptr [403008], 1 that is the flag used on 40115D to test if we're
registered. However changing this value don't register the program.
Now, after you've created the key as said above you've to fill it with
something, but what?
Go to 40128D (rigth after the call to RegCloseKey) and you'll see another
call to a function. Again you've to study the code there to see what happens.

:00401033 60                      pushad
:00401034 8D054C304000            lea eax, dword ptr [0040304C]
:0040103A 33C9                    xor ecx, ecx

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0040104A(U)
|:0040103C 83F930                  cmp ecx, 00000030
:0040103F 740B                    je 0040104C
:00401041 8A18                    mov bl, byte ptr [eax]
:00401043 80EB20                  sub bl, 20
:00401046 8818                    mov byte ptr [eax], bl
:00401048 40                      inc eax
:00401049 41                      inc ecx
:0040104A EBF0                    jmp 0040103C

Can you see what this code do? It take the data read from Registry and with
401043 make a little operation to it. This is very important for what follow
so study this little easy code. Notice that here we have an information of
the length of the key [RET], that is 0x30 bytes long as you can see on
40103C.

Now let's read this part of code

:0040104C A1E2304000              mov eax, dword ptr [004030E2]

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00401058(C)
|
:00401051 48                      dec eax
:00401052 81384D5A9000            cmp dword ptr [eax], 00905A4D
:00401058 75F7                    jne 00401051
:0040105A A3E2304000              mov dword ptr [004030E2], eax
:0040105F 33DB                    xor ebx, ebx
:00401061 8D3D4C304000            lea edi, dword ptr [0040304C]
:00401067 8D35E6304000            lea esi, dword ptr [004030E6]

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0040108A(C)
|
:0040106D 57                      push edi
:0040106E FF35E2304000            push dword ptr [004030E2]

* Reference To: KERNEL32.GetProcAddress, Ord:0129h
                                  |
:00401074 E8AB020000              Call 00401324
:00401079 83F800                  cmp eax, 00000000
:0040107C 7410                    je 0040108E
:0040107E 8906                    mov dword ptr [esi], eax
:00401080 83C710                  add edi, 00000010
:00401083 83C604                  add esi, 00000004
:00401086 43                      inc ebx
:00401087 83FB03                  cmp ebx, 00000003
:0040108A 75E1                    jne 0040106D

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00401093(U)
|
:0040108C 61                      popad
:0040108D C3                      ret

This is very important and a very nice kind of information-hiding.
First of all 40104C take the handle of KERNEL32.DLL (with a call to
GetModuleHandle just after the EP) and seek it's start looking for
the string 'MZ  ' (00905A4D in memory). When founded the address is
stored for later use (at 401074 with GetProcAddress). Now look at
GetProcAddress; this call get an address of a function starting from
its name and its module name. We already know the module name that
is KERNEL32 but we discover that edi (that point to function name)
is what we've read from the registry (not exactly, because the code
we've seen before modified it a bit).
What's that??? We read what we've to do from the Registry? Yes.
To be a little clear:

- we read some data from Registry
- we substract 0x20 to each data-byte read
- we use the strings contained in our data as function names
- we get the address of our function (that are in KERNEL32)

Note that we've to supply 3 function names to the program (401087 cmp ebx, 3).
So the question now is: what function we have to pass to the program?
If you look at the code that follow you can't see something so usefull
so return back two times (after SendMessageA). Pass the cmp [403008], 1
as registered and then follow the call 401183. Here you can see:

:00401183 60                      pushad
:00401184 A1E6304000              mov eax, dword ptr [004030E6]
:00401189 6A00                    push 00000000

* Possible StringData Ref from Data Obj ->"RET.Key" => "key.ret"
                                  |
:0040118B 6800304000              push 00403000
:00401190 FFD0                    call eax
:00401192 A3CA304000              mov dword ptr [004030CA], eax

Don't you see some strange code? with push 0, 'key.ret' and then we make
a call to eax. What is eax? look at 401067 and you'll jump over your
chair: it's the address of a function we've taken before with
GetProcAddress!! So it seems sensful reading from the Registry and then
build a table of three calls.
To discover what function you need you've to make some guess I think, but
if you're familiar with C you can deduce that the call at 401190 is a
call to a open file function and the style is similar to fopen( file, attr ).
What function do this work (with two parameters) under Windows?
It's _lopen...
To store it into Registry remember to add 0x20 at each bytes of name and
terminate the string with 0.
Now look back at the code and you'll see that we've still a function to define:
it is the one at 4011B5. With no great fantasy you can say that the call
(refer to your API guide) is ReadFile.
Now we can go to Registry Editor and make our [RET] key, but as said above
we've three function and now we've defined only two...
Yes, it's true but the other call isn't used (at least to let the registration
work), so you can enter whatever you want (the function must be from KERNEL32).
As said you can't simply cut and paste function names to the registry, you've
to follow a predefined structure. If you look at 401080 you'll see that the
max length of a function is 0x10 (16) bytes. This mean that you have up to
15 byte for the function name and one for the zero code (to terminate the string).
To be a little complicated the names are not clearly shown but you've to sub
0x20 to every byte before you can use them.
This mean that if you write 0x61 ('a') on the Registry the program will use 0x41
('A') for the function name. Keep in mind that KERNEL32 functions are case
sensitive...
Here's an example of a [RET] key used by me (the 3rd function is GetProcAddress):
7F 8C 8F 90 85 8E 20 20 20 20 20 20 20 20 20 20
72 85 81 84 66 89 8C 85 20 20 20 20 20 20 20 20
67 85 94 70 92 8F 83 61 84 84 92 85 93 93 20 20

The first line contain _lopen, the second ReadFile and the third GetProcAddress.
I choose to fill the fields of each function's name with 0 (0x20).
So now you can think the program will works.
Nope...
We are almost registered, but we've to reconstruct the key file (key.ret).
This is not very hard as we'll see but tricky.
First of all the file must be filled with something (4011B7 and 4011BC) and it
must contain a signature at the very beginnig of it (4011CD): ' RETD' (notice
the space that is a 0 in the file. Then follows the real code:

:004011D8 0FB619                  movzx ebx, byte ptr [ecx]
:004011DB 0FB64101                movzx eax, byte ptr [ecx+01]
:004011DF F7E3                    mul ebx
:004011E1 0FB65902                movzx ebx, byte ptr [ecx+02]
:004011E5 2BC3                    sub eax, ebx
:004011E7 0FB65903                movzx ebx, byte ptr [ecx+03]
:004011EB F7E3                    mul ebx
:004011ED 83C104                  add ecx, 00000004

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004011FD(U)
|
:004011F0 803900                  cmp byte ptr [ecx], 00
:004011F3 740A                    je 004011FF

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00401205(U)
|
:004011F5 0201                    add al, byte ptr [ecx]
:004011F7 2A4101                  sub al, byte ptr [ecx+01]
:004011FA 83C102                  add ecx, 00000002
:004011FD EBF1                    jmp 004011F0

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004011F3(C)
|
:004011FF 80790100                cmp byte ptr [ecx+01], 00
:00401203 7402                    je 00401207
:00401205 EBEE                    jmp 004011F5

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00401203(C)
|
:00401207 FFE0                    jmp eax

As you can see we take what we have in the file and do some math with it to compute
an address (stored in eax) which will lead us to success or to a protection fault.
Let's get in order:
- ebx filled with the 4th (ecx) byte of the file (at 4011D8)
- eax filled with the 5th (ecx+1)
- eax=eax*ebx
- eax=eax - 6th byte
- ebx filled with 7th byte
- eax = eax - ebx
What follow is considered as words and added (high word) or substracted (low word) at
4011F5 and 4011F7. This words as you can see soon compose your name (wich is displayed
when you're registered).
If we encounter two zeros (4011F0 and 4011FF) we exit from loops and go to 401207 that
jumps to computed eax.
Well, we now have the flow of instructions but what is the eax we want at the end of
it?
Simply take a look at the file and you'll see that there's a 'Registered to:' string
somewhere. This is the point were we want to go so write down the address: 401218.

A little digression about the EIP reconstruction:
the EIP is taken from the two mul at 4011DF and 4011EB but you've to choose exact
bytes to make it fit 401218. We can see that with 4011F5 and 4011F7 we can only
modify AL, that is the two less significant bytes of 401218. Our goal is thus
found a sequence of three numbers that give us a result from 401200 to 4012FF.
There are many ways to reach this result but the simplest is with a little brute
forcing. Consider this program:

ideal
model tiny
p386
codeseg
org 100h

start:
xor ecx, ecx
inc ebx
inc_cx:
xor edx, edx
inc ecx
inc_dx:
inc edx
mov eax, ebx
imul eax, ecx
imul eax, edx
sub eax, 401200h
cmp eax, 0FFh
jbe found
cmp edx, 255
jne inc_dx
cmp ecx, 255
jne inc_cx
cmp ebx, 255
jne start
mov si, 1
found:
int 20h
end start

If you set a breakpoint on int 20h you'll see in ebx, ecx, edx the right combination
(if si is set to 0). This is probably to most lazy and fast method... You can then
give it an interface to the world, but that's not our goal now.
The first solution found is 0x44 0xF7 0xFA, so the key file will be
00 52 45 54 44 F7 00 FA xx xx xx xx xx ... xx 00 yy zz
-----|----- -----|-----
  signature     code     b1 b2 b3 b4 b5 ... bn    CB CB

Now we've to fine tune our result so that AL will be 0x18. This is very easy.
If you want to insert a name in the key file you have to insert it just after
the code and terminate it with ONLY one zero (4011F0) so you can adjust what
the bytes of name have modified of AL (4011F5 and 4011F7).
With little math you can see that AL=b1-b2+b3-b4 ... so the last byte is the
difference between the value of AL after bn and 0x18. CB means Correction Byte
and is divided into yy and zz. Looking at the code (again 4011F5 and F7) you can
see that yy is substracted and zz is added so you can adjust any code after the name.
If you only need yy (most times, because 0x18 is small) you can omitt zz.

If you want (and have time to spend) you could code a keygen for a given name
(it's not so difficult... it has only some little equations...) to better
understand the code.
Hope this tutorial help you solve the crackme, or simply take a look at an
interesting kind of protection...

Many thanks to Crudd [RET] for this awesome crackme...

By(t)e
the_dux