Inec Investor 7.3 - Tutorial by aSL!

"A brief and succinct tutorial describing how you can quickly unpack the old HASP envelope, this is aided immeasurably by the fact that this target is written in Delphi, try this technique with anything written in VC++ for example, and you'll be doing much more work than this ;-), needless to say I like the idea of changing the call haspreg() to call haspemu() live in the debugging process." "Slightly edited by CrackZ."

Subject : HASP Undongling.
Target : Inec Investor 7.3

All information written below for educational purposes ONLY.


We have a program named Inec Investor 7.3. A demo version is available however it remains a demo, I will investigate therefore the full version. It costs about $1700. After the first run the program displays a window which looks like this :

This tells us that this program is protected using a HASP dongle. After the quick view on the executable, we can see that CODE and DATA sections are encrypted, the section .protect is present, and the original entry point is set into this section. Resources are telling us, that the programm was written in Delphi. OK, what's next?.


1. It is necessary to remove the envelope.
2. Remove any unnecessary HASP checks.


SoftICE 4.x, IceDump 6.x, W32Dasm 8.9x, Hiew x.x.

Let's start...Load Investor.exe into SoftICE. We must note, that HASP envelope checks for SoftICE trying to recieve access to \\.\SIWV. This can be simply bypassed by setting a breakpoint on CreateFileA and after the call making eax=FFFFFFFF. But we are using IceDump, which protects us from this. And the final note : I suggest you don't use bpx, but bpm Addr X, because I have some cases when SoftICE crashes using bpx'es.

First of all, we must find the "high level" HASP API call. This is simple. There are several different ways we can do it including
the famous HASP trademark "HASPDOSDRV" or "cmp bh, 32", but the easiest way will be to set bpx FreeEnvironmentStringsA. After that, we press F12 and see the following screen :

:009A3377 PUSH EBP
:009A3378 CALL 009A532F
:009A337D POP EBP

At address 9A3378 the high level HASP API call is situated. Remove all breakpoints and make a new one : bpm 9A3378 X. Press F5 several times, we can see, that there are some different HASP calls (the service code is passed through BH). In the first time we see BH contains 01, which indicates IsHasp() call. After the call set AX to 01 and press F5 again. The second time BH contains 02, which indicates HaspCode(). It returns a 64 bit integer (in AX, BX, CX, DX) by given seed code in AX. I can also note, that the dongle used by the program is MemoHASP-1, so the HaspCode() algorithm was discovered some years ago (For me, it was bajunny's paper in 1998). We can also use the CrackZ's implementation of HaspCode() function
built in IceDump.

The passwords are passed through CX & DX. So we can simply type /haspcode but I suggest you make some patch
to avoid the typing this (I'm so lazy to type this for several times). For us, it will be more preferrable, if we want to unwrap the envelope. (Who knows, what can be in the future?). There are three calls of HaspCode() from the envelope, so take a paper and pen and write seed codes down : The first and the second was 0648Eh and the third is 0F999h. The answers you can find from the code below. After that, I've made some code, which was placed in the padding between CODE and DATA sections :

003EE619: 80FF01 cmp bh,001
003EE61C: 7504 jne 0003EE622
003EE61E: 33C0 xor eax,eax
003EE620: 40 inc eax
003EE621: C3 retn
003EE622: 80FF02 cmp bh,002
003EE625: 7409 je 0003EE630
003EE627: 33C0 xor eax,eax
003EE629: 33DB xor ebx,ebx
003EE62B: 33C9 xor ecx,ecx
003EE62D: 33D2 xor edx,edx
003EE62F: C3 retn
003EE630: 663D8E64 cmp ax,0648E
003EE634: 7511 jne 0003EE647
003EE636: 66B8A2AF mov ax,0AFA2
003EE63A: 66BB7CD1 mov bx,0D17C
003EE63E: 66B9E253 mov cx,053E2
003EE642: 66BA99F9 mov dx,0F999
003EE646: C3 retn
003EE647: 663D99F9 cmp ax,0F999
003EE64B: 75DA jne 0003EE627
003EE64D: 66B8901D mov ax,01D90
003EE651: 66BBCA92 mov bx,092CA
003EE655: 66B9DDFF mov cx,0FFDD
003EE659: 66BA57C6 mov dx,0C657
003EE65D: C3 retn

As you can see, this code makes does all the dirty work for me. After loading Investor.exe in SoftICE I simply type "bpm 9A3378 X". After that "a eip", "call 7f5019". All necessary work my code does for me!. Press F5 several times, until seed is F999. Type "DD 401000", and remember, that the first dword in Delphi's CODE section is always 00401004. After, trace before the code shown below :

:0099CB58 MOV [0099DC70],EAX
:0099CB5D CALL 0099CD24
:0099CB62 MOV [0099D398],EAX

As we can see, the call at address 99CB5D decryptes CODE and DATA sections. All we must do is to dump those sections to disk, The last problem is to find OEP. There are many different ways to do this, but the easiest is the following : find the address range of Investor.exe (for example, using map32, or PEEditor), after that type "bpr 401000 401000+3D18b4 RW" and press F5. Yes! It breaks at the OEP :

Thus, OEP is at the 7D2460. All, that we need is ready. Let's start to construct .exe. (I must note, that envelope leaves .idata and .reloc sections unchanged, so the question with imports and relocations is not set). In every hex editor we must remove CODE and DATA with our dumped versions. The offsets for they are: 400h and 3DE100h. After, at 0128h we must put the RVA of OEP. (We have VA, and RVA is computed by RVA=VA-ImageBase), so not 07D2460h, but 03D7460h. At the offest 0180h we must put the RVA of import table (Which is the same, as RVA of .idata section -- offset 027Ch), and at 0184h .idata's size (look at 0380h). RVA of relocations must be putted at 01A0h (the RVA of .reloc at offset 02F4h) and at 01A4h its size (look at 02F8h).

That's all. Try to run!!!, Voila! It runs!.

Breaking the program's HASP checking

Yes, the program runs, but it says :

"Íàðóøåíèå êëþ÷åâîé çàùèòû. Êîä HASP-êëþ÷à íå ñîîòâåòñòâóåò âåðñèè ïðîãðàììû".
"Dongle protrection violation. The number of the HASP-dongle doesn't correspond to the program's version".

It uses not only simple envelope protection, but checks the key by itself. It is simple. All necessary code snippets
are listed below :

:006661F6 E8F9090000 call 00666BF4
:006661FB 837DE800 cmp dword ptr [ebp-18], 00000000
:006661FF 7545 jne 00666246

:0066626E E881090000 call 00666BF4
:00666273 837DE403 cmp dword ptr [ebp-1C], 00000003
:00666277 740C je 00666285
:00666279 837DE400 cmp dword ptr [ebp-1C], 00000000
:0066627D 754B jne 006662CA
:0066627F 837DE000 cmp dword ptr [ebp-20], 00000000
:00666283 7445 je 006662CA

:00666300 E8EF080000 call 00666BF4
:00666305 837DE000 cmp dword ptr [ebp-20], 00000000
:00666309 7478 je 00666383
:0066630B 807DFF00 cmp byte ptr [ebp-01], 00
:0066630F 0F8449010000 je 0066645E

:006663F2 7F09 jg 006663FD
:006663F4 817DE4FFFF0000 cmp dword ptr [ebp-1C], 0000FFFF
:006663FB 7540 jne 0066643D

:0066651C E8D3060000 call 00666BF4
:00666521 837DE800 cmp dword ptr [ebp-18], 00000000
:00666525 753B jne 00666562

The solution is fairly simple, but I must note, that this program can work not only with MemoHASP-1, but with NetHASP too, so if you patch at address 0066BF4, you must remember this, but forcing the above jumps will make the program think that it uses MemoHASP-1.

End Notes

(c) 2001 by aSL! (

This essay can be freely distributed / published / printed etc... as long as no modifications are made in anyway.

Greets to : Everyone in UOFG (, CrackZ for his site, and everyone, who think that he must be here.

greenball.gif (835 bytes) Return to Dongles greenball.gif (835 bytes) Return to Main Index

© 1998, 1999, 2000, 2001 aSL!, Hosted by CrackZ. 10th July 2001.