home *** CD-ROM | disk | FTP | other *** search
/ Reverse Code Engineering RCE CD +sandman 2000 / ReverseCodeEngineeringRceCdsandman2000.iso / RCE / +Sandman / kgtut2.txt < prev    next >
Text File  |  2000-05-25  |  23KB  |  492 lines

  1.                 Keygen Tutorial 2
  2.                    Yes123 '99
  3. ---[ WARNING ]--------------------------------------------------------------------------------
  4.  
  5. This Tutorial is for education purpose only. I wrote it to allow you to understand how are
  6. coded some protections schemes in software. I didn't make it to allow you to use the target
  7. program without paying the author. If you plan to use these programs regularly, please remeber
  8. to send your $ to the authors, don't be a outlaw, and over all, don't be a LAMER !!!
  9.  
  10. ---[ INTRO ]----------------------------------------------------------------------------------
  11.  
  12. target: SubmitWolf(DEMO) v4.01
  13. where : http://www.trellian.com/swolf
  14.  
  15. Tools : SoftIce for Win9x v3.24
  16.     W32Dasm v8.9
  17.         Programming Language (C, Pascal, asm, anyone you want, I'll use our old C)
  18.  
  19. This is my second tutorial in english. I hope my bad spelling won't make this text too much 
  20. hard to understand for you. :)
  21.  
  22. I'll try to teach you how to make a key generator for a program . Our target will be an 
  23. easy one, as the protection scheme is really easy to understand and follow.
  24. I'll assume you know the following:
  25.  
  26. - basic use of SoftIce
  27. - asm instructions (at least the ones used for cracking)
  28. - knowing which call is used to calculate serial number.
  29.  
  30. ---[ TUTORIAL ]-------------------------------------------------------------------------------
  31.  
  32. At first, launch SoftICe (assuming you know the basics, and how to setup this Numega's
  33. nice tool). Then launch our target, swolf32.exe! Go to the help menu and select the register.
  34.  
  35. Well, we'll try to find how this protection is running. Let's enter anything as a name
  36. and random digits as a serial. Don't click the OK button yet, but hit CTRL & D to bring up 
  37. SoftICe. We'll define a breakpoint, using the classical BPX hmemcpy(it works for most program. 
  38. Hit CTRL-D again to go back to the program. Click OK and... SoftICe pop up.
  39.  
  40. Keep pressing F12 until you get back to the traget program code. Trace a few lines down you will
  41. be in:
  42.  
  43. :004167D9 8D4C2410                lea ecx, dword ptr [esp+10]        ;ecx=our fake serial
  44. :004167DD 8D942490000000          lea edx, dword ptr [esp+00000090]    ;edx=our name
  45. :004167E4 51                      push ecx
  46. :004167E5 52                      push edx
  47. :004167E6 E8B5450100              call 0042ADA0                ;This is the call which
  48. :004167EB 83C410                  add esp, 00000010            ;calculate our serial
  49. :004167EE 85C0                    test eax, eax                ;and return eax=1 if true
  50. :004167F0 0F8596000000            jne 0041688C                ;jump to registered
  51. :004167F6 8D442408                lea eax, dword ptr [esp+08]
  52. :004167FA 8D8C2488000000          lea ecx, dword ptr [esp+00000088]
  53. :00416801 50                      push eax
  54. :00416802 51                      push ecx
  55. :00416803 E868470100              call 0042AF70                ;This is a call to test
  56. :00416808 83C408                  add esp, 00000008            ;wheteher our serial is
  57. :0041680B 85C0                    test eax, eax                ;for v3.XX one.
  58. :0041680D 7433                    je 00416842
  59.  
  60. The most important call is at 004167E6, there are a few calls before it, but nothing intersting
  61. inside. The following call at 416803 is to test whether our serial is for version 3.XX. It some
  62. how similar to v4.01, you can try to trace it if you want.
  63. So we trace in the call 0042ADA0.
  64.  
  65. * Referenced by a CALL at Addresses:
  66. |:004167E6   , :0042ABFC   
  67. |
  68. :0042ADA0 83EC30                  sub esp, 00000030
  69. :0042ADA3 55                      push ebp
  70. :0042ADA4 56                      push esi
  71. :0042ADA5 57                      push edi
  72. :0042ADA6 8B7C2444                mov edi, dword ptr [esp+44]        ;edi=our fake serial
  73. :0042ADAA 85FF                    test edi, edi    
  74. :0042ADAC 0F84A7010000            je 0042AF59                ;die if empty
  75. :0042ADB2 8B6C2440                mov ebp, dword ptr [esp+40]        ;ebp=our name
  76. :0042ADB6 85ED                    test ebp, ebp                
  77. :0042ADB8 0F849B010000            je 0042AF59                ;die if empty
  78. :0042ADBE 8A07                    mov al, byte ptr [edi]        ;compare first byte of
  79. :0042ADC0 3C50                    cmp al, 50                ;serial with 'P', die
  80. :0042ADC2 0F8587010000            jne 0042AF4F                ;if not equal
  81. :0042ADC8 807F0134                cmp byte ptr [edi+01], 34        ;compare second byte of
  82. :0042ADCC 750C                    jne 0042ADDA                ;serial with '4'
  83. :0042ADCE C70500C8430000000000    mov dword ptr [0043C800], 00000000
  84. :0042ADD8 EB1C                    jmp 0042ADF6
  85.  
  86. * Referenced by a (U)nconditional or (C)onditional Jump at Address:
  87. |:0042ADCC(C)
  88. |
  89. :0042ADDA 3C50                    cmp al, 50                ;compare first byte of
  90. :0042ADDC 0F856D010000            jne 0042AF4F                ;serial with 'P'
  91. :0042ADE2 807F0145                cmp byte ptr [edi+01], 45        ;compare second byte of
  92. :0042ADE6 0F8563010000            jne 0042AF4F                ;serial with 'E'
  93. :0042ADEC C70500C8430001000000    mov dword ptr [0043C800], 00000001
  94.  
  95. We can see from above code, the first byte of our serial need to be 'P' and second byte need to
  96. be either '4'(PRO edition) or 'E'(Enterprise edition), so we can chose to register as either
  97. PRO edition or enterprise edition.
  98.  
  99.  
  100. * Referenced by a (U)nconditional or (C)onditional Jump at Address:
  101. |:0042ADD8(U)
  102. |
  103. :0042ADF6 83C9FF                  or ecx, FFFFFFFF
  104. :0042ADF9 33C0                    xor eax, eax
  105. :0042ADFB F2                      repnz
  106. :0042ADFC AE                      scasb
  107. :0042ADFD F7D1                    not ecx
  108. :0042ADFF 2BF9                    sub edi, ecx
  109.  
  110. The above code basically calculate the lenght of edi(our serial), and return the result in ecx.
  111.  
  112. :0042AE01 8D542414                lea edx, dword ptr [esp+14]
  113. :0042AE05 8BC1                    mov eax, ecx
  114. :0042AE07 8BF7                    mov esi, edi
  115. :0042AE09 8BFA                    mov edi, edx
  116. :0042AE0B 6A2D                    push 0000002D        ;push 2D ('-') in stack
  117. :0042AE0D C1E902                  shr ecx, 02
  118. :0042AE10 F3                      repz
  119. :0042AE11 A5                      movsd
  120. :0042AE12 8BC8                    mov ecx, eax
  121. :0042AE14 83E103                  and ecx, 00000003
  122. :0042AE17 F3                      repz
  123. :0042AE18 A4                      movsb
  124. :0042AE19 8D4C2418                lea ecx, dword ptr [esp+18]
  125.  
  126. The above code move content of edi(our serial) to [ESP+14]
  127.  
  128. :0042AE1D 51                      push ecx
  129. :0042AE1E E81D2A0000              call 0042D840
  130. :0042AE23 8BF8                    mov edi, eax
  131. :0042AE25 83C408                  add esp, 00000008
  132. :0042AE28 85FF                    test edi, edi
  133. :0042AE2A 0F8429010000            je 0042AF59
  134.  
  135. The above call actually test whether our fake serial contain '-'(remember it push 2D into stack?
  136. ), it return eax=-????? of our code or 00 if no '-' found. Then it test if eax=00 then straight
  137. die.
  138.  
  139.  
  140. :0042AE30 C60700                  mov byte ptr [edi], 00    ;clear the '-' in our serial
  141. :0042AE33 8B151CB44300            mov edx, dword ptr [0043B41C]    ;edx=20202020,20 is space(' ')
  142. :0042AE39 A020B44300              mov al, byte ptr [0043B420]
  143. :0042AE3E 6A04                    push 00000004
  144. :0042AE40 8D4C2410                lea ecx, dword ptr [esp+10]
  145. :0042AE44 55                      push ebp
  146. :0042AE45 51                      push ecx
  147. :0042AE46 89542418                mov dword ptr [esp+18], edx
  148. :0042AE4A 8844241C                mov byte ptr [esp+1C], al
  149. :0042AE4E E8ED370000              call 0042E640
  150.  
  151. The above call basically test for space(' ')in our serial, but it did nothing except return eax=
  152. first 4 character of our name. So it basically is a rubbish call.
  153.  
  154. :0042AE53 8A542420                mov dl, byte ptr [esp+20]    ;move first byte of our serial
  155. :0042AE57 83C40C                  add esp, 0000000C        ;to dl
  156. :0042AE5A 84D2                    test dl, dl
  157. :0042AE5C 7421                    je 0042AE7F
  158. :0042AE5E 8D742414                lea esi, dword ptr [esp+14]    ;esi=our serial
  159.  
  160. Actually the above code move 'P' to dl(because the first byte of real serial is 'P' as stated in
  161. above lines).
  162. The first important loop begins:
  163.  
  164. * Referenced by a (U)nconditional or (C)onditional Jump at Address:
  165. |:0042AE7D(C)
  166. |
  167. :0042AE62 33C9                    xor ecx, ecx            ;restart counter
  168. :0042AE64 80C203                  add dl, 03            ;dl=dl+3
  169.  
  170. * Referenced by a (U)nconditional or (C)onditional Jump at Address:
  171. |:0042AE75(C)
  172. |
  173. :0042AE67 8A440C0C                mov al, byte ptr [esp+ecx+0C]    ;move ecx byte of [esp+0c] to al
  174. :0042AE6B F6EA                    imul dl            ;al=al*dl
  175. :0042AE6D 88440C0C                mov byte ptr [esp+ecx+0C], al    ;move result back to [esp+ecx+0c]
  176. :0042AE71 41                      inc ecx            ;increase counter
  177. :0042AE72 83F904                  cmp ecx, 00000004        ;compare counter with 4
  178. :0042AE75 7CF0                    jl 0042AE67            ;jump if less than 4
  179. :0042AE77 8A5601                  mov dl, byte ptr [esi+01]    ;move next byte of serial to dl
  180. :0042AE7A 46                      inc esi            ;increase address of serial
  181. :0042AE7B 84D2                    test dl, dl            ;test dl=0?
  182. :0042AE7D 75E3                    jne 0042AE62            ;jump if false
  183.  
  184.  
  185. This is the first important loops in generating serial. Ecx act as a counter in this case,
  186. it count the number of [esp+0c] up to 4, dl is the first few bytes of our serial until 00
  187. (remember we replace 2D with 00).It multiply every byte of the [esp+0c] with every byte of
  188. our serial until dl=00. So it basically contain two small loop inner one multiple every byte of
  189. [esp+0c](initially [esp+0c] is the first four byte of our name) with dl, the outer loop move 
  190. next byte of our serial to dl until dl=00. So that every byte of the [esp+0c] is multiple by 
  191. every byte of our serial before '-'.
  192. If you still don't understand, try to trace it yourself or look at my C-language coding in 
  193. below part.
  194.  
  195.  
  196. * Referenced by a (U)nconditional or (C)onditional Jump at Address:
  197. |:0042AE5C(C)
  198. |
  199. :0042AE7F 8A4D00                  mov cl, byte ptr [ebp+00]
  200. :0042AE82 84C9                    test cl, cl
  201. :0042AE84 7419                    je 0042AE9F
  202.  
  203. It test wheter first byte of our name is empty or not.
  204. Then we follow by the second important big loop,it contain two loops, a inner and a outer loop.
  205.  
  206. :0042AE86 8BD5                    mov edx, ebp            ;edx=our name
  207. * Referenced by a (U)nconditional or (C)onditional Jump at Address:
  208. |:0042AE9D(C)
  209. |
  210. :0042AE88 33C0                    xor eax, eax            ;eax act as counter
  211. :0042AE8A 80C103                  add cl, 03            ;cl=cl+3
  212.  
  213. * Referenced by a (U)nconditional or (C)onditional Jump at Address:
  214. |:0042AE95(C)
  215. |
  216. :0042AE8D 304C040C                xor byte ptr [esp+eax+0C], cl    ;xor eax byte of[esp+0c] with cl
  217. :0042AE91 40                      inc eax            ;increase counter
  218. :0042AE92 83F804                  cmp eax, 00000004        ;compare eax with 4
  219. :0042AE95 7CF6                    jl 0042AE8D            ;repeat if less than 4
  220. :0042AE97 8A4A01                  mov cl, byte ptr [edx+01]    ;move next char of name into cl
  221. :0042AE9A 42                      inc edx            ;increase edx
  222. :0042AE9B 84C9                    test cl, cl            ;test whether is end of name
  223. :0042AE9D 75E9                    jne 0042AE88            ;jump if false
  224.  
  225. This second impotant loop basically xor (every byte of our name + 3)with every byte of [esp+0c].
  226. the inner loop xor every bytes of [esp+0c] with cl, the outer loop move next char in our name
  227. into cl and add cl with 03.
  228. If you still donn't understand try to trace it again by yourself or look at my c-language coding
  229. in below part.
  230.  
  231.  
  232. * Referenced by a (U)nconditional or (C)onditional Jump at Address:
  233. |:0042AE84(C)
  234. |
  235. :0042AE9F 8B4C240C                mov ecx, dword ptr [esp+0C]    ;move the final result to ecx 
  236. :0042AEA3 85C9                    test ecx, ecx            
  237. :0042AEA5 7D04                    jge 0042AEAB            ;test if ecx>0
  238. :0042AEA7 F7D9                    neg ecx            ;ecx=-ecx 
  239. :0042AEA9 85C9                    test ecx, ecx            ;test if ecx=0
  240.  
  241. * Referenced by a (U)nconditional or (C)onditional Jump at Address:
  242. |:0042AEA5(C)
  243. |
  244. :0042AEAB 7507                    jne 0042AEB4            ;jump if flase
  245. :0042AEAD B901000000              mov ecx, 00000001        ;ecx=1
  246. :0042AEB2 EB08                    jmp 0042AEBC
  247.  
  248. The above code actually convert ecx to positive number if it is less than 0, and if ecx=0 then 
  249. let ecx=1.
  250.  
  251. * Referenced by a (U)nconditional or (C)onditional Jump at Address:
  252. |:0042AEAB(C)
  253. |
  254. :0042AEB4 81F90F270000            cmp ecx, 0000270F    ;compare ecx with 9999
  255. :0042AEBA 7D0D                    jge 0042AEC9
  256.  
  257. * Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
  258. |:0042AEB2(U), :0042AEC7(C)
  259. |
  260. :0042AEBC 8D0C89                  lea ecx, dword ptr [ecx+4*ecx]
  261. :0042AEBF D1E1                    shl ecx, 1
  262. :0042AEC1 81F90F270000            cmp ecx, 0000270F
  263. :0042AEC7 7CF3                    jl 0042AEBC
  264.  
  265. If ecx<9999, then ecx=ecx*10. And repeat the operation until ecx>9999
  266.  
  267.  
  268. * Referenced by a (U)nconditional or (C)onditional Jump at Address:
  269. |:0042AEBA(C)
  270. |
  271. :0042AEC9 81F93F420F00            cmp ecx, 000F423F    ;compare ecx with 999999
  272. :0042AECF 7E1B                    jle 0042AEEC
  273.  
  274. * Referenced by a (U)nconditional or (C)onditional Jump at Address:
  275. |:0042AEEA(C)
  276. |
  277. :0042AED1 B867666666              mov eax, 66666667
  278. :0042AED6 F7E9                    imul ecx
  279. :0042AED8 8BCA                    mov ecx, edx
  280. :0042AEDA C1F902                  sar ecx, 02
  281. :0042AEDD 8BD1                    mov edx, ecx
  282. :0042AEDF C1EA1F                  shr edx, 1F
  283. :0042AEE2 03CA                    add ecx, edx
  284. :0042AEE4 81F93F420F00            cmp ecx, 000F423F
  285. :0042AEEA 7FE5                    jg 0042AED1
  286.  
  287. if ecx>999999, then ecx=ecx/10. And repeat until ecx<1000000.
  288.  
  289. * Referenced by a (U)nconditional or (C)onditional Jump at Address:
  290. |:0042AECF(C)
  291. |
  292. :0042AEEC 51                      push ecx
  293.  
  294. * Possible StringData Ref from Data Obj ->"%li"
  295.                                   |
  296. :0042AEED 6818B44300              push 0043B418
  297. :0042AEF2 8D442430                lea eax, dword ptr [esp+30]
  298. :0042AEF6 6A14                    push 00000014
  299. :0042AEF8 50                      push eax
  300. :0042AEF9 E8FE290000              call 0042D8FC            ;covert ecx into string
  301. :0042AEFE 83C410                  add esp, 00000010
  302. :0042AF01 8D7701                  lea esi, dword ptr [edi+01]
  303. :0042AF04 8D442428                lea eax, dword ptr [esp+28]
  304.  
  305. Until here we have already knew the code by typing:
  306. d esi (which return our fake serial after '-')
  307. d eax (which return the real serial after '-')
  308. I cann't remember which one is the our fake serial and which one is real serial, 
  309. it is either one. You can check and verify it.
  310.  
  311. * Referenced by a (U)nconditional or (C)onditional Jump at Address:
  312. |:0042AF26(C)
  313. |
  314. :0042AF08 8A10                    mov dl, byte ptr [eax]
  315. :0042AF0A 8ACA                    mov cl, dl
  316. :0042AF0C 3A16                    cmp dl, byte ptr [esi]
  317. :0042AF0E 752A                    jne 0042AF3A
  318. :0042AF10 84C9                    test cl, cl
  319. :0042AF12 7414                    je 0042AF28
  320. :0042AF14 8A5001                  mov dl, byte ptr [eax+01]
  321. :0042AF17 8ACA                    mov cl, dl
  322. :0042AF19 3A5601                  cmp dl, byte ptr [esi+01]
  323. :0042AF1C 751C                    jne 0042AF3A
  324. :0042AF1E 83C002                  add eax, 00000002
  325. :0042AF21 83C602                  add esi, 00000002
  326. :0042AF24 84C9                    test cl, cl
  327. :0042AF26 75E0                    jne 0042AF08
  328.  
  329. The above code is just to test every byte of our serial with the real serial.
  330.  
  331. * Referenced by a (U)nconditional or (C)onditional Jump at Address:
  332. |:0042AF12(C)
  333. |
  334. :0042AF28 33C0                    xor eax, eax
  335. :0042AF2A 33C9                    xor ecx, ecx
  336. :0042AF2C 85C0                    test eax, eax
  337. :0042AF2E 0F94C1                  sete cl
  338. :0042AF31 5F                      pop edi
  339. :0042AF32 5E                      pop esi
  340. :0042AF33 8BC1                    mov eax, ecx
  341. :0042AF35 5D                      pop ebp
  342. :0042AF36 83C430                  add esp, 00000030
  343. :0042AF39 C3                      ret
  344.  
  345. It will go to the above code if correct serial enter.
  346. The following code is the wrong serial coding, it will produce eax=0, and we neglect them here.
  347. Now we can now enter the serial PE-?????? to register the program. It sucess but after we
  348. restart the program, it pops up a message "You are using a corrupt or pirate copy of SubmitWolf.
  349. If you .....", it can detect our pirate serial so there should be a hidden routine that has
  350. further test on our serial. So we dissambly the program or just using softice bpx messageboxa to
  351. search for the hidden routine, it should be performed at the starting of the program. I used
  352. dissambly method (by using W32dasm), and checck for the string "You are using a corrupt...." and
  353. look for a few lines above the starings:
  354. And we write down the address 00411BC6, then we lunch the target and get into target coding and
  355. get into softice to put breakpoint bpx 411BC2(you must enter into the target area first to put
  356. breakpoint, you can do this by simplily put a breakpoint bpx showwindow and press F12 several
  357. times to get back into the swolf32!. This is a very basic thing, i assume you all know it,
  358.  and i won't repeat next time, repeating simply thing is meaningless)
  359. Then we break at:
  360.  
  361. :00411BC2 0FBE4802                movsx ecx, byte ptr [eax+02]    ;ecx=3rd character of our serial    
  362. * Possible StringData Ref from Data Obj ->"         (((((                "
  363.                                         ->"  H"
  364.                                   |
  365. :00411BC6 8B15F4B74300            mov edx, dword ptr [0043B7F4]
  366. :00411BCC 8A044A                  mov al, byte ptr [edx+2*ecx]
  367. :00411BCF 83E004                  and eax, 00000004
  368.  
  369. * Referenced by a (U)nconditional or (C)onditional Jump at Address:
  370. |:00411BC0(U)
  371. |
  372. :00411BD2 85C0                    test eax, eax
  373. :00411BD4 7542                    jne 00411C18
  374. :00411BD6 A12C6B4400              mov eax, dword ptr [00446B2C]
  375. :00411BDB 68D00F0000              push 00000FD0
  376. :00411BE0 6840F04300              push 0043F040
  377.  
  378. * Possible Reference to String Resource ID=01457: "You are using a corrupt or pirate copy of SubmitWolf.  If yo"
  379.                                   |
  380. :00411BE5 68B1050000              push 000005B1
  381. :00411BEA 50                      push eax
  382. :00411BEB FFD7                    call edi
  383. :00411BED 8B0D2C6B4400            mov ecx, dword ptr [00446B2C]
  384. :00411BF3 68D00F0000              push 00000FD0
  385. :00411BF8 68E0DD4300              push 0043DDE0
  386.  
  387. In order to jump over the warning message, we must have none zero eax. So we must have something
  388. that and with 4(0100) to produce non-zero, so eax must be either ?4(0100),?5(0101),?6(0110)
  389.  or ?7(0111), the four less significant bit of eax must be from 4-7.
  390. We then check for edx since edx is a reference table of all the byte .By typing d eax we saw many
  391. 20,00,48,28,10,... and we also found some 84 at address(satisfy what we want):
  392. 004BB83E,004BB85E-004BB870
  393. Since ecx is the 3rd character of our serial, in order to reach the above address(reverse the
  394. above coding), ecx=((address of 84)-edx)/2    ;edx=43B7F4
  395. So for the address:
  396. 4BB83E ECX=20(' ')
  397. 4BB85E ECX=30('0')
  398. 4BB85F ECX=31('1')
  399. 4BB860 ECX=32('2')
  400. .....
  401. 4BB870 ECX=39('9')
  402.  
  403. So we know our serial must contain the 3rd byte with ' 'or '0'-'9'.
  404. An example of our serial is PE4-654321.
  405.  
  406. ---[ OVERALL CONCLUSION OF KEY GENERATING PROCESS ]--------------------------------------------
  407. 1.first two character of serial must be either 'PE' or 'P4'.
  408. 2.multiple every first four character or our name with every byte of our serial number before '-'.
  409. 3.xor every four byte with every byte of our name.
  410. 4.convert to positive number if <0.
  411. 5.convert to number between 10000 and 1000000.
  412.  
  413. As an example, i use name:yes123 ,the final registration number is PE4-103061(Enterprise edition)
  414.                                    P44-114080(PRO edition)
  415. ---[ C-LANGUAGE CODE ]-------------------------------------------------------------------------
  416. #include <stdio.h>
  417. #include<conio.h>
  418.  
  419. int main(void)
  420.   {
  421.    long code=555583,count1,count2;
  422.    char name[25],cod[5],type='0';
  423.    clrscr();
  424.    textcolor(14);
  425.    cprintf("    __,__\r\n");
  426.    cprintf("   /     \\\r\n" );
  427.    cprintf("   vvvvvvv  /|__/|\r\n");
  428.    cprintf("      I   /O,O   |\r\n");
  429.    cprintf("      I /_____   |      /|/|\r\n");
  430.    cprintf("     J|/^ ^ ^ \\  |    /00  |    _//|\r\n");
  431.    cprintf("      |^ ^ ^ ^ |W|   |/^^\\ |   /oo |\r\n");
  432.    cprintf("       \\m___m__|_|    \\m_m_|   \\mm_|\r\n");
  433.    textcolor(10);
  434.    cprintf("=======================================");
  435.    textcolor(11);
  436.    cprintf("\r\nKeyGenerator for SubmitWolf(DEMO) v4.01");
  437.    textcolor(10);
  438.    cprintf("\r\n=======================================");
  439.    printf("\nCracked by ");
  440.    textcolor(14);
  441.    cprintf("%c%c%c",0x10,0x10,0x10);
  442.    textcolor(12);
  443.    cprintf("Yes123");
  444.    textcolor(14);
  445.    cprintf("%c%c%c",0x11,0x11,0x11);
  446.    printf(" - March 1999");
  447.    printf("\n\nSelect edition PRO(0) or Enterprise(1) (0/1)= ");
  448.    scanf("%c",&type);
  449.    if (type=='1') code=557283;
  450.    getchar();
  451.    printf("Enter registration name = ");
  452.    scanf("%[^\n]",name);
  453.    for(count1=0;count1<=3;count1++)
  454.      cod[count1]=name[count1];
  455.    for(count1=1;count1<=3;count1++){
  456.      for(count2=0;count2<=3;count2++)
  457.        cod[count2]=cod[count2]*(code%100);
  458.      code=code/100;
  459.      }
  460.    for(count1=0;name[count1]>0;count1++)
  461.      for(count2=0;count2<=3;count2++)
  462.        cod[count2]=cod[count2]^(name[count1]+3);
  463.    for(count1=3;count1>=0;count1--){
  464.      code=code+(cod[count1]&0xFF);
  465.      if (count1>0)
  466.        code=code*0x100;
  467.      }
  468.    if(code<0) code=-code;
  469.    for(;code<10000;) code=code*10;
  470.    for(;code>999999;) code=code/10;
  471.    printf("Your serial number = P%c4-%ld",(type=='1')? 'E':'4',code);
  472.    return ;
  473. }
  474.  
  475. ---[ LAST ]--------------------------------------------------------------------------------------
  476.  
  477. I know my english expressing ability is weak, so in many place i know what's happening but i can
  478. express well and explain to you clearly. I hope you can really try it out then you can
  479. understand more out of it. There are many interesting coding like how they do /10 or *10 in
  480. asembly, it is quite different from what we had learned.
  481.  
  482. After you register the program it will need to upgrade to full functional version by download
  483. certain data from internet.
  484.  
  485. You can also try to make a keygen, using the same scheme, for the version 3.XX of the same 
  486. program, remember in the begining i said there is also another call which test for serial key
  487. of version 3,XX, you can have a try on it, it used similar method with little differences.
  488.  
  489. ---[ THAT'S ALL FOLKS ]-----------------------------------------------------------------------
  490.  
  491. Yes123 '99
  492. ==========