Undocumented HASP
(no more security through obscurity)
advanced
Advanced
27 May 1998
by Bajunny
Courtesy of Fravia's page of reverse engineering
slightly edited
by fravia+
fra_00xx
980527
Bajunny
0010
AD
DG
...maybe the HASP designers never took this into account and 
concentrated rather on production costs... and cut costs on 
good encryption... they must have thought that neither the 
(gullible) programmers nor the (incompetent) testers would 
ever have found out the terrible intrinsic weakness of this 
HASP scheme...


... luckily there are some good reversers around, like Bajunny, that with this last part of his now famous Undocumented Hasp essay, eliminates once for all Aladdin's protection scheme, which proves to be rather trivial (russian dudes have even created automated 'dehaspers'). Software programmers, take note: NEVER trust commercial protectors: see, FOR MONEY you'll always be able to get only "poor concocted" protections , you'll find FAR better protections FOR FREE (on this very site as well). As usual, on this web of ours.
+dongles
Dongles
There is a crack, a crack in everything That's how the light gets in
Rating
( )Beginner ( )Intermediate (x)Advanced ( )Expert

Some necessary final words for my Undocumented HASP project..
Undocumented HASP
Closing Part
Written by Bajunny


Essay
--------------------------------------------------------------
                    Undocumented HASP,           by -bajunny
                         Part III
                 (hopefully the last one)
               
    7. C'est la mort du petit cheval.
    ---------------------------------  
  Brushing up my materials on HASP reversing while writing
these words I suddenly realized there was nothing more to add!
You have been shown how HASP produce its answer to given seed,
and now you are able to bruteforce HASP password in case you have 
a solitary dongle and no corresponding software... boy, you can 
even read/write ALL hasp memory!
  
  Of course, there were some dark spots in my narration - bound
to be, coz I never tried to contact the manufacturer and
had no information whatsoever on internals (hhe, I will hardly
receive anything but useless advertisement brochures).. 
I also didn't describe the necessary electrical wiring here: 
it's rather trivial, just imagine famous HASP ASIC and 
93C46X EEPROM and a bunch of diodes...
Such EEPROM is not protected and can be soldered away and 
analyzed - well, it's not necessary: it can be read/written in 
place much more easily..
  
  Soon after publishing part II I was told that memory is 
accessed through MicroWire(tm) protocol - and so opcodes
0100100000 and 0100010000 stand for "bulk erase" and
"bulk write" respectively (do not forget to save your HASP
memory content before you decide to play with them:) - many
thanks to Highway SÅar for that info!
  
  Very interesting things came from the "secret table". Let's look
again at this neat 64-bit-to-one boolean function, that I prefer 
to arrange as 8x8 table. Here is the snapshot for one of my HASPs:

0 1 0 1 1 0 0 1  please note, number of 1s and 0s are equal and
1 1 0 1 1 0 0 0  all columns exhibit some very clear symmetrical
0 1 0 0 0 0 0 1  patterns. I have observed about 10 such tables
1 1 0 0 0 0 0 0  (not a big number for solid statistics, BTW)
0 1 1 1 1 0 1 1  and everywhere I saw only vectors from the set
1 1 1 1 1 0 1 0  { 00000000, 11111111, 10101010, 01010101,
0 1 1 0 0 0 1 1    11001100, 00110011, 11110000, 00001111 }
1 1 1 0 0 0 1 0  (how close to the truth was I!! -- see appendix)

  This observation moved me to the following explanation of the
boolean's output: input actually consists of two triads, one to
select a certain bit from the other, invert or not invert it and
so generate a vector from the set above..
*** ***
 |   |           For each boolean we have thus a complexity of 
 |  selector     8 triads (or 24bits..) - so Aladdine could not
 |               make more than 16M unique HASPs :)
bits to be selected, add an imaginary 4th wire for a constant
input - totals in 4 + inverted ==> 8 vectors!
   
  All HASPs I've tested had symmetrical booleans - I strongly 
believe it is this that made some independent testers trust 
in HASP API#2 good security... The reason is that linear 
congruential RNG, though very weak, provide "linear", i.e. 
uniform performance on bin test - and if boolean is also 
symmetrical (in a crypto sense, i.e. it has equal number
of 0s and 1s) the output would be rather "random-looking" 
and non-biased for simple statistical tests if only boolean 
isn't degenerately symmetrical (in usual sense). But it's all
my fabrications, maybe the HASP designers never took this into
account, concentrated rather on production costs... and cut 
costs on good encryption... they must have thought that neither 
the (gullible) programmers nor the (incompetent) testers would 
ever have found out the intrinsic weakness of this scheme... 
  
  Observation of that symmetry really helps when reconstructing
secret tables by some known HASP answers but I never expected that
the key to HASP secret table structure had been in my hands
all the time! But listen to the real story!...
  
  At the beginning of May two russian crackers (MeteO and Fixit)
have found by trial&error and pure Zen pondering the strongest 
correlation between the secret table boolean and the HASP password!!! 
As MeteO said: "now HASP is really DEAD", there's nothing left except 
EEPROM.. Automatically all the problems with ambiguous password
detection vanished, coz now one can draw a secret table from the
password and the contrary as well! YOU CAN DERIVE the valid password 
from the secret table (which is observable after a quick session of 
password bruteforcing)!
  
  The relevant code is presented in appendix. Now I would like to 
give some finalizing comments for my "Undocumented HASP" essay... 
I hope you survived boredom reading through this...
  
  Well, I hope this text was useful. Its main purpose was not 
to show you what's inside HASP, which proved fairly easy, but to show 
you all the IMPORTANCE to dig deeper in order 
to UNDERSTAND things. 

As far as I remember the black magic of cybernetics, Ashby law states 
that the required variety of regulator must exceed those of the system 
being regulated. 

So whenever someone tries purposely to lower the amount of relevant 
information available to you (Micro$oft, anti-reverser regulators, 
obfuscating programmers...) he actually lowers your required variety 
- and you become therefore much more controllable! (Sorry, I should stop 
this rambling here, it certainly needs more preparation - but I guess 
that now you yourself have athered a different vision than before, 
haven't you? :) 

Another note: remember that "shoulders principle"? When I bumped into 
MeteO's results I was at first dumbfounded, but he reassured me - "After 
all, without your findings we wouldn't have gone any further.." And I  
believe that the open +HCU university is playing indeed a great role 
"to make bridges, not walls"! 

  Yours faithfully,                                 --Bajunny
  
  Thanks to:
    MeteO and Fixit,
    Highway SÅar,
    Shaman,
    and, of course, to all +crackers and to the +HCU!

  "Special" thanks to the "programmers" of
   Aladdin Knowledge Systems Ltd. for their laziness and 
   their lame attempts to obfuscate their really dumb and 
   ugly code...

APPENDIX -------- // TOTAL DISCLOSURE of HASP codegen!!! // ------- slightly bugfixed.. -------- /************************************************************************** * * This code is only for demo and educational use! * * The HASP(R)codegenerator and its documentation are copyrighted by //UCL. * All rights reserved. * * This is *complete* HASP seed code generator for NetHASP(TM), MacHASP(TM), * DataHASP(TM), TimeHASP(TM), SerialHASP(TM), HASP36(TM), MemoHASP36(TM), * NetHASP36(TM), OpenHASP(TM), HASPCard(TM) of Aladdin Knowledge Systems Ltd. * * (c)1998 by MeteO, Fixit * e-mail us: meteo@null.net * admin@fixit.spb.ru *************************************************************************/ #include <STDIO.h> long pwd; char al_buf[8]; static unsigned char ch[10]; unsigned int tab[64]; unsigned int seed,j,k; HASP_rows[8][8]={ {0,0,0,0,0,0,0,0}, {0,1,0,1,0,1,0,1}, {1,0,1,0,1,0,1,0}, {0,0,1,1,0,0,1,1}, {1,1,0,0,1,1,0,0}, {0,0,0,0,1,1,1,1}, {1,1,1,1,0,0,0,0}, {1,1,1,1,1,1,1,1} }; /*************************************** The table is represented as triads ***************************************/ void xor_pwd(void) { int i; pwd^=0x09071966; /* Guess, whose birthday.. ;) */ for(i=0;i<8;i++) { al_buf[i]= pwd & 7; pwd = pwd >> 3; } }; /*************************************** Main function (HASP_seed) Original code by bajunny ****************************************/ void emulate_func2( unsigned short seed) { int i, j; for(i=0;i<8;i++) { ch[i] = 0; for(j=0;j<8;j++) { seed *= 0x1989; seed += 5; ch[i] |= (tab[(seed>>9)&0x3f]) <7-j); } } } void main(void) { int i; printf("\nInput 1st HASP password:"); scanf("%4X",(int*) &j); printf("Input 2nd HASP password:"); scanf("%4X",(int*) &k); pwd=(long) k*0x10000+j; printf("\nInput HASP seedcode:"); scanf("%x", (int*) &seed); xor_pwd(); /************************************ Compute universal secret table *************************************/ for(i=0;i<8;i++){ for(j=0;j<8;j++){tab[i+j*8]=HASP_rows[al_buf[i]][j];} } for(i=0;i<8;i++){ for(j=0;j<8;j++){printf("%1.1d",tab[i*8+j]);} printf("\n"); } emulate_func2(seed); for(i=0;i<4;i++) {printf("%2.2X%2.2X ", ch[i*2+1],ch[i*2]);} } // ------------- end of transmission -----------------

Ob Duh
I *strongly* believe the contents of this "Ob Duh" section should be obvious to you after all that reading, so just close the eyes and let it visualize in your head..

You are deep inside fravia's page of reverse engineering, choose your way out:



advanced
Back to Advanced

redBack to project 3
redhomepage redlinks redsearch_forms red+ORC redstudents' essays redacademy database
redreality cracking redhow to search redjavascript wars
redtools redanonymity academy redcocktails redantismut CGI-scripts redmail_fravia+
redIs reverse engineering legal?