home *** CD-ROM | disk | FTP | other *** search
/ Reverse Code Engineering RCE CD +sandman 2000 / ReverseCodeEngineeringRceCdsandman2000.iso / RCE / Quantico / km / dao31e.asm.txt < prev    next >
Encoding:
Text File  |  2000-05-25  |  9.2 KB  |  269 lines

  1.  
  2.  
  3. ;-----------------------------------------------------------------------------
  4. ; 100% keygenerator for CDR-Win 3.1e/DAO 16/32 3.1e
  5. ; coded 06/26/97
  6. ; full credits go to the guy who localised the hidden check.
  7. ; do_what_you_want_with_it_source
  8. ; compile : tasm dao31e-k
  9. ;           tlink /t /3 dao31e-k
  10. ;-----------------------------------------------------------------------------
  11.  
  12. ; some notes on the registration check by the guy mentioned above ;)
  13. ;
  14. ; the registration algorithm works this way:
  15. ; 1.1 compute 32 bit hash value from user name (must be at least 6 chars)
  16. ; 1.2 swap upper and lower 16 bits of this hash value
  17. ; 1.3 compute 32 bit hash value from company name (must be at least 6 chars)
  18. ; 1.4 XOR 32 bit numbers computed in step.1.2 and step.1.3 with each other
  19. ; 1.5 convert registration number (which is an ascii string) to a 32 bit number
  20. ;     by calling atol() (this is a C library function)
  21. ; 1.6 compare 24 bits of the two numbers we got in step.1.4 and step.1.5
  22. ; 1.7 if they match (in those 24 bit positions) then accept registration
  23. ;
  24. ; wow, now we know how to compute the registration number!
  25. ;
  26. ; well, at least this is what all crackers thought when they were tracing
  27. ; through the registration code. it seems that nobody had a second thought
  28. ; about the fact that only 24 bits were checked/compared, 8 bits were simply
  29. ; ignored, thus making key generators where those 8 bits were chosen randomly
  30. ; (usually taken from the number computed in step.1.4)
  31. ;
  32. ; however, later people noticed that certain types of CDs were fucked up
  33. ; 'cos apparently some random data was written into some sectors (which
  34. ; made the CD unusable). rumour went around stating that there was a second
  35. ; or hidden check in the program.
  36. ;
  37. ; well, as you probably found out by now this hidden check does exist indeed!
  38. ; to find it i used IDA, probably one of the best disassemblers ever made.
  39. ; (i didn't use WINICE at all)
  40. ;
  41. ; this is how i approached the problem: first, i had to find out what those
  42. ; 24 bits were that were checked during registration. this was easy, however
  43. ; i'd like to point out that the checking algorithm is extremly lame (well,
  44. ; maybe it was intentional to confuse the crackers) 'cos instead of using
  45. ; a bitmask to mask out the uninteresting 8 bits and then doing a simple cmp,
  46. ; the author wrote a for loop in which he compared 24 of 32 bits, one by one.
  47. ;
  48. ; the bits to be compared were determined by a table of 32 entries, where each 
  49. ; entry (a 0 or 1) corresponded to a bit position, namely a 1 caused a bit 
  50. ; position to be compared (i.e. there are 24 1s and 8 0s in that table).
  51. ; btw, the effective bitmask in the comparison is 0xFB39DEBF.
  52. ;
  53. ; after learning this, i assumed that in the hidden check only the remaining
  54. ; 8 bits were checked, either by using the table of 1s and 0s mentioned above
  55. ; (which was not the case, as IDA didn't find any more references to it) or
  56. ; by using the more effective masking method (which turned out to be the case).
  57. ;
  58. ; now, the masking method basically could have been implemented in two ways:
  59. ; either using 0xFB39DEBF or its binary complement 0x04C62140. a quick search
  60. ; revealed that the first value was used, as it was stored in the data area
  61. ; of the program (you can find it in the executable if you search for it).
  62. ; now, all i had to do was to find the code that referenced this value (which
  63. ; IDA did for me automatically) and see how it was used.
  64. ;
  65. ; so, the hidden check works this way:
  66. ;
  67. ; 2.1 read 0xFB39DEBF from the data area and then NOT it
  68. ; 2.2 AND the registration number and the mask computed in step.2.1
  69. ; 2.3 substract 0x822040 from the number computed in step.2.2
  70. ; 2.4 if the result is not zero, then set a variable to 0x930 in the data area
  71. ; 2.5 later, during burning, check whether that variable mentioned in the
  72. ;     previous step is equal to 0x930 or not. if it is then write some random
  73. ;     data into the current sector being written
  74. ;
  75. ; so, all we have to make sure is that the substraction done in step.2.3 will
  76. ; result in 0 (in this case that memory variable will contain a 0 by default).
  77. ; i guess, from this point on it is very trivial what those 8 bits have to be
  78. ; set to. if not then have a look at the code below ;).
  79. ;-----------------------------------------------------------------------------
  80.  
  81. .model tiny
  82. .code
  83. .386
  84. org 100h
  85. main:
  86.  
  87.         push cs
  88.         pop ds
  89.         mov dx,offset(presentation)
  90.         mov ah,09h
  91.         int 21h
  92.  
  93.         mov ah,0ah
  94.         mov dx,offset(keyb_buffer)
  95.         int 21h
  96.  
  97.         cmp byte ptr [string_length],06h
  98.         jb not_enough_char_4_name
  99.  
  100.         mov esi,offset(DAO_REG_TABLE)
  101.         call magic_num_calc
  102.         push eax
  103.  
  104.         mov esi,offset(CDRWIN_REG_TABLE)
  105.         call magic_num_calc
  106.  
  107.         rol eax,10h
  108.         mov dword ptr [offset(magic1)],eax
  109.  
  110.         mov dx,offset(ask_company)
  111.         mov ah,09h
  112.         int 21h
  113.  
  114.         mov ah,0ah
  115.         mov dx,offset(keyb_buffer)
  116.         int 21h
  117.  
  118.         cmp byte ptr [string_length],06h
  119.         jb not_enough_char_4_company
  120.  
  121.         mov esi,offset(DAO_REG_TABLE)
  122.         call magic_num_calc
  123.         push eax
  124.  
  125.         mov esi,offset(CDRWIN_REG_TABLE)
  126.         call magic_num_calc
  127.         xor eax,dword ptr [offset(magic1)]
  128.  
  129. ;------------Fixing Calculated key in order to make it real-----------
  130.         and eax,0FB39DEBFh
  131.         or  eax,00822040h
  132. ;---------------------------------------------------------------------
  133.  
  134.         mov bx,offset(CDRWIN31eRegCode)+9
  135.         call hex2dec
  136.  
  137.         mov ah,09h
  138.         mov dx,offset(HereisCDRWIN31e)
  139.         int 21h
  140.  
  141.         pop ebx
  142.         pop eax
  143.         rol eax,10h
  144.         xor eax,ebx
  145. ;------------Fixing Calculated key in order to make it real-----------
  146.         and eax,0FB39DEBFh
  147.         or  eax,00822040h
  148. ;---------------------------------------------------------------------
  149.  
  150.         mov bx,offset(DAO31eRegCode)+9
  151.         call hex2dec
  152.  
  153.         mov ah,09h
  154.         mov dx,offset(HereisDAO31e)
  155.         int 21h
  156.  
  157. prog_ends_ok:
  158.         mov ax,4C00h
  159.         int 21h
  160.  
  161. hex2dec proc near
  162.         mov ecx,000ah
  163.         xor edx,edx
  164.         div ecx
  165.         add dl,30h
  166.         mov [BX],dl
  167.         dec bx
  168.         or eax,eax
  169.         jnz hex2dec
  170.  
  171.         ret
  172.         endp
  173.  
  174. not_enough_char_4_name:
  175.         mov dx,offset(toofew4name)
  176.         jmp print_error
  177. not_enough_char_4_company:
  178.         mov dx,offset(toofew4cie)
  179. print_error:
  180.         mov ah,09h
  181.         int 21h
  182.         mov ax,4Cffh
  183.         int 21h
  184.  
  185. MAGIC_NUM_CALC PROC NEAR
  186.         xor eax,eax
  187.         mov ebx,offset(string)
  188.  
  189.         push word ptr string_length
  190. keep_calc:
  191.         xor edx,edx
  192.         mov DL,[EBX]
  193.         INC EBX
  194.         mov ECX,EDX
  195.         shr edx,02h
  196.         xor ecx,eax
  197.         shr eax,04h
  198.         and ecx,0000000fh
  199.         mov ecx,[ecx*4+esi]
  200.         xor ecx,eax
  201.         lea eax,[ecx*4+0]
  202.         shr ecx,04h
  203.         xor eax,edx
  204.         and eax,3ch
  205.         mov eax,[esi+eax]
  206.         xor eax,ecx
  207.         DEC byte ptr [offset(string_length)]
  208.         jnz keep_calc
  209.         pop word ptr string_length
  210.         ret
  211.         endp
  212.  
  213. CDRWIN_REG_TABLE:
  214.         DB 000h,000h,000h,000h,07Eh,088h,03Eh,01Ch,0FCh,010h,07Dh,038h,082h,098h,043h,024h
  215.         DB 0F8h,021h,0FAh,070h,086h,0A9h,0C4h,06Ch,004h,031h,087h,048h,07Ah,0B9h,0B9h,054h
  216.         DB 0F0h,043h,0F4h,0E1h,08Eh,0CBh,0CAh,0FDh,00Ch,053h,089h,0D9h,072h,0DBh,0B7h,0C5h
  217.         DB 008h,062h,00Eh,091h,076h,0EAh,030h,08Dh,0F4h,072h,073h,0A9h,08Ah,0FAh,04Dh,0B5h
  218.  
  219. DAO_REG_TABLE:
  220.         DB 000h,000h,000h,000h,0C0h,0ADh,055h,019h,080h,05Bh,0ABh,032h,040h,0F6h,0FEh,02Bh
  221.         DB 000h,0B7h,056h,065h,0C0h,01Ah,003h,07Ch,080h,0ECh,0FDh,057h,040h,041h,0A8h,04Eh
  222.         DB 000h,06Eh,0ADh,0CAh,0C0h,0C3h,0F8h,0D3h,080h,035h,006h,0F8h,040h,098h,053h,0E1h
  223.         DB 000h,0D9h,0FBh,0AFh,0C0h,074h,0AEh,0B6h,080h,082h,050h,09Dh,040h,02Fh,005h,084h
  224.  
  225. magic1: DB 00h,00h,00h,00h
  226.  
  227. presentation:
  228.         DB 0ah,0dh
  229.         DB ' 100% Key-Generator for DAO 3.1e/CDR-Win 3.1e, hidden check supported 26-06-97',0ah,0dh
  230.         DB ' ---[Brought to you by #cracking]---------------------------------------------',0ah,0dh,0ah,0dh
  231.         DB ' Produces original keys, you won''t fuck CDs with it! CDRWIN/DAO both tested.',0ah,0dh
  232.         DB ' Thanks to Midi-Man for testing with his rewritable.',0ah,0dh,0ah,0dh
  233.  
  234. ask_name:
  235.         DB 'Enter your name (min 6 char): $'
  236.  
  237. ask_company:
  238.         DB 0ah,0dh
  239.         DB 'Enter your company (min 6 char): $'
  240.  
  241. toofew4name:
  242.         DB 0dh,0ah,0dh,0ah
  243.         DB 'At least 6 characters for name needed$'
  244.  
  245. toofew4cie:
  246.         DB 0dh,0ah,0dh,0ah
  247.         DB 'At least 6 characters for company needed$'
  248.  
  249. HereisCDRWIN31e:
  250.         DB 0dh,0ah,0dh,0ah
  251.         DB 'CDRWIN 3.1e : '
  252.  
  253. CDRWIN31eRegCode:
  254.         db '          $'
  255.  
  256. HereisDAO31e:
  257.         DB 0dh,0ah
  258.         DB 'DAO 3.1e    : '
  259.  
  260. DAO31eRegCode:
  261.         db '          $'
  262.  
  263. keyb_buffer:
  264.         DB 80h
  265. string_length:
  266.         DB 00h
  267. string:        
  268.         end     main
  269.