http://www.infonegocio.com/vbcrack/vbapi.htm - List of all VB6 exports (good reference too).
Sivan Design's CIVILCAD 2000 is available on the web for download as a 15-day trial (57Mb's), this trial allows all 5 editions or 'flavours' to be trialled, a good idea for potential buyers imho. I looked at this target initially because it appeared to be protected by a HASP dongle (we'll see how this is and isn't the case later on). This tutorial will not damage the authors in anyway since a cracked version has already been released to the scene by a group calling themselves PARADOX (a pretty bodged job actually in my opinion but more on that later ;-) ), I'll also describe the logic of my approaches since this appears to be an area where many newer reverse engineers struggle.
The trial version ships with the HASP driver installer Hinstall.exe & the HASP API communications dll haspvb32.dll. CIVILCAD looks for all intent and purposes like it can be made to work by emulating the presence of the dongle.....I decided to put breakpoints for the main hasp() routine exported from haspvb32.dll. Nothing broke, I was still looking at the trial screen. A quick journey into SoftICE later, 'vxd hasp95dl' & 'vxd hardlock' confirmed that the HASP drivers hadn't been loaded. No dongle access here.
After disassembling Civilcad.exe in IDA (this will take a while, you are warned!), I quickly isolated the 'haspvb32.dll' reference, its loaded via the import _DllFunctionCall at 4E9BFD. This routine (sub_4E9BE8) has 16 references, grouped into 3 distinct areas of the file. Analysis of just one of the callers confirms this is the hasp() routine, 9 parameters are pushed onto the stack each time which is exactly what all HASP services require.
:00A60112 push offset dword_153A44C ; Par4.
:00A60117 push offset dword_153A448 ; Par3.
:00A6011C push offset dword_153A444 ; Par2.
:00A60121 push offset dword_153A440 ; Par1.
:00A60126 mov edi, 1
:00A6012B push 48DFh ; Password 2.
:00A60130 push 443h ; Password 1.
:00A60135 push edi ; Port.
:00A60136 push 12Ch ; Seed.
:00A6013B push 2Ah ; Service (Login).
:00A6014D call hasp
A quick look in the HASP manual and we can label our parameters (like I have above). So CIVILCAD uses a NetHASP (deduced by the Service), with password 1 0x443 & password 2 0x48DF. By examining the other services we can see that various words of the dongle are read and the HaspCode() algorithm is called with seed 0x12C (the return values indicate this is a HASP 4 generation). All of this information is nice, but in reality it isn't useful. Tracing up the code tree for each of the 3 areas where the hasp() calls are, it becomes apparent that entire swathes of the HASP calling code and other routines are never reached. Finding even where 1 function should be called is usually a craps shoot, where 3 ought to be inside 17Mb's of code is pretty much an impossibility.
Of course none of this is a real problem, we know now what these developers probably did, they commented out in their source the highest level routines responsible for calling the HASP and left in everything else. This leaves us with the 15 day trial scheme, which can be isolated fairly trivially, searching for the unicode string 'Sorry, the trial period has expired" will lead to 2 simple cross references. Lets take a look, by simple backtracing of the nag message we uncover this :
:013F4B49 call ds:rtcGetDateVar ; Get current date.
:013F4B4F lea eax, [ebp-84Ch]
:013F4B55 push eax
:013F4B56 call ds:__vbaI4Var ; Convert.
:013F4B5C mov [ebp-74h], eax ; Save current date (actually number
of days).
This is the second part of the protection (I'll discuss the first part which covers how the program derives the first run date) at the end. In this snippet we get the current date, convert it & save it in [ebp-74h], I didn't find much documentation on the API but I believe this value reflects the number of days since 01/01/1900 (in my case we get 0x946D or 37997 (a quick use of the calculator confirms my assumption is more or less correct)).
:013F4BF8 mov eax, [ebp-74h] ; Current Date.
:013F4BFB sub eax, [ebp-78h] ; Start Date.
:013F4BFE jo loc_13F571B ; Check for overflow.
:013F4C04 xor ecx, ecx ; ECX=0.
:013F4C06 cmp eax, 0Fh ; EAX=time left in days (0xF=15 trial).
:013F4C09 setnl cl ; Set CL if times up.
:013F4C0C mov edx, [ebp-74h] ; Current Date.
:013F4C0F sub edx, [ebp-78h] ; Start Date.
:013F4C12 jo loc_13F571B ; Check for overflow again.
:013F4C18 xor eax, eax ; EAX=0.
:013F4C1A test edx, edx ; Is time left 0.
:013F4C1C setl al ; Set AL if no times up.
:013F4C1F or ecx, eax ; OR flags.
:013F4C21 test ecx, ecx
:013F4C23 jnz loc_13F4E63 ; 0 = trial still valid.
The end game is shown above. Overflow errors are checked for and the remaining number of days left in the trial will be compared to 15. There is also protection against simplistic tampering, all that is needed is to ensure ECX is 0 at 013F4C21 and we won't be expired, although you will have to live with the nag screen telling you there are now negative days left in the trial.
So where does our initial run date come from?, well no surprises that one location its in is the registry. I used SoftICE to track where ebp-78h's value came from (013F4306 is where its written) and then worked my way back from there. The pertinent keyname is in HKEY_CLASSES_ROOT\CLSID\{A9FC132B-096D-460B-B7D5-1DB0FAE0C063}\TypeLib, hard-coded into Civilcad.exe. The value here for my key is {F0D2F211-CCB0-11D0-A316-D3E130012DDA}. Lets see the part we are really interested in :
{F0D2F211-CCB0-11D0-A316-D3E130012DDA}
1. 130012 + 74 (0x4A) constant = 130086
2. 130086 / 3.3 (double constant) = 39420
3. 39420 - 1458 (constant) = 37962 (0x944A)
Lets say now we want to regain our 15 days trial, we'll need our key to be the current day (0x946D).
1. 0x946D (37997) + 1458 (constant) = 39455
2. 39455 * 3.3 (double constant) = 130201.5 (round down to 130201)
3. 130201 - 74 (0x4A constant) = 130127 (0x1FC4F)
We amend the key in the registry (note amending the first copy you find will automatically amend the second too) and run CIVILCAD. It doesn't work.....Why?, well the good CIVILCAD developers have also decided to store the first run date in several other files (in your system directory odbcex32.dll and in the CIVILCAD program directory prototype.pr1 are also stamped) be sure to amend these too since they are checked against our registry entry. We run CIVILCAD once again.....it works. Note also that any files you create with this demo version will be time stamped in the same fashion.
The PARADOX Patch
Analysis of PARADOX's ready made patch is discussed very briefly. In total 5 patches are made. Of these the only necessary one to work beyond the trial period is the NOP'ing of the jnz at 013F4C23, the remaining patches are completely unnecessary.