home *** CD-ROM | disk | FTP | other *** search
-
-
- ;-----------------------------------------------------------------------------
- ; 100% keygenerator for CDR-Win 3.1e/DAO 16/32 3.1e
- ; coded 06/26/97
- ; full credits go to the guy who localised the hidden check.
- ; do_what_you_want_with_it_source
- ; compile : tasm dao31e-k
- ; tlink /t /3 dao31e-k
- ;-----------------------------------------------------------------------------
-
- ; some notes on the registration check by the guy mentioned above ;)
- ;
- ; the registration algorithm works this way:
- ; 1.1 compute 32 bit hash value from user name (must be at least 6 chars)
- ; 1.2 swap upper and lower 16 bits of this hash value
- ; 1.3 compute 32 bit hash value from company name (must be at least 6 chars)
- ; 1.4 XOR 32 bit numbers computed in step.1.2 and step.1.3 with each other
- ; 1.5 convert registration number (which is an ascii string) to a 32 bit number
- ; by calling atol() (this is a C library function)
- ; 1.6 compare 24 bits of the two numbers we got in step.1.4 and step.1.5
- ; 1.7 if they match (in those 24 bit positions) then accept registration
- ;
- ; wow, now we know how to compute the registration number!
- ;
- ; well, at least this is what all crackers thought when they were tracing
- ; through the registration code. it seems that nobody had a second thought
- ; about the fact that only 24 bits were checked/compared, 8 bits were simply
- ; ignored, thus making key generators where those 8 bits were chosen randomly
- ; (usually taken from the number computed in step.1.4)
- ;
- ; however, later people noticed that certain types of CDs were fucked up
- ; 'cos apparently some random data was written into some sectors (which
- ; made the CD unusable). rumour went around stating that there was a second
- ; or hidden check in the program.
- ;
- ; well, as you probably found out by now this hidden check does exist indeed!
- ; to find it i used IDA, probably one of the best disassemblers ever made.
- ; (i didn't use WINICE at all)
- ;
- ; this is how i approached the problem: first, i had to find out what those
- ; 24 bits were that were checked during registration. this was easy, however
- ; i'd like to point out that the checking algorithm is extremly lame (well,
- ; maybe it was intentional to confuse the crackers) 'cos instead of using
- ; a bitmask to mask out the uninteresting 8 bits and then doing a simple cmp,
- ; the author wrote a for loop in which he compared 24 of 32 bits, one by one.
- ;
- ; the bits to be compared were determined by a table of 32 entries, where each
- ; entry (a 0 or 1) corresponded to a bit position, namely a 1 caused a bit
- ; position to be compared (i.e. there are 24 1s and 8 0s in that table).
- ; btw, the effective bitmask in the comparison is 0xFB39DEBF.
- ;
- ; after learning this, i assumed that in the hidden check only the remaining
- ; 8 bits were checked, either by using the table of 1s and 0s mentioned above
- ; (which was not the case, as IDA didn't find any more references to it) or
- ; by using the more effective masking method (which turned out to be the case).
- ;
- ; now, the masking method basically could have been implemented in two ways:
- ; either using 0xFB39DEBF or its binary complement 0x04C62140. a quick search
- ; revealed that the first value was used, as it was stored in the data area
- ; of the program (you can find it in the executable if you search for it).
- ; now, all i had to do was to find the code that referenced this value (which
- ; IDA did for me automatically) and see how it was used.
- ;
- ; so, the hidden check works this way:
- ;
- ; 2.1 read 0xFB39DEBF from the data area and then NOT it
- ; 2.2 AND the registration number and the mask computed in step.2.1
- ; 2.3 substract 0x822040 from the number computed in step.2.2
- ; 2.4 if the result is not zero, then set a variable to 0x930 in the data area
- ; 2.5 later, during burning, check whether that variable mentioned in the
- ; previous step is equal to 0x930 or not. if it is then write some random
- ; data into the current sector being written
- ;
- ; so, all we have to make sure is that the substraction done in step.2.3 will
- ; result in 0 (in this case that memory variable will contain a 0 by default).
- ; i guess, from this point on it is very trivial what those 8 bits have to be
- ; set to. if not then have a look at the code below ;).
- ;-----------------------------------------------------------------------------
-
- .model tiny
- .code
- .386
- org 100h
- main:
-
- push cs
- pop ds
- mov dx,offset(presentation)
- mov ah,09h
- int 21h
-
- mov ah,0ah
- mov dx,offset(keyb_buffer)
- int 21h
-
- cmp byte ptr [string_length],06h
- jb not_enough_char_4_name
-
- mov esi,offset(DAO_REG_TABLE)
- call magic_num_calc
- push eax
-
- mov esi,offset(CDRWIN_REG_TABLE)
- call magic_num_calc
-
- rol eax,10h
- mov dword ptr [offset(magic1)],eax
-
- mov dx,offset(ask_company)
- mov ah,09h
- int 21h
-
- mov ah,0ah
- mov dx,offset(keyb_buffer)
- int 21h
-
- cmp byte ptr [string_length],06h
- jb not_enough_char_4_company
-
- mov esi,offset(DAO_REG_TABLE)
- call magic_num_calc
- push eax
-
- mov esi,offset(CDRWIN_REG_TABLE)
- call magic_num_calc
- xor eax,dword ptr [offset(magic1)]
-
- ;------------Fixing Calculated key in order to make it real-----------
- and eax,0FB39DEBFh
- or eax,00822040h
- ;---------------------------------------------------------------------
-
- mov bx,offset(CDRWIN31eRegCode)+9
- call hex2dec
-
- mov ah,09h
- mov dx,offset(HereisCDRWIN31e)
- int 21h
-
- pop ebx
- pop eax
- rol eax,10h
- xor eax,ebx
- ;------------Fixing Calculated key in order to make it real-----------
- and eax,0FB39DEBFh
- or eax,00822040h
- ;---------------------------------------------------------------------
-
- mov bx,offset(DAO31eRegCode)+9
- call hex2dec
-
- mov ah,09h
- mov dx,offset(HereisDAO31e)
- int 21h
-
- prog_ends_ok:
- mov ax,4C00h
- int 21h
-
- hex2dec proc near
- mov ecx,000ah
- xor edx,edx
- div ecx
- add dl,30h
- mov [BX],dl
- dec bx
- or eax,eax
- jnz hex2dec
-
- ret
- endp
-
- not_enough_char_4_name:
- mov dx,offset(toofew4name)
- jmp print_error
- not_enough_char_4_company:
- mov dx,offset(toofew4cie)
- print_error:
- mov ah,09h
- int 21h
- mov ax,4Cffh
- int 21h
-
- MAGIC_NUM_CALC PROC NEAR
- xor eax,eax
- mov ebx,offset(string)
-
- push word ptr string_length
- keep_calc:
- xor edx,edx
- mov DL,[EBX]
- INC EBX
- mov ECX,EDX
- shr edx,02h
- xor ecx,eax
- shr eax,04h
- and ecx,0000000fh
- mov ecx,[ecx*4+esi]
- xor ecx,eax
- lea eax,[ecx*4+0]
- shr ecx,04h
- xor eax,edx
- and eax,3ch
- mov eax,[esi+eax]
- xor eax,ecx
- DEC byte ptr [offset(string_length)]
- jnz keep_calc
- pop word ptr string_length
- ret
- endp
-
- CDRWIN_REG_TABLE:
- DB 000h,000h,000h,000h,07Eh,088h,03Eh,01Ch,0FCh,010h,07Dh,038h,082h,098h,043h,024h
- DB 0F8h,021h,0FAh,070h,086h,0A9h,0C4h,06Ch,004h,031h,087h,048h,07Ah,0B9h,0B9h,054h
- DB 0F0h,043h,0F4h,0E1h,08Eh,0CBh,0CAh,0FDh,00Ch,053h,089h,0D9h,072h,0DBh,0B7h,0C5h
- DB 008h,062h,00Eh,091h,076h,0EAh,030h,08Dh,0F4h,072h,073h,0A9h,08Ah,0FAh,04Dh,0B5h
-
- DAO_REG_TABLE:
- DB 000h,000h,000h,000h,0C0h,0ADh,055h,019h,080h,05Bh,0ABh,032h,040h,0F6h,0FEh,02Bh
- DB 000h,0B7h,056h,065h,0C0h,01Ah,003h,07Ch,080h,0ECh,0FDh,057h,040h,041h,0A8h,04Eh
- DB 000h,06Eh,0ADh,0CAh,0C0h,0C3h,0F8h,0D3h,080h,035h,006h,0F8h,040h,098h,053h,0E1h
- DB 000h,0D9h,0FBh,0AFh,0C0h,074h,0AEh,0B6h,080h,082h,050h,09Dh,040h,02Fh,005h,084h
-
- magic1: DB 00h,00h,00h,00h
-
- presentation:
- DB 0ah,0dh
- DB ' 100% Key-Generator for DAO 3.1e/CDR-Win 3.1e, hidden check supported 26-06-97',0ah,0dh
- DB ' ---[Brought to you by #cracking]---------------------------------------------',0ah,0dh,0ah,0dh
- DB ' Produces original keys, you won''t fuck CDs with it! CDRWIN/DAO both tested.',0ah,0dh
- DB ' Thanks to Midi-Man for testing with his rewritable.',0ah,0dh,0ah,0dh
-
- ask_name:
- DB 'Enter your name (min 6 char): $'
-
- ask_company:
- DB 0ah,0dh
- DB 'Enter your company (min 6 char): $'
-
- toofew4name:
- DB 0dh,0ah,0dh,0ah
- DB 'At least 6 characters for name needed$'
-
- toofew4cie:
- DB 0dh,0ah,0dh,0ah
- DB 'At least 6 characters for company needed$'
-
- HereisCDRWIN31e:
- DB 0dh,0ah,0dh,0ah
- DB 'CDRWIN 3.1e : '
-
- CDRWIN31eRegCode:
- db ' $'
-
- HereisDAO31e:
- DB 0dh,0ah
- DB 'DAO 3.1e : '
-
- DAO31eRegCode:
- db ' $'
-
- keyb_buffer:
- DB 80h
- string_length:
- DB 00h
- string:
- end main
-