Hard Disk Sleeper v1.55

Tutorial by Lucifer48 [Immortal Descendants]
(23 july 1999)



Target Program: Hard Disk Sleeper v1.55
Location: http://www.mwso.com/
Protection: Name/Serial
Level: Beginner (3/10)



Getting a good serial isn't extremly difficult (the program is written in C (borland), the code is clear), but it requires some calculations. As usual, we fill the Name & Serial boxes... When we click on the OK button, there are only a comparison:
XXXX:00413A24  MOV  EAX,[004205D0]          ;checksum computed with the name and the serial
XXXX:00413A29  CMP  EAX,[004205C0]          ;comparison with the right value (19Eh)
XXXX:00413A2F  JZ   00413A6C                ;no jump = bad cracker!
The calculation of the dword in [004205D0] is done after each key pressed.
XXXX:004139DC  CALL USER32!GetWindowTextA
XXXX:004139E1  CMP  EAX,08                  ;the serial must have 8 chars
...
XXXX:00413A08  CALL 00413C94                ;make 8 bytes
...
XXXX:00413A10  LEA  EAX,[EBP-0C]            ;our 8 precious bytes (C1, C2, ..., C8)
XXXX:00413A13  PUSH EAX
XXXX:00413A14  CALL 00413D13                ;calculation of the checksum (result eax)
XXXX:00413A19  POP  ECX                     ;add esp,4
XXXX:00413A1A  MOV  [004205D0],EAX          ;save to compare later
These 8 bytes (C1, C2, ..., C8) are computed with the name and the serial. This is (in a virtual language, somewhere between C and Pascal) what the call 00413D13 does with these 8 bytes:
x={ C1, C2, C3, C4, C5, C6, C7, C8 }

checksum=0;
for i:=0 to 6 do
  checksum:=checksum + ( (x[i]+i) mod $A ) * ( (x[i+1]+i+1) mod $A );
At the end of the loop, we must have: checksum=0x19E. How doing this ? Brute force attack ?? Umm, not at all, 8 variables (from 0 to FF) it's too much. We will rather uses the two mod instructions, indeed we can't exceed 9*9 (and at least 0*0) for one loop. We will try to find in a first time 8 numbers between 0 to 9. I mean, we make a change of variable, D1= (C1 + 0) mod 0xA, etc.. so the formula with the checksum will become:
y={ D1, D2, D3, D4, D5, D6, D7, D8 }

checksum=0;
for i:=0 to 6 do
  checksum:=checksum + y[i] * y[i+1];
and more simply:
checksum = D1*D2 + D2*D3 + D3*D4 + D4*D5 + D5*D6 + D6*D7 + D7*D8
At this moment, the "brute force attack" will be easy (8 variables from 0 to 9, only 10^8 possibilities...).

This my source in C:
/*********************************************************/
#include 

void main()
{
signed char x1, x2, x3, x4, x5, x6, x7, x8;
long a;

for(x1=0; x1<=9; x1++)
 for(x2=0; x2<=9; x2++)
  for(x3=0; x3<=9; x3++)
   for(x4=0; x4<=9; x4++)
    for(x5=0; x5<=9; x5++)
     for(x6=0; x6<=9; x6++)
      for(x7=0; x7<=9; x7++)
       for(x8=0; x8<=9; x8++)
       {
       a=0;
       a= x1*x2 + x2*x3 + x3*x4 + x4*x5 + x5*x6 + x6*x7 + x7*x8;
       if (a==0x19E)
         printf("%x %x %x %x %x %x %x %x\n",x1,x2,x3,x4,x5,x6,x7,x8);
       } /* end of for */
}
/*********************************************************/
We find lots of solutions (2919 exactly) in few seconds. This is the last one:
a b c d e f g h

9 9 9 9 9 4 6 5
9 9 9 9 9 4 9 2
9 9 9 9 9 5 5 4
9 9 9 9 9 5 9 0
9 9 9 9 9 6 3 6
9 9 9 9 9 6 4 3
9 9 9 9 9 6 6 0
9 9 9 9 9 7 3 2
9 9 9 9 9 8 2 1
9 9 9 9 9 9 1 0
If i take the last combination as example, it means (with the source of the program):
Loop1:		(C1 + 0 + 0) mod 10 = 9  et  (C2 + 0 + 1) mod 10 = 9
Loop2:		(C2 + 1 + 0) mod 10 = 9  et  (C3 + 1 + 1) mod 10 = 9
Loop3:		(C3 + 2 + 0) mod 10 = 9  et  (C4 + 2 + 1) mod 10 = 9
Loop4:	        (C4 + 3 + 0) mod 10 = 9  et  (C5 + 3 + 1) mod 10 = 9
Loop5:	        (C5 + 4 + 0) mod 10 = 9  et  (C6 + 4 + 1) mod 10 = 9
Loop6:	        (C6 + 5 + 0) mod 10 = 9  et  (C7 + 5 + 1) mod 10 = 1
Loop7:	        (C7 + 6 + 0) mod 10 = 1  et  (C8 + 6 + 1) mod 10 = 0
We remove expressions which are twice times present:
(C1 + 0) mod 10 = 9 (= a)
(C2 + 1) mod 10 = 9 (= b)
(C3 + 2) mod 10 = 9 (= c)
(C4 + 3) mod 10 = 9 (= d)
(C5 + 4) mod 10 = 9 (= e)
(C6 + 5) mod 10 = 9 (= f)
(C7 + 6) mod 10 = 1 (= g)
(C8 + 7) mod 10 = 0 (= h)
So, it is easy to generate our 8 precious bytes (C1, C2, ..., C8). It is over for the call 00413D13.

Remark: Don't forget that these 8 bytes are computed with the name and the serial.

Ok, we know how getting 8 good bytes (C1...C8), now, let's study how the serial and the serial are encoded to produce the 8 bytes. It is located in CALL 00413C94 (in XXXX:00413A08). S1, S2, ..., S8 are the 8 bytes of the final (working) serial.

My name (Lucifer48) is coded like this (84 = 4C + 38) on 8 bytes:
XXXX:0068F464  84 75 63 69 66 65 72 34                          .ucifer4
               N1 N2 N3 N4 N5 N6 N7 N8
This is the encryption scheme:
C1 =S1 - [ (N1 mod 1Ah) + 41h ]
C2 =S2 - [ (N2 mod 1Ah) + 41h ]
...
C8 =S8 - [ (N8 mod 1Ah) + 41h ]
If Ck (k={1,2,...8} ) is negative (between 7F and FF), then Ck += 1Ah.
Each char of the serial is independent. So we could solve separately 8 equations. Which are:
S1 = C1 + [ (N1 mod 1Ah) + 41h ]
S2 = C2 + [ (N2 mod 1Ah) + 41h ]
...
S8 = C8 + [ (N3 mod 1Ah) + 41h ]
It is true, assuming Sk > [ (Nk mod 1Ah) + 41h ]
(to remove the carry problem (+1A) ).

For my name:
S1 = C1 + 43
S2 = C2 + 4E
S3 = C3 + 56
S4 = C4 + 42
S5 = C5 + 59
S6 = C6 + 58
S7 = C7 + 4B
S8 = C8 + 41
To find C1, C2, ..., C8 i do:
C1 = 3*Ah + 9 - 0 = 27
C2 = 3*Ah + 9 - 1 = 26
...
C7 = 3*Ah + 1 - 6 = 19
C8 = 3*Ah + 0 - 7 = 17
I take this 3 because it is an ideal number which allow us to obtain printable chars for the serial (not too high ascii value). I get this:

6A ; 74 ; 7B ; 66 ; 7C ; 7A ; 64 ; 58 (so: "jt{f|zdX")

The serial works, but there are two bad chars: {, | ;) In fact the 3 is not so good... I will take 2, i think it will be better ! (same process as above):
C1 = 2*Ah + 9 - 0 = 1D
C2 = 2*Ah + 9 - 1 = 1C
...
C7 = 2*Ah + 1 - 6 = 0F
C8 = 2*Ah + 0 - 7 = 0D
I get:
60 ; 6A ; 71 ; 5C ; 72 ; 70 ; 5A ; 4E (so: "`jq\rpZN")

The second serial also works ! But the 2 is not very good too !
Finaly, i decide to mix the two serials to get my registration:
Name/ Lucifer48
Serial/ jjqfrzdX

Greetings: All ID members (Volatility, Torn@do, ...), Eternal Bliss, ACiD BuRN, people on #cracking4newbies, french crackers, etc.



(c) Lucifer48. All rights reversed