http://www.cypressnet.com - Webpage (ctmailer.zip - (1.34Mb))
Welcome once again to another updated key generator tutorial which does some fairly standard manipulations of the user name and provides an opportunity for me to illustrate how you can rip out the key generator code directly from the disassembler. Without further ado lets start our target and locate the registration dialog (selectable as soon as you start the program).
Now we'll set some SoftICE breakpoints (after entering some information into the dialog boxes above of course), you'll find GetWindowTextA works well, so perform the necessary actions (allowing for 2 breaks) and you'll be staring at code inside mfc42.dll (a Microsoft Foundation Class dll). So step for a little (no more than 20) and reach this code inside ctmailer.exe.
:00406599 MOV EAX, DWORD PTR [EAX] <-- User Name.
:0040659B PUSH EAX <-- Stack it for next call.
:0040659C PUSH 0040E0FC <-- "CTMAILER".
:004065A2 CALL 00407F30 <-- Add the string reference as a prefix.
This first section of code merely takes the user name and prefixes it with the string reference i.e. CTMAILERCrackZ, if you use IDA to disassemble this you'll even get the function name. The calculation routine follows.
:004065B6 CALL 00401E20 <-- Calculation routine.
:004065C7 MOV DL, BYTE PTR [EAX] <-- Good code.
:004065C9 MOV BL, BYTE PTR [ESI] <-- Entered code.
:004065CB MOV CL,DL <-- Use CL to store.
:004065CD CMP DL,BL <-- Compare.
:004065CF JNZ 004065EF <-- This commences the compare loop.
This code isn't particularly challenging and you can of course just snatch your good code from EAX. I'll now show you how the serial number is calculated and also how to construct a key generator. Recall the first prefixing section, I initially thought I'd have to include that in the key generator, but of course the CTMAILER string is constant so the values of the registers will be the same for every name. Trace inside 00401E20.
:00401E37 SCASB <-- Classic string length.
:00401E38 NOT ECX <-- Invert ECX.
:00401E3A DEC ECX <-- Actual length in ECX.
:00401E3F MOV EDI,ECX <-- Store length in EDI as well.
:00401E41 CMP EDI,ESI <-- ESI was 0, silly check when it prefixes CTMAILER.
:00401E43 JLE 00401E79 <-- Irrelevant.
A few things to note here, firstly when you make an ASM key generator there isn't a great deal of point in using different registers than the actual calculation routine (unless of course your forced too), you'll just be making yourself debugging work, secondly note that EDI & ECX store the length of the prefixed string, our code will only store the name length (we'll load the registers with the default values from CTMAILER before we start).
:00401E45 MOV EAX, DWORD PTR [ESP+6C] <-- Name.
:00401E49 MOVSX ECX, BYTE PTR [ESI+EAX] <-- Name character.
:00401E4D PUSH ECX <-- Stack it.
:00401E4E CALL [0040A454] <-- MSVCRT.toupper (upper casing routine).
:00401E54 MOV EDX,EAX <-- Store name in EDX.
:00401E56 ADD ESP, 04 <-- Stack correction (not needed).
:00401E59 AND EDX, 80000001
:00401E5F JNS 00401E66 <-- Jump Not Signed.
:00401E61 DEC EDX
:00401E62 OR EDX, FFFFFFFE <-- -2.
:00401E65 INC EDX
:00401E66 JNZ 00401E72 <-- Which maths will we use on each letter.
:00401E68 LEA EAX, DWORD PTR [EAX+4*EAX+0A] <-- Arithmetic.
:00401E6C LEA EBP, DWORD PTR [EBP+2*EAX] <-- More arithmetic.
:00401E70 JMP 00401E74 <-- Next char.
:00401E72 ADD EBP,EAX <-- Else do this.
:00401E74 INC ESI <-- Character Pointer.
:00401E75 CMP ESI,EDI <-- Is name complete.
:00401E77 JL 00401E45 <-- Repeat.
Firstly note that this is the first part of the loop, EBP holds the only final value at the end of this loop. Secondly, after the loop through CTMAILER, EBP=B0Fh, this is a value which we'll use as a default. I won't insult your intelligence by explaining what "toupper" does, needless to say it does perform a move you should be aware of. The 2nd part of the generation routine is a pretty trite repetition of this one, at the end we have a few polishing instructions.
:00401EB6 MOV EAX, EBP <-- The 2nd loop uses EBP's
:00401EB8 SUB EAX, EBX <-- This code executes when EBP is greater than EBX.
:00401EBC MOV EAX, EBX <-- This code executes when
EBX is greater than EBP.
:00401EBE SUB EAX, EBP <-- More subtraction.
:00401EC0 ADD EAX, 64h <-- Final polish.
Don't miss the subtle check before this, EAX's value is calculated from EBP & EBX, the larger minus the smaller, then EAX adds 64h which will be the 3rd part of the code, the hyphens are constants. Outputting this result is a serious pain in ASM, this program fortunately has a nice high level language function to save the work. You'll find below a very rushed ASM key generator which I tested briefly, doing this key generator in ASM took 1/2hr longer than I expected because of all the register tracking and stages.
Sadly, registering this program didn't enable me to use it, it crashed with what looks like dll conflicts.