📄 dao31e.asm
字号:
;-----------------------------------------------------------------------------
; 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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -