http://www.cyberspacehq.com - Webpage (addsoft2.exe - (1.00Mb)).
This is an updated tutorial (previously I'd looked at v2.11), at that time I had been waging something of a personal war against this type of program. AddSoft is a software submission program for shareware authors, it claims to take all of the hassles out of uploading/promoting your software to various shareware archives, at $89 it would indeed need to be a lot of hassle before I considered buying this program, so lets start.
You'll easily locate our registration option, so enter a user name and registration code, I'm as ever using CRACKZ & 0123456789, it seems that Windows API use is kept to a minimum so you'll need to >bpx Hmemcpy to gain an entry point, note also there is no failure message box which indicates that the protection writer at least thought about the scheme a little bit (deadlisters will of course be disappointed if they look for a success message).
You should easily locate the main protection routine shown below (after allowing the necessary SoftICE breaks, hit F12 about 12 times, you'll even F12 through the infamous BOZOSLIVEHERE), else trace with F10.
:00480AA1 MOV EAX, DWORD PTR [EBP-04] <-- Number entered.
:00480AA4 MOV EDX,00480B44 <-- TRIAL MODE.
:00480AA9 CALL 00403DF8 <-- Compare.
:00480AAE JZ 00480B18 <-- Jump_trial_mode.
:00480AF1 CALL 004754D4 <-- This_must_be_traced.
:00480AF6 MOV EBX,EAX
:00480AF8 MOV EAX,[004A642C]
:00480AFD MOV EAX,[EAX]
:00480AFF MOV BYTE PTR [EAX+00000784],BL <-- Good_guy/Bad_guy_flag.
:00480B05 MOV EAX,[004A642C]
:00480B0A TEST BL,BL <-- Good_code_sets_BL_non_zero.
:00480B0C JZ 00480B18 <-- Jump_bad_code.
O.K, I'll explain why I've deleted the lines in between 00480AAE & 00480AF1, the reason is simply this, there are no conditional jumps in between these 2 addresses, so even if there was a string length check or other check the program will still reach 00480AF1 regardless. You'll need to trace 004754D4 to find the good registration code, after some simple string length checking for 0 you'll reach this code.
:00475520 MOV EDX,000007CE <-- 7CEh used to calculate
portion of good code.
:00475525 MOV EAX,[EBP-04] <-- Name.
:00475528 CALL 00471F00 <-- Trace this if you are going to produce a key generator.
:0047552D MOV EAX,[EBP-0C] <-- Else get the good code here.
:00475530 MOV EDX,[EBP-08] <-- Code entered.
:00475533 CALL 00403DF8 <-- Compare codes.
:00475538 JNZ 0047553E <-- Jump_bad_guy.
:0047553A MOV BL,01 <-- Good_guy_flag.
The key generation routine beneath 00471CD0 is actually pretty tedious indeed, but take a look if you are so inclined, I'm not sure whether all the function calls are compiler generated or an over zealous programmer using "functions to do everything". The good code is calculated in 2 stages, the programmer first uses a loop from 00471F67 - 00472297 through each of the name letters attempting to find a match (this is really inefficient and quite possibly intended to be so). A good compare provides a single integer value for each letter of the user name (I really don't advise you trace this).
Here's a copy of the table.
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z 5 3 8 2 8 4 1 7 9 2 7 1 4 5 1 6 7 3 8 4 9 1 3 8 1 3
Hence using this table my user name CRACKZ becomes 835873. There are of course several things you might like to verify, firstly how does the program handle longer names which will generate huge values for the next stage?, how does the program handle space characters?, how does the program handle numbers/other ASCII characters?. I'll answer some of those for you, it would seem all numbers barring 0 (which is switched to a 3) remain unchanged, where as non-alphanumeric values e.g. hyphens, brackets are disregarded. Space characters are represented as 9, however the presence of a space seems to act as a switching mechanism, directing the program to take the first 3 numbers and last 3 numbers reversed. Of course my handle being 6 letters long with no spaces behaves rather conveniently.
Having generated this value the program multiplies it with 7CEh (1998) to give 1669085244 which is then output and reversed to give the correct serial number.
1 6 6 9 0 8 5 2 4 4 <-- reversed. 4 4 2 5 8 0 9 6 6 1 <-- correct.
Of course from earlier we can see where the 'real' check will happen, so it seems a fairly simple task to patch the code instead. To summarise this isn't actually a bad scheme, the protectionist has learnt several things, the algorithm requires working through and many functions might lose an inexperienced SoftICE user. Unfortunately the memory echo is all to easy to find and its even easier still to change just 1 instruction and register, note that the user information is written out to the registry.