http://www.dialogscript.com - Webpage (updated to v5.0 now I believe)
Before I start, I'd like to wish everyone reading this tutorial a very happy christmas :). The objective of this tutorial is to produce yet another key generator by examining the build up of a valid serial number, in fact VDS uses a fairly interesting algorithm although its concept is not particularly new. You ought to know the drill, launch the program and locate the register dialog, the registration codes are all 200- prefixed, kind of stupid really.
Reaching the calculation routine requires the use of Hmemcpy (3 breaks) then F12 work through the usual stack patterns. I'll tell you basically now how the scheme works, both the name and user name are used to hook into a hard-coded table (fish through W32Dasm's string references and find the table "ghj68HGfr57mKhf60.....", this generates one DWORD value which is stored always at ECX-04. In my case CrackZ / Zencrack produces a result of 4393928. This result is then prefixed by another hard-coded in value (7238824) to give 72388244393928, the program then discards as many characters as necessary to leave 8 numbers before adding the real prefix (200-). In my case the result is 200-44393928.
The relevant code is shown here, I'll explain the snippets below 0045499C as I go along.
:0045C78B MOV EDX, DWORD PTR [EBP-08] <-- Company/Location.
:0045C78E MOV EAX, DWORD PTR [EBP-04] <-- Name.
:0045C791 CALL 0045499C <-- Call_calculation_routine.
:0045C7A0 MOV EDX, DWORD PTR [EBP-0C] <-- Entered code.
:0045C7A3 MOV EAX, DWORD PTR [EBP-10] <-- Good code.
Any "I must register now" crackers can snatch their good code from EAX and bid farewell, to produce a key generator however you'll need to trace into 0045499C. The program starts by initialising a DWORD location with a hard-coded in value.
:004549CF MOV [EBP-04], 047440B1 <-- Initialisation.
:004549DE MOV EDX, 00000003 <-- More initialisation.
:004549E3 CALL 00454954 <-- Hook into the table using the namelength.
So, the first stage of the protection is to use the name length (which can't be greater than 30) to hook a table value, this value is then looped until 0, storing the result at [ECX-04] (it might be an idea to have a watch on that). Here's the relevant name length loop code which is also used to loop the name and company in similar fashion.
:0045495E AND EAX,8000001F <-- AND namelength.
:00454963 JNS 0045496A <-- Jump not signed.
:0045496A MOV EBX, DWORD PTR [0045E990] <-- Table at EBX.
:00454970 MOVZX EAX, BYTE PTR [EBX+EAX] <-- Hook table value.
:00454978 MOV EBX, DWORD PTR [ECX] <-- The store location.
:0045497A ADD DWORD PTR [ECX], EBX <-- Add to store.
:0045497C ADD DWORD PTR [ECX], EDX <-- Add EDX to store.
:0045497E CMP DWORD PTR [ECX], 05F5E100 <-- Compare to default.
I won't comment any more here, needless to say this is just a big loop, the DWORD result at [ECX-04] being used as the store. This is the first part of 4 of the key generator and as 00454954 performs the same loop through the user name and company its your choice whether you want to try and sub these functions for all 3 iterations. Ordinarily I'd write more but your main reference is the source code of the key generator which I've coded (see the Key Generator archive). Certain parts of it aren't recomended practice but it does illustrate how you can write the equivalent of high level language functions in ASM.