Target: CrackMe [id:13]
Author: tC...
Cracker: The AntiXryst [CrossOver]
Rating: Easy. I know tC... having written worse things.
Used tools: WDASM 8.93, Hex Workshop
Greetings to: Me, myself and I and everybody else I injured during my
	      sadomasochistic games ;-)


Hi there!

You have probably read my tutorial on getting past tC's CrackMe id:12.
If you did not and now do not know how to find relevant procedures of
Delphi-written programs, read it NOW!

As you may already have experienced, I will NOT explain every single
detail, I'll just show you what part of code does what in a syntactical
mix of Pascal and ASM register calling...
If you browse through the disassembly and get closer to its sense,
you'll soon recognise that the Delphi compiler is VERY stupid and
produces completely inefficient, sometimes even idiotic code.

And now launch WDASM, disassemble the crackme and set a breakpoint to
$00441908, what is actually "our" routine. Feel free either just to
read my text or to follow my steps with the debugger...


Code snippet $00441924-$004419B0:
---------------------------------
String data from the input boxes is read through the Delphi VCL and
stored in pre-defined memory offsets. You'll find a string reference to
"Yeah, You did it!" followed by a call - do not worry, this is just a
hoax, because the called routine $00403850 has no relevance for the
generation of serial numbers/key values due to its position in the VCL
fully linked to the executable and because the value returned by this
function in EAX is ignored by XOR EAX,EAX ($00441931).



Code snippet $004419B5-$004419C8:
---------------------------------
A relevant function is called - $004418D0. It seems to test something.
This routine stores its result in [$00443838]. If this result is 2, the
program continues. Elseway it calls a "clean-up" routine at $004417E4
which deletes some calculated values and memory-stored string data from
the input boxes, after the call returns, the jump to $00441AF5 is
performed thus "our" relevant routine is terminated.



Subroutines $004418D0 and $004418AC:
------------------------------------
The routine $004418D0 does perform a check whether memory-stored string
values from the upper 2 input boxes are longer than 0. You could also
say that this function checks whether the values have been entered at
all. If both values are present, routine $004418AC is called.
The routine $004418AC performs via subtraction a compare of string
lengths. If they are same, $00443838 becomes 2.



Code snippet $004419DC-$00441A17:
---------------------------------
In this code snippet the entered serial number is validated without a
correct serial number is being generated.

:004419DC lea edx, dword ptr [ebp-08]      <---- getting User entry
:004419DF mov eax, dword ptr [esi+000002C4]      from input box
:004419E5 call 004231A4				 via VCL call

:004419EA mov eax, dword ptr [ebp-08]      <---- offset of User
:004419ED movzx eax, byte ptr [eax+ebx-01] <---- ASCII value is loaded,
:004419F2 add eax, 00000003                      increased by 3
:004419F5 push eax			   <---- and stored

:004419F6 lea edx, dword ptr [ebp-0C]      <---- getting Serial entry
:004419F9 mov eax, dword ptr [esi+000002C8]      from input box
:004419FF call 004231A4				 via VCL call

:00441A04 mov eax, dword ptr [ebp-0C]      <---- offset of Serial
:00441A07 movzx eax, byte ptr [eax+ebx-01] <---- getting ASCII value
:00441A0C pop edx			   <---- loading User char+3
:00441A0D sub edx, eax
:00441A0F add dword ptr [00443840], edx    <---- difference between
						 User char+3 and Serial
						 char

:00441A15 inc ebx			   <---- EBX is index counter
:00441A16 dec edi			   <---- EDI is loop counter
:00441A17 jne 004419DC

You can sum up this in a sort of Pascal syntax:
       var index:Cardinal;
       for index:=1 to Length(User) do
	[00443840]:=[00443840]+(Ord(Name[index])+3-Ord(Serial[index]));



Code snippet $00441A19-$00441A25:
---------------------------------
A call to the routine $0044182C is performed. This routine is a hoax,
intended to confuse the cracker. Why? Surely it does some string mani-
pulation with XOR, addition and subtraction. But it does not store any
calculated values ;-) After the call, offset $00443840 is checked
whether it's 0. If not, the routine terminates. Do you see that the
manipulated string and the serial must match? So here's the algorithm:
       var index:Cardinal;
       Serial:='';
       for index:=1 to Length(User) do
        Serial:=Serial+Chr(Ord(User[index])+3);



Code snippet $00441A31-$00441A3D:
---------------------------------
The string value for RegCode is obtained through the VCL and checked,
whether it has been entered (length > 0). If the string is not present,
the routine terminates.



Code snippet $00441A49-$00441A7D:
---------------------------------
A call to the hoax routine $004418AC is performed. The length of Serial
and RegCode are checked, they must be the same, elseway the routine
terminates.

:00441A5E mov eax, dword ptr [00443848]	<---- offset of RegCode
:00441A63 call 00403A34			<---- call to Length()
:00441A68 mov ebx, eax			<---- result stored
:00441A6A mov eax, dword ptr [0044384C] <---- offset to Serial
:00441A6F call 00403A34			<---- call to Length()
:00441A74 cmp ebx, eax			<---- compare the lengths
:00441A76 je 00441A7F			<---- if OK, then continue



Code snippet $00441A89-$00441A:
---------------------------------
In this code snippet the entered RegCode is validated without a valid
RegCode is being generated. This is the same as the validation of the
Serial string, there's just one difference - instead of increasing by 3
the chars of the user name are decreased by 3.

:00441A8E lea edx, dword ptr [ebp-08]	    <---- getting User entry
:00441A91 mov eax, dword ptr [esi+000002C4]
:00441A97 call 004231A4

:00441A9C mov eax, dword ptr [ebp-08]	    <---- now decreasing its
:00441A9F movzx eax, byte ptr [eax+ebx-01]	  chars by 3
:00441AA4 sub eax, 00000003
:00441AA7 push eax			    <---- storing

:00441AA8 lea edx, dword ptr [ebp-0C]       <---- getting RegCode entry
:00441AAB mov eax, dword ptr [esi+000002D0]
:00441AB1 call 004231A4

:00441AB6 mov eax, dword ptr [ebp-0C]       <---- again getting 1 char
:00441AB9 movzx eax, byte ptr [eax+ebx-01]
:00441ABE pop edx                           <---- "remembering" and
:00441ABF sub edx, eax                            subtraction
:00441AC1 add dword ptr [00443844], edx     <---- storing

:00441AC7 inc ebx
:00441AC8 dec edi
:00441AC9 jne 00441A8E

As you see, nearly the same as the Serial validation. The correct
algorithm for creation of the RegCode:
       var index:Cardinal;
       RegCode:='';
       for index:=1 to Length(User) do
        RegCode:=RegCode+Chr(Ord(User[index])-3);



Code snippet $00441ACB-$00441AEB:
---------------------------------
Here, 2 calls to another hoax routines are done. The difference of
chars of RegCode and manipulated user name is checked, if not equal 0,
the routine terminates.

:00441ACB call 00441870			<---- hoax routine
:00441AD0 call 0044175C			<---- another hoax
:00441AD5 mov eax, dword ptr [00443844] <---- getting the difference
					      computed above
:00441ADA add eax, 00027009		<---- just to confuse newbies
:00441ADF cmp eax, 00027009             <---- if EAX was 0, now EAX
					      must be $27009, thus the
					      RegCode is recognized as
					      valid.
:00441AE4 je 00441AED			<---- if OK, then proceed
:00441AE6 call 004417E4			<---- elseway terminate
:00441AEB jmp 00441AF5



That's all, folks! Now it's up to you to write a working keygen. Or if
you are as lazy as me, myself and I, you may play with my keygen.
-----------------------------------------------------------------------

I hope you have learned a little bit from this. Look out for my cracks:
tutorials or source codes are included in most cases!

Sincerely yours,
  The AntiXryst [CrossOver]

Visit the newcoming cracking group I am the CoLeader of:
http://crossover.tsx.org