"xDEAD:xBEEF: extending HASP manufacturer's services" |
Advanced | |
by fravia+ |
||
fra_00F3 980312 bajunni 0010 AD P3 | Dongle |
|
Second part of the text deals primarily with accessing HASP memory. Some aspects of software protection are also included (not very organised, though).
Open mind for a different view And nothing else matter.. an old song by Metallica -------------------------------------------------------------- Undocumented HASP - Part II by -bajunny 4. Memo- ..stands for memory! ------------------------------ The HASP documentation says that MemoHASP-I has a total incredible amount of 112 bytes of memory ready for programmer use, while all happy buyers of NetHASP and MemoHASP-IV (which are essentially the same thing I believe) can take even more - 496 bytes. One can immediately realize, that in both cases HASP had reserved 16 bytes for its own use, because 112 +16 == 128 and 496 +16 == 512 and memory manufacturers enjoy power_of_2_numbers. This fact was further acknowledged by the following fragments of disassembled HASP driver code: ; API_service#6 . . . mov word ptr ds:[bp + 0ea], fff9; call 6496 . . . mov word ptr ds:[bp + 0ea], fff8; call 6496 . . . mov ax, ds:[bp + si + 0d3] ; HASP memory access commands . . . add ax, word ptr ds:[bp + 0ea] ; reasons for ADD will follow add ax, 8 ; ! . . . So real addressing for user-accessible memory begins from offset 8, while in offsets 0 and 1 resides the "unique HASP ID". In fact, the following 6 words are never user by any HASP software (I didn't look for Net- and Time- devices, though) so you will be able to place something even more _unique_ here.. But you need more details on HASP memory access indeed before... As we already have seen in the first part of this essay, HASP wouldn't give anything useful without proper activation. Memory access is no exception, and this is the sad news. The good news is that we actually have already acquired all necessary items for this activation. I mean the opening combination that we have found in the first part of this text. But we should stop at the correct moment: in fact we need to know that after the 15th outbyte() is issued, one of HASP's internal flip-flops switches output to query its booleans.. The moment after 14th outbyte() is right. It's amazing, but if you will try to retrieve Boolean at that moment HASP returns only zeros to you - it definitely indicates some change in HASP internal state! Change for some memory work! Technically speaking, all memory ops are issued through appropriate commands. These commands along with their arguments and subsequent results are passed to HASP serially - that is bit by bit by signalling specific bits just like bit0 was signalled in the outbyte function, forcing HASP to parse its input as command bytes. 14th byte of opening sequence was used as a background for this. - This is the reason why this byte was set to certain value (x9C) irrelevant of all other password related fiddlings. Command length is 10 bit. HASP driver provides the 7 following values as command ops (all presented as bit strings, x's stand for address values): 0110xxxxxx - read word from address specified 0101xxxxxx - write word to -------//-------- 0111xxxxxx - erase word at -------//-------- 0100110000 - enable write ops 0100000000 - disable write ops 0100100000 - ? unknown, apparently no effect on Memo-'s 0100000000 - ? the same.. So, to read word from address 9, one should send the following 10 bits to MemoHASP: 0110001001. Sending are performed by signalling bit6, along with bit5 alterations (see my code at appendix). Do not forget to begin and end all memory operations by signalling bit1.. Resulting word is received also in a serial manner, see below the code inside hasp_read_word().. If you happen to torture MemoHASP-IV, just expend these command strings by two more bits, allowing full 256 words address space (and of course call hasp_send_cmd( ..., 12 )!:) Writing is analogous, but first one must enable write using a special command. HASP driver also issues obligatory erase before each write, but it's not really necessary: write successfully sets both 1s and 0s. One feature for erasure and writing: HASP driver has a specific code that waits for state change after each of those two operations, I put something analogous to wait_till_burned() routine below, though no actual wait was ever detected during my own experiments... If you dare to use my routines to read/write some HASP memory, you won't see any expected values, because once again HASP designers used some silly obfuscating schemes to conceal their data. So you need first of all a password number to correctly decipher it. I already warned you there could be some ambiguities in password detection, well, here is the place where they can be encountered. But in fact this obfuscation CAN HELP to get the right password: many areas inside HASP memory holds initial xFFFF's (you see, erasure sets bits this way) - and this is especially true for all hidden words at 2..7! They are set to xFFFF. Obfuscation algorithm is presented inside the code fragments in appendix, it uses simple XOR of 1st word of the password, address of word and constant of xFF00 for addresses 0..7 (well, actually xFFF8..xFFFF inside the HASP driver). I played a little with command opcodes, hoping to fish something interesting, but without success. Maybe you will be more successful... if so write about it. 5. HASP ID story. ----------------- The extremely vague HASP documentation warns you that: "You cannot order HASP keys with specific ID Numbers. These are assigned pseudo-randomly during manufacturing and are guaranteed not to repeat".. So if your HASP has some ugly ID like xA60D:x12F7 you have to live with it?? No, no,no! Bajunny CAN help you to change it to something "prominent" like xDEAD:xBEEF or x1234:x5678 (as in all my HASPs) or whatever you like... extending thus the manufacturer's services, power of good cracking ;) Of course everything is already prepared: HASP ID lives at the very beginning of memory, words at _0 and _1, this area is accessible and is not write protected.. You already have all necessary information to carne your own HASP ID. Nothing much to be added to the ID story except to mention that ID is checked sometimes by the envelope routines.. But for other crucial HASP parts: password and booleans I have no way to modify by means of software (but who knows.. what if... we will see ;) my wish to invent some mechanism to make one HASP start mocking another failed... So end of the story... for now ;) 6. Conclusion (again too long). ------------------------------- When writing these words I have to admit to you I finally got awfully bored of all this HASP super protection. Well, once more we have to observe the old banal truth, so common in our cryptography intense world: security through obscurity is worse than no security at all. So what we have in these "ultrastrong" HASP dongles? What's inside them? Almost nothing interesting. In fact, today already exist more decent dongles, documentally presenting strong algorithms inside (or I'm still dreaming, are they as easy to reverse?) having at least PIC-complexity rather than a simple set of flip-flops and memory cells.. Well, the HASP people can and will surely argue that they have at least implemented a strong software protection. It's complete bullshit - all info I have given to you in my essay has been gathered by myself through disassembling and experimenting with software. No ion-beams or layer etching intervention. Nothing in my hands! And I didn't encounter _any_ cool anti-debugging tricks! Well, some folks say they implemented anti-softicing like disabling breakpoints and firing something like "hboot" to your debugger's command line.. I don't know.. In fact, I've used winice only to get rid of HASP for the InscriberVMP program... and it was my first experience with windoze debugging.. Yeah, I use windoze only to format something to print on laser or to browse those great pages of fravia+ :) - all other experimenting still in good old doze.. Where else can one find such a well documented, inexpensive, _true_ real-time OS ? :)) Maybe in the future I will present a more comprehensive survey of HASP software protection. All this enveloping stuff, and the like. Right now I'm not sure it will ever materialise. Not because its difficult, but because its very boring, and I've almost spent my strategic supply of Homeric laughters looking at something like: "FAS - Full Authorization System" This seller's hypo stands for some feature in enveloping: you can assign a number to a program and specify a maximum number of activations. Sounds good? In fact, this FAS system eats half of your MemoHASP cell space - 2 words for each 16 possible program numbers, first word to check if corresponding slot was occupied (xFFFF if not, any other value if yes, HASP... puts x0000) while the second word keeps the counter (xFFFF if unlimited activations..). Of course you can edit everything with my functions below or even using HASPEDIT. Well, what should I say? I sip a good cup of tea, observing this moronical hype once again and have decided to give up, my dear reader... it's too easy and too stupid... Even fighting windmills is better than fighting stupidity.. APPENDIX -------- Here are some fragments to be added to my little cracking program from the first part of this work of mine
The author encourages you always to look one level deeper, of course if the time and patience would permit it... if you do, by all means, write and document and publicize your findings...