Localize the check in SoftICE with a bpx GetWindowTextA, follow the input. You will notice it will go through some calculation and then be checked against some number, if equal return will be 1 else zero. This check just controls the enabling of the continue button. Use some password and change that switch, then click continue, following still that password. We will pass that first check, then again the same kind of comparision, if equal jump, then you will notice the password gets copied and thrown into a very time-consuming routine.
Disassemble this routine. You will notice that first the password gets XORed with a doubleword, that is to say every 4 bytes gets XORed with that same DWORD. Then a temp file (the actual installation file) gets byte wised treated with the resulting key in a simple way : the low and high bits are exchanged and the resulting byte is XORed with a key byte. This procedure takes time since the temporary file is big. The resulting "decrypted" temp file is now checked for its signature : the first 4 bytes should read MSCF this gives us in fact the first 4 password characters as ISE2.
Now some simple cryptanalysis : increment the password length until you see recognizable parts in the temporary file : this will happen with a length of 5 and 10. You will see for example word parts like this "isk1" "\Dis" "out,"etc. If you compare with a known InstallShield package file you will notice that it contains phrases like Disk1\layout.bin etc. So it is clear that the pass length is 10 and it is now easy to reconstruct the missing characters.
The HASP wrapper checks for SoftICE. This version only checks by trying to open the NTICE driver. So either change that name in your SoftICE (in all files) or bpx CreateFileA, first hit will try to open NTICE, change it there to something else, i.e CreateFileA should return -1. HASP's wrapper uses a tedious "onion skin" encryption scheme : it is built out of small routines with names *.mod. Each mod usually starts by decrypting the next .mod then if it is a functional mod it does what it is suppposed to do (for example killice.mod, detects SoftICE, hasperr.mod takes care of dongle error messages, hasp.mod contains the dongle access routines etc.) or if it is a functionless mod it just passes flow to the next mod, perhaps by obscuring the flow a bit using interrupt handles (flow using INT 3 or illegal instruction).
Our job is the following, find where hasp.mod gets decrypted, note the decryption routine (e.g. print it) and its arguments. Decryption routines have as arguments : offset (from where to decrypt), length (how long is the mod to decrypt) and a seed value. Not all decryption routines are routines, some are implemented as a loop. They all have the same structure though, with just some minor changes.
Code this encryption routine in your familiar language, decrypt the hasp.mod. Patch what you want to patch and encrypt it again (for encryption you might have to make some small changes in the encryption routine).
For mamoe.exe it works like this : bpx CreateFileA, change NTICE to something else; look in the routine that called CreateFileA, scroll a bit upwards to find the memory that contains the address of the next .mod (in the beginning of the routine in the form cmp [...],0 / jz ... Now set a bpx on the start of that mod, check its name in the data window, will be at the end of the routine. Continue till you find hasp.mod.
Most mods have the name gag#.mod they are the functionless mods. Usually hasperr.mod will come just before hasp.mod. I usually put the HASP emulator in a dll I have constructed with as entrypoint GetEnvironmentStrings, thats just to be able to patch it minimally. Note the decryption of the main program is based on the HaspCode routine. Its algorithm is known (discovered by UCL from the HASP encryption package). Some memory read from the dongle might be used to set some flags, in the case of Mamoe.exe addresses 18h & 19h, they should be in this case 0 & FFFFh.
Kashmir (June 2000).