Hi all,
after many hours of study I'm beginning to understand something about the protection (but the solution is so far).
First of all an user has sent to me a screen with the program fully executed and then I believe that the dongle is simply bypassable but I'm a newbie so I have to understand how
I begin to explain (I hope clearly) what the application does.
From the hardlock api guide and some C examples, the code begin with:
Code:
result = HL_LOGIN (29809,DONT_CARE,"HARDLOCK","@0=/&#s3"

;
IF (result == STATUS_OK)
IF (HL_AVAIL() == STATUS_OK)
eeprom = SPACE(128);
HL_READBL (eeprom);
ENDIF;
result = HL_LOGOUT();
ENDIF;
The API Status Values returned are:
STATUS_OK --> 0, NOT_INIT --> 1, ecc.
So after the HL_LOGIN and HL_AVAIL functions the returned value should be 0 and after it will be possible to execute the HL_READBL function.
(N.B. I have installed the Hardl*ck driver (file hl*rv32.zip downloaded from the official ftp).
In olly I will have:
Code:
00402ED7 CALL 00554A02 ; HL_LOGIN
00402EDC MOVZX EDI,AX ; EAX returned to me is 0x13 (19 dec) that isn't an API STATUS documented in the pdf
So I forced the EAX value to 0 (STATUS_OK)
And I stepped over until:
Code:
00402EDC MOVZX EDI,AX
00402EDF ADD ESP,10
00402EE2 CMP DI,BX
00402EE5 JE SHORT 00402EF6; IF EAX=0 jump the HL_LOGOUT
00402EE7 HL_LOGOUT
With EAX=0 the LOGOUT and Error msgbox (00402F38) will be bypassed.
After, there is the HL_AVAIL() function that I believe is here:
Code:
00402F4E CALL 00525590; HL_AVAIL()
Stepped over this call the status is 0 (EAX=0 STATUS_OK), so I stepped until the HL_READBL function (to "read" the dongle context):
Code:
00402F63 CALL 00426440 ; Call to HL_READBL
Inside the call:
Code:
00426440 MOV EAX,DWORD PTR SS:[ESP+4]
00426444 PUSH EAX
00426445 CALL 00554CE9; HL_READBL
In this piece of code the pointer is loaded and passed to the HL_READBL function.
If some breakpointers are set inside this function, error messages will be returned because there are calls to GetTickCount() function.
The only interesting part in this function is the pointer value to the memory structure (in my case is 00699D90 and inside the structure there is the ASCII DA*AKUST value).
Stepping with F8 I arrive at the HL_CODE function (that crypt/decrypt a block).
From the manual, the prototype is:
HL_CODE(DATAPTR, BCNT)
DATAPTR-->pointer
BCNT-->number of blocks to crypt/decrypt
Then:
Code:
result = HL_LOGIN (29809,DONT_CARE,"HARDLOCK","@0=/&#s3"

;
IF (result == STATUS_OK)
text = "Hello Hardlock !";
IF (HL_CODE(text, 2) == STATUS_OK))
PRINT "The encrypted data is: " + text;
ENDIF;
result = HL_LOGOUT();
ENDIF;
In olly:
Code:
00402F7D CALL 00426460; Call to HL_CODE
00402F82 ADD ESP,8
Entrando nella CALL:
Code:
00426460 PUSH EBP
00426461 MOV EBP,DWORD PTR SS:[ESP+8]
00426465 PUSH ESI
00426466 PUSH EDI
00426467 XOR EDI,EDI
00426469 LEA ESP,[LOCAL.2]
00426470 LEA EAX,[EBP+EDI]; Here begin the loop to read the structure
00426473 PUSH 1 ; Arg2 = 1
00426475 PUSH EAX ; Arg1 --> In my case is 0012FDB0 and the memory area is large 128 byte
00426476 CALL 00554994; HL_CODE
0042647B ADD ESP,8
0042647E MOV SI,AX
00426481 NEG SI
00426484 SBB ESI,ESI
00426486 ADD EDI,8
00426489 ADD ESI,1
0042648C CMP EDI,80
00426492 JB SHORT 00426470; Read loop
Step with F7 the HL_CODE call
Code:
00554994 PUSH EBP
00554995 MOV EBP,ESP
00554997 PUSH EBX
00554998 PUSH ESI
00554999 PUSH EDI
0055499A CMP DWORD PTR DS:[699E90],0; Verify that there is the 00699D90 value, otherwise set it
005549A1 JNE 005549B1
005549A7 MOV DWORD PTR DS:[699E90],OFFSET 00699D90
005549B1 MOV EAX,DWORD PTR SS:[ARG.1]; Move in EAX the 0012FDB0 pointer
005549B4 MOV ECX,DWORD PTR DS:[699E90]; Move in ECX the 00699D90 pointer
005549BA MOV DWORD PTR DS:[ECX+12],EAX
005549BD MOV AX,WORD PTR SS:[ARG.2]; AX = 1 and then EAX will be 00120001
005549C1 MOV ECX,DWORD PTR DS:[699E90]; ECX = 00699D90 (Not changed)
005549C7 MOV WORD PTR DS:[ECX+16],AX; ECX+16 = 1
005549CB MOV EAX,DWORD PTR DS:[699E90]; EAX = 00699D90
005549D0 MOV WORD PTR DS:[EAX+18],0B; EAX+18 = 0B
005549D6 MOV EAX,DWORD PTR DS:[699E90]; EAX = 00699D90 (Not changed)
In these instructions I believe that there is the call to the crypt/decrypt of a block function:
Code:
005549DB PUSH EAX; Arg1 = cna*2.699D90
005549DC CALL 00554520; Crypt/Decrypt
005549E1 ADD ESP,4
005549E4 MOV EAX,DWORD PTR DS:[699E90]; EAX = 00699D90
005549E9 MOV WORD PTR DS:[EAX+16],0
005549EF MOV EAX,DWORD PTR DS:[699E90]; EAX = 00699D90
005549F4 MOV AX,WORD PTR DS:[EAX+1A]; AX = 1 so EAX = 00690001
005549F8 JMP 005549FD; Jump to the next instruction
005549FD POP EDI
005549FE POP ESI
005549FF POP EBX
00554A00 LEAVE
00554A01 RETN; Read the next block
Inside the CALL
Code:
00554520 PUSH EBP; Crypt/Decrypt?!?!
00554521 MOV EBP,ESP; EBP = 0012FD04
00554523 SUB ESP,4; ESP = 0012FD00 --> ASCII 2EU
00554526 PUSH EBX; ESP = 0012FCFC --> 0
00554527 PUSH ESI; ESP = 0012FCF8 ---> 00701660
00554528 PUSH EDI; ESP = 0012FCF4 ---> 0
00554529 MOV EAX,DWORD PTR SS:[ARG.1]; EAX=00699D90 (Not changed)
0055452C PUSH EAX; ESP = 0012FCF0 ---> 00699D90
0055452D CALL 005586F5; I believe that in this call is verified if the crypt/decrypt procedure is well executed
00554532 ADD ESP,4;
00554535 MOV WORD PTR SS:[LOCAL.1],AX; Move 1 in 0012FD00
00554539 MOV AX,WORD PTR SS:[LOCAL.1]; Not changed
0055453D JMP 00554542; Jump to the next instruction
00554542 POP EDI; 0012FCF4=0
00554543 POP ESI; 0012FCF8=00701660
00554544 POP EBX; 0012FCF8=0
00554545 LEAVE; Release the stack
00554546 RETN
Inside the CALL 0055452D:
Code:
005586F5 PUSH EBP; ESP = 0012FCE8 --> 0012FD04
005586F6 MOV EBP,ESP
005586F8 PUSH EBX; ESP = 0012FCE4 --> 0
005586F9 MOV EBX,DWORD PTR SS:[ARG.1]; EBX = 00699D90
005586FC CALL 00558020; Interesting call, here are executed 3 CMPs
00558701 POP EBX; EBX = 0
00558702 POP EBP; EBP = 0012FD04
00558703 RETN
Inside the CALL 00558020 there are 3 interesting CMPs:
Code:
00558020 CMP WORD PTR DS:[EBX+6],0; DS:[EBX+6] = 2
00558025 JNE SHORT 0055803E; Not jump
00558027 CMP WORD PTR DS:[EBX+18],0B; DS:[EBX+18] = 0B
0055802C JNE SHORT 0055803E; Not jump
0055802E CMP WORD PTR DS:[EBX+16],0; DS:[EBX+16] = 1
00558033 JNE SHORT 00558040; Jump! Here, IMHO, set AX=1 when the Crypt/Dectrypt function fails
00558035 MOV AX,0
00558039 MOV WORD PTR DS:[EBX+1A],AX; [EBX+1A] = 1
0055803D RETN
0055803E JMP SHORT 00558086
00558040 CMP BYTE PTR DS:[EBX+0FE],0; [EBX+0FE] = 0
00558047 JNE SHORT 0055804F; Non salta
00558049 MOV AX,1; Imposta AX =1
0055804D JMP SHORT 00558039
At the return from the main HL_CODE function (00402F82) EAX is 0.
After this analysis I'm not able to understand when the program read the features and, in particular, what are these features!
Go ahead with the code, the HL_CODE is called for the 2nd time:
Code:
00403087 CALL 00426E40; Call to HL_CODE
0040308C CMP WORD PTR DS:[6A5E40],2; EAX = 00618F98
Step and I reach the call that run the program:
Code:
004030EF CALL 00404C20
Some info are loaded from an .ini file until this instruction:
Code:
00404E8B CALL EBP; \USER32.CreateWindowExA
And this messagebox appears:
Cannot find Ha*dlock(0).
Please check correct installation.
What I have to do?
Some advice?
I'm begin crazy because "I don't see the light" for a solution
Help guys
Thank you very much :wink:
Bye all