Aesculapius Y2K +HCU Strainer - Tutorial
================================================================================
Author        : Canterwood <canterwood@altern.org>
Protection    : basic encryption, per-computer code
Level         : Beginner+
Tools         : OllyDbg, LordPE, Hex Workshop, IDA & MASM32 (keygen)
Attached files: crackme + patched crackme + keygen + trim example
================================================================================
10.01.2004

Introduction
--------------------------------------------------------------------------------
  If found this +HCU strainer on the crackme.de website, and when I saw the
"level 9" (/10!), I obviously thought that it was not for non-skilled crackers
like me...
But, strangly, as we're going to discover, the protection scheme isn't very hard
to reverse and the name/serial protection is really easy to decode...
Well, perhaps I have forgotten something "hidden" or it is due to my operating
system (WinXP), I do not know...

Nonetheless, that's not a problem, I have decided to release this tut' anyway,
because this lil' crackme uses some cool & interesting tricks.
So, let's study on this stuff now. :)

Step I : Patching the proggie
--------------------------------------------------------------------------------
  Why patching? Simply because some parts of the code/data of this crackme are
(lamely) crypted in the PE file, and restored in memory once lauching the app.
It is the case of the .DATA section (which contains all strings), and the most
omportant part of the validation routine.
By this way, we cannot work on the strainer with a disassembler (for the
moment), but only use the live approch method (debugging).

So, for a better understanding, we need first to replace the original code in
the executable. Do not worry about this, it is quite easy.

  Now, we lauch the proggie with OllyDbg; you can also use other debuggers, such
as Numega SoftICE or TRW2000 but I do not give explanation for those ones...

A dialog box appears with two fields, name and serial. Without waiting anymore,
we fill these edit boxes with information like:

User Name    : Canterwood
Serial Number: 12345

As the crackme is very small (20k), it isn't necessary to push breakpoints or
other methods to seek the validation routine.
If we take a look at the listing, we can easily find the Windows Procedure, ie
the function which is listening all events that occur during the session, like
Mouse Scrolling, Windows Resizing, etc...
In our case, we wanna locate which code is executed when we click on the OK
button.

We browse the disassembly, and after a few seconds, we find that:

...
00403201  MOV EAX,0
00403206  LEAVE
00403207  RETN 10
0040320A  CMP DWORD PTR DS:[4044F6],1
00403211  JE SHORT aescul.00403224            ; a jump for other Windows Events
00403213  MOV ESI,aescul.00404000             ; the beginning of the routine
00403218  MOV EDI,ESI
0040321A  MOV ECX,0B16
0040321F  CALL aescul.00403465                ; a mysterious call...
00403224  PUSH 40
00403226  PUSH aescul.004041BA
0040322B  PUSH 3E8
00403230  PUSH DWORD PTR SS:[EBP+8]
00403233  CALL <JMP.&USER32.GetDlgItemTextA>  ; get the name
...

  Before the proggie gets the name, it calls a function, probably a procedure
which is important for the rest of the routine, as the value 00404000 (data) is
assigned to the register esi.
Indeed, if we enter in it (403465), we have this:

00403465  XOR EAX,EAX
00403467  LODS BYTE PTR DS:[ESI]       ; loads the next byte of the data
00403468  ROL AL,CL
0040346A  NOT AL                       ; decrypt it
0040346C  STOS BYTE PTR ES:[EDI]       ; replace the old byte with the new one
0040346D  LOOPD SHORT aescul.00403465  ; continue (jump to 403465)
0040346F  MOV DWORD PTR DS:[4044F6],1  ; sets the flag once unciphered
00403479  RETN

Yes, it's the function that decrypts the strings. You can see below a similar
procedure, and we guess it will be used for the code...

As a consequence, we do not make any dump or patch for the moment, we'll do it
at the end of this part, when the remaining code will be decrypted.

Next, we can see that the name, followed by the serial, are copied into memory.
The proggie also checks if these values aren't equal to zero.

There's now another interesting point :

00403286  PUSH aescul.00404B0E                   ; /pHandle = aescul.00404B0E
0040328B  PUSH 1                                 ; |Access = KEY_QUERY_VALUE
0040328D  PUSH 0                                 ; |Reserved = 0
0040328F  PUSH aescul.00404000                   ; |Subkey = "Software\Micro..."
00403294  PUSH 80000002                          ; |hKey = HKEY_LOCAL_MACHINE
00403299  CALL <JMP.&ADVAPI32.RegOpenKeyExA>     ; \RegOpenKeyExA
0040329E  PUSH aescul.00404B12                   ; /pBufSize = aescul.00404B12
004032A3  PUSH aescul.004043BC                   ; |Buffer = aescul.004043BC
004032A8  PUSH 0                                 ; |pValueType = NULL
004032AA  PUSH 0                                 ; |Reserved = NULL
004032AC  PUSH aescul.00404033                   ; |ValueName = "ProductId"
004032B1  PUSH DWORD PTR DS:[404B0E]             ; |hKey = 0
004032B7  CALL <JMP.&ADVAPI32.RegQueryValueExA>  ; \RegQueryValueExA

The crackme gets the ProductId of Windows, probably to generate the good serial
from this value. It is located in the registry, at:

[HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion]
"ProductId"

On my computer, it has this format: XXXXX-XXX-XXXXXXX-XXXXX.
The cracke also adds the prefix "WS" to this value.

Now, we see this :

004032E7 CALL aescul.0040347A  ; the validation code decryption procedure
004032EC JMP aescul.00403380   ; a jump to this procedure.

The call is the same one we have evoked previously, therefore I do not need to
give details about it.

Making a dump
***************************************************************
  To reinject the decrypted code in the *.exe file, there are various ways: you
can make a partial dump with LordPE, using some other memory tools, or doing it
by hand...

I have simply copied the code with OllyDbg, in the heap window, with the Binary
Copy command in the context menu. Then I have removed the spaces between the hex
values with a little JavaScript proggie (it is included in this archive). It's a
quite boring method, but it works...

I give you the method for the .DATA section, it's fairly easy:

1) Select the values in the heap from 404000 to 404000h + 0B16h = 404B16h. I
know this because it's indicated in the parameters of the decrypting function:

00403213  MOV ESI,aescul.00404000 ; the starting address
00403218  MOV EDI,ESI
0040321A  MOV ECX,0B16            ; the amount of data to be unciphered
0040321F  CALL aescul.00403465

2) Once decrypted, copy the code in the clipboard. Now, you can make a script to
clean the spaces, or removing them by hand... If you're not enough strong to try
this, use the Dump Partial function of LordPE.

3) Now, you obtain a string like this:

536F6674776172655C4D6963726F736F66745C57696E646F77735C43757272656E74566572736...

OK, we must replace the code in the PE file. We localize the raw offset of the
.DATA section with our PE editor, it's: 2C00h.
Then we duplicate the crackme, open it with Hex Workshop, go to the 2C00h offset
and paste our decrypted code with the function "Paste Special" -> "CF_TEXT".
Don't forget to choose the option "Interpret as a hexadecimal string", else it
will not work. You must also select the old code with your mouse to replace it.
Finally, click "OK".

4) That's all. Sorry, I do not describe precisely how to use the tools, because
it is a thing that I consider you already know.

For the code, it is perceptibly the same manipulation, the only values that
change are the address and the size of the block:

Memory offset: 403050h
Size         : 134h
Raw offset   : 2650h

That's done? It's time to patch the proggie, so as to cancel the decrypting
operation which is now obsolete. Two simple JMPs will be enough.

Replace this:

00403465  XOR EAX,EAX
00403467  LODS BYTE PTR DS:[ESI]
00403468  ROL AL,CL
0040346A  NOT AL
0040346C  STOS BYTE PTR ES:[EDI]
0040346D  LOOPD SHORT aescul.00403465
0040346F  MOV DWORD PTR DS:[4044F6],1
00403479  RETN
0040347A  XOR EAX,EAX
0040347C  LODS BYTE PTR DS:[ESI]
0040347D  ROL AL,CL
0040347F  NOT AL
00403481  STOS BYTE PTR ES:[EDI]
00403482  LOOPD SHORT aescul.00403465
00403484  MOV DWORD PTR DS:[4044FA],1
0040348E  RETN

with this:

00403465  JMP SHORT aescul_p.0040346F    ; patch here
00403467  LODS BYTE PTR DS:[ESI]
00403468  ROL AL,CL
0040346A  NOT AL
0040346C  STOS BYTE PTR ES:[EDI]
0040346D  LOOPD SHORT aescul_p.00403465
0040346F  MOV DWORD PTR DS:[4044F6],1
00403479  RETN
0040347A  JMP SHORT aescul_p.00403484    ; patch also here
0040347C  LODS BYTE PTR DS:[ESI]
0040347D  ROL AL,CL
0040347F  NOT AL
00403481  STOS BYTE PTR ES:[EDI]
00403482  LOOPD SHORT aescul_p.00403465
00403484  MOV DWORD PTR DS:[4044FA],1
0040348E  RETN

You can make this changes via the Assemble function of OllyDbg, and selecting
"Copy to Executable" -> "All modifications", then "Save file".

Normally we have a working dump. We are ready to study on the serial generation
routine...

Step II : Understanding the validation routine
--------------------------------------------------------------------------------
  After the crackme has decrypted the validation code, it calls the function
EndDialog which causes the window destruction, and we arrive at the top of the
listing, just below the DialogBoxParamA call: in a NOPs field.
As there are a lot of these instructions, we can push a breakpoint at the bottom
(scroll the CPU window), at 403038.

There is this piece of code:

00403038  XOR EAX,EAX
0040303A  PUSH aescul_p.00403393
0040303F  PUSH DWORD PTR FS:[EAX]
00403042  MOV DWORD PTR FS:[EAX],ESP
00403045  PUSHFD
00403046  PUSHFD
00403047  POP EAX
00403048  OR EAX,100
0040304D  PUSH EAX
0040304E  POPFD
0040304F  NOP
00403050  XOR ESI,ESI                 ; Single-step event

I really dunno what is the goal of these ASM instructions: the 00403393
address points to a routine that modifies the behavior of the debuggee, a
single-step event is generated, but we can easily conturn it with Olly
(SHIFT + F7).
Probably an anti-debugger routine...

Next, there is the serial-generation loop:

00403061  /PUSH EBP
00403062  |PUSH EDI
00403063  |PUSH ESI
00403064  |MOV EBP,aescul_p.004044C0     ; ebp = table ("0I5LZ7G123RXCV9OPA...")
00403069  |MOV EBX,aescul_p.004043BA     ; ebx = Windows ProductId
0040306E  |MOV AL,BYTE PTR DS:[EBX+ESI]  ; take a character of the PId
00403071  |SAR EAX,4
00403074  |AND EAX,0F                    ; eax = the 4 most significant bytes
00403077  |CALL aescul_p.0040313B        ; gets the corresponding entry in the table
0040307C  |MOV BYTE PTR DS:[EDI],AL      ; concatenate the result to the serial
0040307E  |MOV CL,BYTE PTR DS:[EBX+ESI]
00403081  |AND ECX,0F
00403084  |MOV EAX,ECX
00403086  |CALL aescul_p.0040313B        ; idem, with the 4 remaining bytes
0040308B  |MOV BYTE PTR DS:[EDI+1],AL    ; concatenate the result to the serial
0040308E  |POP ESI
0040308F  |POP EDI
00403090  |POP EBP
00403091  |INC ESI
00403092  |ADD EDI,2
00403095  |CMP EBP,ESI
00403097  \JNZ SHORT aescul_p.00403061

Try to trace in the code and you'll understand directly... Each caracter of the
name is taken, and some manipulations are done.

Imagine the current character value is 37h:

1) The program takes the number 3, the four high 4-bits.
2) It gets the corresponding element in the array, like '3'.
3) Now, this operation is repeated with the 4 other bits: 7; we get 'W'.
4) The results '3' and 'W' are added to the right serial.
5) Jump to 1) with the next character.

The good serial is stored in the value pointed by edi. Note I do not describe
how the element of the constant is got, because it isn't important.

Finally, we have this:

00403099  XOR ESI,ESI
0040309B  MOV EAX,DWORD PTR DS:[ESI+4042BA]
004030A1  MOV EBX,DWORD PTR DS:[ESI+404502]
004030A7  CMP EAX,EBX                        ; 1st dword
004030A9  JNZ SHORT aescul_p.004030F0
004030AB  ADD ESI,4
004030AE  MOV EAX,DWORD PTR DS:[ESI+4042BA]
004030B4  MOV EBX,DWORD PTR DS:[ESI+404502]
004030BA  CMP EAX,EBX                        ; 2nd dword
004030BC  JNZ SHORT aescul_p.004030F0
004030BE  ADD ESI,4
004030C1  MOV EAX,DWORD PTR DS:[ESI+4042BA]
004030C7  MOV EBX,DWORD PTR DS:[ESI+404502]
004030CD  CMP EAX,EBX                        ; 3rd dword
004030CF  JNZ SHORT aescul_p.004030F0
004030D1  ADD ESI,4
004030D4  MOV EAX,DWORD PTR DS:[ESI+4042BA]
004030DA  MOV EBX,DWORD PTR DS:[ESI+404502]
004030E0  CMP EAX,EBX                        ; 4th dword
004030E2  JNZ SHORT aescul_p.004030F0
004030E4  MOV DWORD PTR DS:[4044F2],1        ; sets the flag to 1 if good
004030EE  JMP SHORT aescul_p.004030FA
004030F0  MOV DWORD PTR DS:[4044F2],0        ; sets the flag to 0 if bad
004030FA  POPFD
004030FB  XOR EAX,EAX
004030FD  POP DWORD PTR FS:[EAX]
00403100  ADD ESP,4
00403103  CMP DWORD PTR DS:[4044F2],1
0040310A  JNZ SHORT aescul_p.00403121        ; bad boy if the serial is wrong

Don't be anxious, it just tests if the serial we entered matches wih he good
one. In other words, it's a clone of lstrcmpA...

On my operating system, the serial looks like this:

Serial Number: 57U33U3U3RCW3TBM3VST33RM3W3RCASSSSSB33RM3RCCC83V

You can find it in clear at address 404502. Just copy it and enter it in the
edit box of the non-patched strainer (to verify); yes, it's OK!

Step III: Creating the keyfinder
--------------------------------------------------------------------------------
  As this crackmes uses a Name/Serial scheme, it is a good idea to code a
keygen. In this case, you have just to rip some parts of the code, with tools
like IDA, for example... I let you do it... a sample is attached with this tute.

In fact, it isn't exactly a keygen for the proggies does not uses the name to
generate the serial, but the PId. Thus, I have called it a "keyfinder".

Conclusion
--------------------------------------------------------------------------------
  We have finished! Really easy, isn't it? Now, we are +Crackers, yeah! ;) But
it wasn't a +ORC strainer and the +HCU is dead since 1999... Therefore, we'll
report our canditature to the future...

  In fact, I already knew this type of crackmes, with basic code encryption:
the NGEN Trial 2003 (first edition) is one of them... and curiously, it's more
complicated!

I hope you've appreciated this tutorial, and sorry for my bad expression...

================================================================================
Thanks   : Analyst, Christal, Lise_Grim for their tutes, and YOU!
Greetings: RocketSpawn, xyzero (hi dude!), devilz, $KORBUT, Gbillou, Snio, and
all others...

Canterwood