【软件介绍】:国产软件, 游戏, 简体中文,  2.7 M

【软件下载】:http://www.supersoko.com/chs/supersoko.zip

【保护方式】:Keyfile + 功能限制

【破解工具】:Win2000, PEiD, Ollydbg, DeDe, W32DSM

【破解目的】:研究算法分析

【作者声明】:初学Crack,只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!

—————————————————————————————————
【破解过程】:

1, 注册文件名破解

侦测:用PEiD查壳,ASPack 2.12, 用Ollydbg+ImportRec, 几分钟就可脱掉

脱壳后再用PEiD, 为 Borland Delphi 4.0 - 5.0

OllyDbg 打开软件, F9 运行, 帮助(H) -> 注册(R) 输入: 

注册用户名:: blackeyes
用户Email::  blackeyes@abc.com

只有 "确定" 一个 Button, 没有别的可点.

点 "确定" , 没有错误提示, 再 帮助(H) -> 注册(R), 注册用户名 & 用户Email 为空.

看注册方法:
1、到作者网站,按照注册说明交付注册费;
2、将您的注册用户名及真实有效的Email告知作者,作者会在最短的时间内把注册文件邮寄给您;
3、将注册文件拷贝到游戏目录下,再次进入这里输入您的用户名及EMail,若输入正确则点击注册,然后退出并重新进入游戏即可完成注册!

看来要先有注册文件才可以点击注册.

用 DEDE 分析脱壳后 的文件,

TAboutBox.eNameChange 是用户在输入 注册用户名 & 用户Email 时调用的, 

用 OLLYDBG 动态跟一下:

/* How to get the FileName
004AEDDC    55              PUSH EBP
004AEDDD    8BEC            MOV EBP,ESP
004AEDDF    B9 07000000     MOV ECX,7
004AEDE4    6A 00           PUSH 0
004AEDE6    6A 00           PUSH 0
004AEDE8    49              DEC ECX
004AEDE9  ^ 75 F9           JNZ SHORT SuperSok.004AEDE4
004AEDEB    53              PUSH EBX
004AEDEC    56              PUSH ESI
004AEDED    8BD8            MOV EBX,EAX
004AEDEF    33C0            XOR EAX,EAX
004AEDF1    55              PUSH EBP
004AEDF2    68 A9EF4A00     PUSH SuperSok.004AEFA9
004AEDF7    64:FF30         PUSH DWORD PTR FS:[EAX]
004AEDFA    64:8920         MOV DWORD PTR FS:[EAX],ESP
004AEDFD    8D55 F4         LEA EDX,DWORD PTR SS:[EBP-C]
004AEE00    8B83 20030000   MOV EAX,DWORD PTR DS:[EBX+320]
004AEE06    E8 A918F8FF     CALL SuperSok.004306B4                   ; GetText(eMail, str_eMail);
004AEE0B    8B45 F4         MOV EAX,DWORD PTR SS:[EBP-C]
004AEE0E    8D55 F8         LEA EDX,DWORD PTR SS:[EBP-8]
004AEE11    E8 7AA0F5FF     CALL SuperSok.00408E90
004AEE16    8B55 F8         MOV EDX,DWORD PTR SS:[EBP-8]
004AEE19    B8 C0EF4A00     MOV EAX,SuperSok.004AEFC0
004AEE1E    E8 4554F5FF     CALL SuperSok.00404268
004AEE23    85C0            TEST EAX,EAX
004AEE25    0F8E 13010000   JLE SuperSok.004AEF3E
004AEE2B    8D55 EC         LEA EDX,DWORD PTR SS:[EBP-14]
004AEE2E    8B83 18030000   MOV EAX,DWORD PTR DS:[EBX+318]
004AEE34    E8 7B18F8FF     CALL SuperSok.004306B4                   ; GetText(eName, str_eName);
004AEE39    8B45 EC         MOV EAX,DWORD PTR SS:[EBP-14]
004AEE3C    8D55 F0         LEA EDX,DWORD PTR SS:[EBP-10]
004AEE3F    E8 4CA0F5FF     CALL SuperSok.00408E90
004AEE44    8D45 F0         LEA EAX,DWORD PTR SS:[EBP-10]
004AEE47    50              PUSH EAX
004AEE48    8D55 E4         LEA EDX,DWORD PTR SS:[EBP-1C]
004AEE4B    8B83 20030000   MOV EAX,DWORD PTR DS:[EBX+320]
004AEE51    E8 5E18F8FF     CALL SuperSok.004306B4
004AEE56    8B45 E4         MOV EAX,DWORD PTR SS:[EBP-1C]
004AEE59    8D55 E8         LEA EDX,DWORD PTR SS:[EBP-18]
004AEE5C    E8 2FA0F5FF     CALL SuperSok.00408E90
004AEE61    8B55 E8         MOV EDX,DWORD PTR SS:[EBP-18]
004AEE64    58              POP EAX
004AEE65    E8 1A51F5FF     CALL SuperSok.00403F84                   ; str = strcat(str_eName, str_eMail);
004AEE6A    837D F0 00      CMP DWORD PTR SS:[EBP-10],0
004AEE6E    0F84 CA000000   JE SuperSok.004AEF3E
004AEE74    8D55 DC         LEA EDX,DWORD PTR SS:[EBP-24]
004AEE77    8B83 18030000   MOV EAX,DWORD PTR DS:[EBX+318]
004AEE7D    E8 3218F8FF     CALL SuperSok.004306B4
004AEE82    8B45 DC         MOV EAX,DWORD PTR SS:[EBP-24]
004AEE85    8D55 E0         LEA EDX,DWORD PTR SS:[EBP-20]
004AEE88    E8 03A0F5FF     CALL SuperSok.00408E90
004AEE8D    8D45 E0         LEA EAX,DWORD PTR SS:[EBP-20]
004AEE90    50              PUSH EAX
004AEE91    8D55 D4         LEA EDX,DWORD PTR SS:[EBP-2C]
004AEE94    8B83 20030000   MOV EAX,DWORD PTR DS:[EBX+320]
004AEE9A    E8 1518F8FF     CALL SuperSok.004306B4
004AEE9F    8B45 D4         MOV EAX,DWORD PTR SS:[EBP-2C]
004AEEA2    8D55 D8         LEA EDX,DWORD PTR SS:[EBP-28]
004AEEA5    E8 E69FF5FF     CALL SuperSok.00408E90
004AEEAA    8B55 D8         MOV EDX,DWORD PTR SS:[EBP-28]
004AEEAD    58              POP EAX
004AEEAE    E8 D150F5FF     CALL SuperSok.00403F84
004AEEB3    8B45 E0         MOV EAX,DWORD PTR SS:[EBP-20]
004AEEB6    E8 497A0400     CALL SuperSok.004F6904                   ; num1=Func1(str)
004AEEBB    8BF0            MOV ESI,EAX
004AEEBD    A1 206F5200     MOV EAX,DWORD PTR DS:[526F20]
004AEEC2    FF30            PUSH DWORD PTR DS:[EAX]                  ; "C:\Program Files\Supersoko\"
004AEEC4    68 CCEF4A00     PUSH SuperSok.004AEFCC                   ; ASCII "fsk"
004AEEC9    6A 00           PUSH 0
004AEECB    6A 7B           PUSH 7B
004AEECD    8BC6            MOV EAX,ESI
004AEECF    B9 A0860100     MOV ECX,186A0                            ; 100000
004AEED4    33D2            XOR EDX,EDX
004AEED6    F7F1            DIV ECX
004AEED8    8955 C8         MOV DWORD PTR SS:[EBP-38],EDX            ; num2=num1%100000;
004AEEDB    33C0            XOR EAX,EAX
004AEEDD    8945 CC         MOV DWORD PTR SS:[EBP-34],EAX
004AEEE0    DF6D C8         FILD QWORD PTR SS:[EBP-38]               ; d1=(double)num2;
004AEEE3    DB2D D0EF4A00   FLD TBYTE PTR DS:[4AEFD0]                ; d2 = 3.14;
004AEEE9    DEC9            FMULP ST(1),ST
004AEEEB    D9FA            FSQRT                                    ; d3= sqrt(d1*d2);
004AEEED    E8 E63BF5FF     CALL SuperSok.00402AD8                   ; num3 = (int)round(d3); // int (d3+0.5);
004AEEF2    E8 A17BF5FF     CALL SuperSok.00406A98                   ; num4 = Func2(0x7b, num3); // A * B
004AEEF7    52              PUSH EDX
004AEEF8    50              PUSH EAX
004AEEF9    8D45 D0         LEA EAX,DWORD PTR SS:[EBP-30]
004AEEFC    E8 3FA1F5FF     CALL SuperSok.00409040                   ; printf("%d", num4);
004AEF01    FF75 D0         PUSH DWORD PTR SS:[EBP-30]
004AEF04    68 E4EF4A00     PUSH SuperSok.004AEFE4                   ; ASCII ".fsk"
004AEF09    8D45 FC         LEA EAX,DWORD PTR SS:[EBP-4]
004AEF0C    BA 04000000     MOV EDX,4
004AEF11    E8 2651F5FF     CALL SuperSok.0040403C
004AEF16    8B45 FC         MOV EAX,DWORD PTR SS:[EBP-4]
004AEF19    E8 E2A3F5FF     CALL SuperSok.00409300
004AEF1E    84C0            TEST AL,AL
004AEF20    74 0F           JE SHORT SuperSok.004AEF31
004AEF22    B2 01           MOV DL,1
004AEF24    8B83 28030000   MOV EAX,DWORD PTR DS:[EBX+328]
004AEF2A    E8 9D16F8FF     CALL SuperSok.004305CC
004AEF2F    EB 0D           JMP SHORT SuperSok.004AEF3E
004AEF31    33D2            XOR EDX,EDX
004AEF33    8B83 28030000   MOV EAX,DWORD PTR DS:[EBX+328]
004AEF39    E8 8E16F8FF     CALL SuperSok.004305CC
004AEF3E    33C0            XOR EAX,EAX
004AEF40    5A              POP EDX
004AEF41    59              POP ECX
004AEF42    59              POP ECX
004AEF43    64:8910         MOV DWORD PTR FS:[EAX],EDX
004AEF46    68 B0EF4A00     PUSH SuperSok.004AEFB0
004AEF4B    8D45 D0         LEA EAX,DWORD PTR SS:[EBP-30]
004AEF4E    E8 A94DF5FF     CALL SuperSok.00403CFC
004AEF53    8D45 D4         LEA EAX,DWORD PTR SS:[EBP-2C]
004AEF56    E8 A14DF5FF     CALL SuperSok.00403CFC
004AEF5B    8D45 D8         LEA EAX,DWORD PTR SS:[EBP-28]
004AEF5E    E8 994DF5FF     CALL SuperSok.00403CFC
004AEF63    8D45 DC         LEA EAX,DWORD PTR SS:[EBP-24]
004AEF66    E8 914DF5FF     CALL SuperSok.00403CFC
004AEF6B    8D45 E0         LEA EAX,DWORD PTR SS:[EBP-20]
004AEF6E    E8 894DF5FF     CALL SuperSok.00403CFC
004AEF73    8D45 E4         LEA EAX,DWORD PTR SS:[EBP-1C]
004AEF76    E8 814DF5FF     CALL SuperSok.00403CFC
004AEF7B    8D45 E8         LEA EAX,DWORD PTR SS:[EBP-18]
004AEF7E    E8 794DF5FF     CALL SuperSok.00403CFC
004AEF83    8D45 EC         LEA EAX,DWORD PTR SS:[EBP-14]
004AEF86    E8 714DF5FF     CALL SuperSok.00403CFC
004AEF8B    8D45 F0         LEA EAX,DWORD PTR SS:[EBP-10]
004AEF8E    E8 694DF5FF     CALL SuperSok.00403CFC
004AEF93    8D45 F4         LEA EAX,DWORD PTR SS:[EBP-C]
004AEF96    E8 614DF5FF     CALL SuperSok.00403CFC
004AEF9B    8D45 F8         LEA EAX,DWORD PTR SS:[EBP-8]
004AEF9E    BA 02000000     MOV EDX,2
004AEFA3    E8 784DF5FF     CALL SuperSok.00403D20
004AEFA8    C3              RETN
*/


/* Get a Number based on a string 
004F6904    53              PUSH EBX
004F6905    56              PUSH ESI
004F6906    57              PUSH EDI
004F6907    55              PUSH EBP
004F6908    51              PUSH ECX
004F6909    8BD8            MOV EBX,EAX
004F690B    8BC3            MOV EAX,EBX
004F690D    E8 6AD6F0FF     CALL SuperSok.00403F7C                   ; num1 = strlen(str1); ==> ESI
004F6912    8BF0            MOV ESI,EAX
004F6914    8BC3            MOV EAX,EBX
004F6916    E8 61D6F0FF     CALL SuperSok.00403F7C                   ; len = strlen(str1)
004F691B    8BF8            MOV EDI,EAX
004F691D    85FF            TEST EDI,EDI
004F691F    7E 57           JLE SHORT SuperSok.004F6978              ; for(i=0;i<len;i++) {
004F6921    BD 01000000     MOV EBP,1
004F6926    8A442B FF       MOV AL,BYTE PTR DS:[EBX+EBP-1]           ; ch1=str1[i]; ==> AL
004F692A    8BD6            MOV EDX,ESI
004F692C    C1EA 08         SHR EDX,8                                ; num1>>8
004F692F    32C2            XOR AL,DL
004F6931    880424          MOV BYTE PTR SS:[ESP],AL                 ; ch2 = ch1 ^ (num1>>8); ==>[ESP]
004F6934    8BC3            MOV EAX,EBX
004F6936    E8 41D6F0FF     CALL SuperSok.00403F7C                   ; strlen(str1)
004F693B    B9 32000000     MOV ECX,32                               ; 50
004F6940    99              CDQ
004F6941    F7F9            IDIV ECX                                 ; EAX=(EDX:EAX)/50, EDX=[EDX:EAX)%50
004F6943    8B0495 286B5200 MOV EAX,DWORD PTR DS:[EDX*4+526B28]      ; num2 = value1[len%50];
004F694A    33D2            XOR EDX,EDX
004F694C    8A1424          MOV DL,BYTE PTR SS:[ESP]
004F694F    03F2            ADD ESI,EDX                              ; num1 += ch2;
004F6951    F7EE            IMUL ESI                                 ; num2 *= num1;
004F6953    50              PUSH EAX
004F6954    8BC3            MOV EAX,EBX
004F6956    E8 21D6F0FF     CALL SuperSok.00403F7C
004F695B    B9 32000000     MOV ECX,32
004F6960    99              CDQ
004F6961    F7F9            IDIV ECX
004F6963    B8 31000000     MOV EAX,31
004F6968    2BC2            SUB EAX,EDX                              ; num3 = 49 - len%50;
004F696A    5A              POP EDX
004F696B    031485 F46B5200 ADD EDX,DWORD PTR DS:[EAX*4+526BF4]      ; num2 += value2[num3];
004F6972    8BF2            MOV ESI,EDX                              ; num1 = num2;
004F6974    45              INC EBP
004F6975    4F              DEC EDI
004F6976  ^ 75 AE           JNZ SHORT SuperSok.004F6926              ; }
004F6978    8BC6            MOV EAX,ESI                              ; return num1;
004F697A    5A              POP EDX
004F697B    5D              POP EBP
004F697C    5F              POP EDI
004F697D    5E              POP ESI
004F697E    5B              POP EBX
004F697F    C3              RETN
*/

注册文件名算法:
a. 注册用户名 + 用户Email, 再 CALL 004F6904, 返回一 magic_num
b. magic_num / 100000, 取余数, 再 X 3.14;
c. 取平方根, 4舍5入取整,
d. 再 X 0x7B, 得一number: ####
e. 文件名为 fsk###.fsk


2. keyfile 内容初步跟踪/破解

输入

  注册用户名:: blackeyes
  用户Email::  blackeyes@abc.com

算出文件名为fsk46740.fsk

用二进制工具构造出一 fsk46740.fsk 文件, 拷贝到游戏目录下

OLLYDBG, 下断 CreateFileA, 当filename 是fsk46740.fsk, Ctrl+F9 返回 00409203

下断 ReadFile, 然后再 F8 慢慢跟

004091F8   E8 43AFFFFF      CALL SuperSok.00404140
004091FD   50               PUSH EAX
004091FE   E8 69DEFFFF      CALL SuperSok.0040706C                   ; JMP to kernel32.CreateFileA
00409203   5E               POP ESI                                  ; // 返回这
00409204   5B               POP EBX
00409205   C3               RETN                                     ; // 返回00412FD2


00412FBC   E8 6788FFFF      CALL SuperSok.0040B828
00412FC1   E8 EA07FFFF      CALL SuperSok.004037B0
00412FC6   EB 37            JMP SHORT SuperSok.00412FFF
00412FC8   0FB7D7           MOVZX EDX,DI
00412FCB   8BC6             MOV EAX,ESI
00412FCD   E8 F661FFFF      CALL SuperSok.004091C8                   ; Open KeyFile
00412FD2   8943 04          MOV DWORD PTR DS:[EBX+4],EAX             ; // 上面返回这
00412FD5   837B 04 00       CMP DWORD PTR DS:[EBX+4],0
00412FD9   7D 24            JGE SHORT SuperSok.00412FFF
00412FDB   8975 F4          MOV DWORD PTR SS:[EBP-C],ESI
00412FDE   C645 F8 0B       MOV BYTE PTR SS:[EBP-8],0B
00412FE2   8D45 F4          LEA EAX,DWORD PTR SS:[EBP-C]
00412FE5   50               PUSH EAX
00412FE6   6A 00            PUSH 0
00412FE8   8B0D 24735200    MOV ECX,DWORD PTR DS:[527324]            ; SuperSok.0040DAC8
00412FEE   B2 01            MOV DL,1
00412FF0   A1 78EA4000      MOV EAX,DWORD PTR DS:[40EA78]
00412FF5   E8 2E88FFFF      CALL SuperSok.0040B828
00412FFA   E8 B107FFFF      CALL SuperSok.004037B0
00412FFF   8BC3             MOV EAX,EBX
00413001   807D FF 00       CMP BYTE PTR SS:[EBP-1],0
00413005   74 0F            JE SHORT SuperSok.00413016
00413007   E8 A403FFFF      CALL SuperSok.004033B0
0041300C   64:8F05 00000000 POP DWORD PTR FS:[0]
00413013   83C4 0C          ADD ESP,0C
00413016   8BC3             MOV EAX,EBX
00413018   5F               POP EDI
00413019   5E               POP ESI
0041301A   5B               POP EBX
0041301B   8BE5             MOV ESP,EBP
0041301D   5D               POP EBP
0041301E   C2 0400          RETN 4                                   ; // 返回00413143


0041313E   E8 29FEFFFF      CALL SuperSok.00412F6C                   ; // Open KeyFile
00413143   8945 FC          MOV DWORD PTR SS:[EBP-4],EAX             ; // 上面返回这
00413146   33C0             XOR EAX,EAX
00413148   55               PUSH EBP
00413149   68 74314100      PUSH SuperSok.00413174
0041314E   64:FF30          PUSH DWORD PTR FS:[EAX]
00413151   64:8920          MOV DWORD PTR FS:[EAX],ESP
00413154   8B55 FC          MOV EDX,DWORD PTR SS:[EBP-4]
00413157   8BC3             MOV EAX,EBX
00413159   E8 96FFFFFF      CALL SuperSok.004130F4                   ; // F8 这一句, 会断在 ReadFile
0041315E   33C0             XOR EAX,EAX
00413160   5A               POP EDX
00413161   59               POP ECX
00413162   59               POP ECX
00413163   64:8910          MOV DWORD PTR FS:[EAX],EDX
00413166   68 7B314100      PUSH SuperSok.0041317B
0041316B   8B45 FC          MOV EAX,DWORD PTR SS:[EBP-4]
0041316E   E8 A5FEFEFF      CALL SuperSok.00403018
00413173   C3               RETN                                     ; // 返回0041317B
00413174  ^E9 FF05FFFF      JMP SuperSok.00403778
00413179  ^EB F0            JMP SHORT SuperSok.0041316B
0041317B   5B               POP EBX
0041317C   59               POP ECX
0041317D   5D               POP EBP
0041317E   C3               RETN                                     ; // 返回0050D2B3



/* File Handler during INIT
0050D28B   .  E8 FC17F4FF   CALL SuperSok.0044EA8C
0050D290   >  B2 01         MOV DL,1
0050D292   .  A1 90F64000   MOV EAX,DWORD PTR DS:[40F690]
0050D297   .  E8 4C5DEFFF   CALL SuperSok.00402FE8
0050D29C   .  8B15 30735200 MOV EDX,DWORD PTR DS:[527330]            ;  SuperSok.00ADEFAC
0050D2A2   .  8902          MOV DWORD PTR DS:[EDX],EAX
0050D2A4   .  A1 30735200   MOV EAX,DWORD PTR DS:[527330]
0050D2A9   .  8B00          MOV EAX,DWORD PTR DS:[EAX]
0050D2AB   .  8B55 F0       MOV EDX,DWORD PTR SS:[EBP-10]
0050D2AE   .  E8 795EF0FF   CALL SuperSok.0041312C                   ; // Open & Read KeyFile
0050D2B3   .  A1 30735200   MOV EAX,DWORD PTR DS:[527330]            ; 返回这
0050D2B8   .  8B00          MOV EAX,DWORD PTR DS:[EAX]
0050D2BA   .  E8 415AF0FF   CALL SuperSok.00412D00
0050D2BF   .  8BD0          MOV EDX,EAX
0050D2C1   .  81EA FE010000 SUB EDX,1FE                              ; EDX -= 510;
0050D2C7   .  A1 30735200   MOV EAX,DWORD PTR DS:[527330]
0050D2CC   .  8B00          MOV EAX,DWORD PTR DS:[EAX]
0050D2CE   .  33C9          XOR ECX,ECX
0050D2D0   .  8B18          MOV EBX,DWORD PTR DS:[EAX]
0050D2D2   .  FF53 0C       CALL DWORD PTR DS:[EBX+C]
0050D2D5   .  33C0          XOR EAX,EAX
0050D2D7   .  55            PUSH EBP
0050D2D8   .  68 2FD35000   PUSH SuperSok.0050D32F
0050D2DD   .  64:FF30       PUSH DWORD PTR FS:[EAX]
0050D2E0   .  64:8920       MOV DWORD PTR FS:[EAX],ESP
0050D2E3   .  33DB          XOR EBX,EBX
0050D2E5   .  8B35 AC715200 MOV ESI,DWORD PTR DS:[5271AC]            ;  numbers @ [5271AC]
0050D2EB   >  8D55 E6       LEA EDX,DWORD PTR SS:[EBP-1A]
0050D2EE   .  A1 30735200   MOV EAX,DWORD PTR DS:[527330]
0050D2F3   .  8B00          MOV EAX,DWORD PTR DS:[EAX]
0050D2F5   .  B9 0A000000   MOV ECX,0A                               ; 10 bytes
0050D2FA   .  8B38          MOV EDI,DWORD PTR DS:[EAX]
0050D2FC   .  FF57 04       CALL DWORD PTR DS:[EDI+4]                ; copy_buf()
0050D2FF   .  8D8D 1CFFFFFF LEA ECX,DWORD PTR SS:[EBP-E4]
0050D305   .  8D45 E6       LEA EAX,DWORD PTR SS:[EBP-1A]
0050D308   .  8BD3          MOV EDX,EBX
0050D30A   .  E8 7196FEFF   CALL SuperSok.004F6980                   ; 解密 buf
0050D30F   .  8B85 1CFFFFFF MOV EAX,DWORD PTR SS:[EBP-E4]
0050D315   .  E8 D2BDEFFF   CALL SuperSok.004090EC                   ; num = (unsigned long)atol(buf)
0050D31A   .  8906          MOV DWORD PTR DS:[ESI],EAX               ; numbers[i] = num;
0050D31C   .  43            INC EBX                                  ; i++;
0050D31D   .  83C6 04       ADD ESI,4
0050D320   .  83FB 33       CMP EBX,33                               ; i==51?
0050D323   .^ 75 C6         JNZ SHORT SuperSok.0050D2EB              ; repeat
0050D325   .  33C0          XOR EAX,EAX
0050D327   .  5A            POP EDX
0050D328   .  59            POP ECX
0050D329   .  59            POP ECX
*/



/* Decode 10 bytes buffer 
004F6980  /$  53            PUSH EBX                                 ; (EAX=buf_in, DX=index, ECX=buf_out)
004F6981  |.  56            PUSH ESI
004F6982  |.  57            PUSH EDI
004F6983  |.  55            PUSH EBP
004F6984  |.  83C4 F8       ADD ESP,-8
004F6987  |.  894C24 04     MOV DWORD PTR SS:[ESP+4],ECX
004F698B  |.  8BEA          MOV EBP,EDX
004F698D  |.  890424        MOV DWORD PTR SS:[ESP],EAX
004F6990  |.  0FB7C5        MOVZX EAX,BP
004F6993  |.  66:8B3C45 C06>MOV DI,WORD PTR DS:[EAX*2+526CC0]        ; ushort num1 = value3[index];
004F699B  |.  8B4424 04     MOV EAX,DWORD PTR SS:[ESP+4]
004F699F  |.  BA FC694F00   MOV EDX,SuperSok.004F69FC                ; ASCII "0000000000"
004F69A4  |.  E8 A7D3F0FF   CALL SuperSok.00403D50
004F69A9  |.  BE 01000000   MOV ESI,1                                ; for (i=0;i<10;i++) {
004F69AE  |.  8B1C24        MOV EBX,DWORD PTR SS:[ESP]
004F69B1  |>  8B4424 04     MOV EAX,DWORD PTR SS:[ESP+4]
004F69B5  |.  E8 92D7F0FF   CALL SuperSok.0040414C
004F69BA  |.  8A13          MOV DL,BYTE PTR DS:[EBX]                 ; ch1 = buf_in[i];
004F69BC  |.  0FB7CF        MOVZX ECX,DI                             ;
004F69BF  |.  C1E9 08       SHR ECX,8
004F69C2  |.  32D1          XOR DL,CL                                ; ch1 ^= (num1>>8);
004F69C4  |.  885430 FF     MOV BYTE PTR DS:[EAX+ESI-1],DL           ; buf_out[i] = ch1;
004F69C8  |.  33D2          XOR EDX,EDX
004F69CA  |.  8A13          MOV DL,BYTE PTR DS:[EBX]                 ; ch1 = buf_in[i];
004F69CC  |.  66:03FA       ADD DI,DX                                ; num1 += ch1;
004F69CF  |.  0FB7C5        MOVZX EAX,BP
004F69D2  |.  66:0FAF3C85 2>IMUL DI,WORD PTR DS:[EAX*4+526B28]       ; num1 *= value1[index];
004F69DB  |.  66:033C85 F46>ADD DI,WORD PTR DS:[EAX*4+526BF4]        ; num1 += value2[index];
004F69E3  |.  46            INC ESI
004F69E4  |.  43            INC EBX
004F69E5  |.  83FE 0B       CMP ESI,0B
004F69E8  |.^ 75 C7         JNZ SHORT SuperSok.004F69B1              ; }
004F69EA  |.  59            POP ECX
004F69EB  |.  5A            POP EDX
004F69EC  |.  5D            POP EBP
004F69ED  |.  5F            POP EDI
004F69EE  |.  5E            POP ESI
004F69EF  |.  5B            POP EBX
004F69F0  \.  C3            RETN
*/

跟踪结果:
a. 文件最后510 bytes, 分为 51 块, 每块 10 Bytes
b. 每块 10 Bytes, CALL 004F6980 解密, 
c. 结果应是长为10 的整数串
d. 每串转换为一整数, 保存在 size 为 51 的数组中

 
3. keyfile 内容再跟踪/破解A


用C写一小程序, 构造出一 fsk46740.fsk 文件, 长为510, 满足上面的条件.

再用 OLLYDBG 动态调

程序报错, 在OLLYDBG 中点 暂停, 根据堆栈友好提示, 可跟踪到下面的CODE

/* 
005129DC  |.  A1 30735200   MOV EAX,DWORD PTR DS:[527330]
005129E1  |.  8B00          MOV EAX,DWORD PTR DS:[EAX]
005129E3  |.  33C9          XOR ECX,ECX
005129E5  |.  BA F8110000   MOV EDX,11F8                             ; offset = 4600; // 23*200
005129EA  |.  8B18          MOV EBX,DWORD PTR DS:[EAX]
005129EC  |.  FF53 0C       CALL DWORD PTR DS:[EBX+C]
005129EF  |.  33C0          XOR EAX,EAX
005129F1  |.  8945 EC       MOV DWORD PTR SS:[EBP-14],EAX            ; sum = 0;
005129F4  |.  BB C8000000   MOV EBX,0C8                              ; num = 200;
005129F9  |>  8D55 EB       /LEA EDX,DWORD PTR SS:[EBP-15]           ; buf=[EBP-15];
005129FC  |.  A1 30735200   |MOV EAX,DWORD PTR DS:[527330]
00512A01  |.  8B00          |MOV EAX,DWORD PTR DS:[EAX]
00512A03  |.  B9 01000000   |MOV ECX,1                               ; bytes=1
00512A08  |.  8B38          |MOV EDI,DWORD PTR DS:[EAX]
00512A0A  |.  FF57 04       |CALL DWORD PTR DS:[EDI+4]               ; get_buf(buf, bytes)?
00512A0D  |.  33C0          |XOR EAX,EAX
00512A0F  |.  8A45 EB       |MOV AL,BYTE PTR SS:[EBP-15]             ; ch=buf[0];
00512A12  |.  0145 EC       |ADD DWORD PTR SS:[EBP-14],EAX           ; sum += ch;
00512A15  |.  4B            |DEC EBX                                 ; num--;
00512A16  |.^ 75 E1         \JNZ SHORT SuperSok.005129F9             ; num==0?
00512A18  |.  A1 AC715200   MOV EAX,DWORD PTR DS:[5271AC]            ; numbers @ [5271AC]
00512A1D  |.  8B40 5C       MOV EAX,DWORD PTR DS:[EAX+5C]            ; EAX = numbers[23]; // 0x5C=4*23d
00512A20  |.  3B45 EC       CMP EAX,DWORD PTR SS:[EBP-14]            ; EAX = sum? ********
00512A23  |.  74 26         JE SHORT SuperSok.00512A4B               ; // 必须跳
00512A25  |.  8B0D 58715200 MOV ECX,DWORD PTR DS:[527158]            ;  SuperSok.00ADEF9C
00512A2B  |.  8B09          MOV ECX,DWORD PTR DS:[ECX]
00512A2D  |.  8B15 A86F5200 MOV EDX,DWORD PTR DS:[526FA8]            ;  SuperSok.00ADEFD0
00512A33  |.  8B12          MOV EDX,DWORD PTR DS:[EDX]
00512A35  |.  B8 03000000   MOV EAX,3
00512A3A  |.  E8 6940FEFF   CALL SuperSok.004F6AA8
00512A3F  |.  A1 18725200   MOV EAX,DWORD PTR DS:[527218]
*/

跟踪结果:
a. 从文件offset 4600 取200 Bytes 累加, 求和
b. 累加和 == 51 个的数组中的一个, array[23]

用W32DASM反汇编, 找类似的CODE, 好多地方, 只有 OFFSET 与 index 有区别.

4. keyfile 内容再跟踪/破解B

重新构造出一 fsk46740.fsk 文件, 长为200*50+510, 满足上面的条件.

再用 OLLYDBG F9运行, 还是报错, 跟到下面的CODE

/*
004B47CF  |.  33F6          XOR ESI,ESI                              ; i = 0;
004B47D1  |.  8D45 E6       LEA EAX,DWORD PTR SS:[EBP-1A]            ; buf=[EBP-24]
004B47D4  |.  8945 DC       MOV DWORD PTR SS:[EBP-24],EAX
004B47D7  |>  8BD6          /MOV EDX,ESI                             ; EDX = i;
004B47D9  |.  C1E2 02       |SHL EDX,2                               ; EDX *= 4;
004B47DC  |.  8D1492        |LEA EDX,DWORD PTR DS:[EDX+EDX*4]        ; EDX *= 5; // EDX=20*i;
004B47DF  |.  81C2 F8110000 |ADD EDX,11F8                            ; offset = 4600+20*i; // 23 * 200
004B47E5  |.  A1 30735200   |MOV EAX,DWORD PTR DS:[527330]
004B47EA  |.  8B00          |MOV EAX,DWORD PTR DS:[EAX]
004B47EC  |.  33C9          |XOR ECX,ECX
004B47EE  |.  8B38          |MOV EDI,DWORD PTR DS:[EAX]
004B47F0  |.  FF57 0C       |CALL DWORD PTR DS:[EDI+C]
004B47F3  |.  8B45 DC       |MOV EAX,DWORD PTR SS:[EBP-24]
004B47F6  |.  8BD0          |MOV EDX,EAX
004B47F8  |.  A1 30735200   |MOV EAX,DWORD PTR DS:[527330]
004B47FD  |.  8B00          |MOV EAX,DWORD PTR DS:[EAX]
004B47FF  |.  B9 01000000   |MOV ECX,1                               ; bytes = 1
004B4804  |.  8B38          |MOV EDI,DWORD PTR DS:[EAX]
004B4806  |.  FF57 04       |CALL DWORD PTR DS:[EDI+4]               ; get_buf(buf, bytes)?
004B4809  |.  46            |INC ESI                                 ; i++;
004B480A  |.  FF45 DC       |INC DWORD PTR SS:[EBP-24]               ; buf++;
004B480D  |.  83FE 0A       |CMP ESI,0A                              ; i<10?
004B4810  |.^ 75 C5         \JNZ SHORT SuperSok.004B47D7             ; loop
004B4812  |.  8D4D A0       LEA ECX,DWORD PTR SS:[EBP-60]            ; &result
004B4815  |.  8D45 E6       LEA EAX,DWORD PTR SS:[EBP-1A]            ; buf
004B4818  |.  66:BA 1700    MOV DX,17
004B481C  |.  E8 5F210400   CALL SuperSok.004F6980                   ; 解密 buf
004B4821  |.  8B45 A0       MOV EAX,DWORD PTR SS:[EBP-60]            ; result
004B4824  |.  8B15 FC6E5200 MOV EDX,DWORD PTR DS:[526EFC]            ;
004B482A  |.  8B12          MOV EDX,DWORD PTR DS:[EDX]
004B482C  |.  E8 5BF8F4FF   CALL SuperSok.0040408C                   ; CString_Compare(result, xx)?
004B4831  |.  74 26         JE SHORT SuperSok.004B4859               ; // 必须跳
004B4833  |.  8B0D 58715200 MOV ECX,DWORD PTR DS:[527158]            ; SuperSok.00ADEF9C
004B4839  |.  8B09          MOV ECX,DWORD PTR DS:[ECX]
004B483B  |.  8B15 A86F5200 MOV EDX,DWORD PTR DS:[526FA8]            ; SuperSok.00ADEFD0
004B4841  |.  8B12          MOV EDX,DWORD PTR DS:[EDX]
004B4843  |.  B8 03000000   MOV EAX,3
004B4848  |.  E8 5B220400   CALL SuperSok.004F6AA8
004B484D  |.  A1 18725200   MOV EAX,DWORD PTR DS:[527218]
004B4852  |.  8B00          MOV EAX,DWORD PTR DS:[EAX]
004B4854  |.  E8 33A2F9FF   CALL SuperSok.0044EA8C
004B4859  |>  8B83 2C030000 MOV EAX,DWORD PTR DS:[EBX+32C]
004B485F  |.  8B80 44020000 MOV EAX,DWORD PTR DS:[EAX+244]
*/
跟踪结果:
a. 从文件offset 4600 取200 Bytes
b. 每 20 bytes 中取 第1 BYTE, 构成一长为10的BUF;
c. 10 Bytes, CALL 004F6980 解密
d. 结果与一串相比, 必须一样, 
e. 类似的CODE好多, 只有 OFFSET 与 index 有区别.


相比较的串是这样取出来的:
004B4824  |.  8B15 FC6E5200 MOV EDX,DWORD PTR DS:[526EFC] 
004B482A  |.  8B12          MOV EDX,DWORD PTR DS:[EDX]

在 OLLYDBG 中 Search constants 526EFC, 可找到下面的CODE

/*
0050D141   .  A1 48705200   MOV EAX,DWORD PTR DS:[527048]
0050D146   .  C600 00       MOV BYTE PTR DS:[EAX],0
0050D149   .  6A 00         PUSH 0
0050D14B   .  8D45 F4       LEA EAX,DWORD PTR SS:[EBP-C]             ;  buf for RegName
0050D14E   .  50            PUSH EAX
0050D14F   .  A1 4C735200   MOV EAX,DWORD PTR DS:[52734C]
0050D154   .  8B00          MOV EAX,DWORD PTR DS:[EAX]
0050D156   .  B9 4CE35000   MOV ECX,SuperSok.0050E34C                ;  ASCII "Name"
0050D15B   .  BA E4E45000   MOV EDX,SuperSok.0050E4E4                ;  ASCII "RegName"
0050D160   .  E8 D31EF7FF   CALL SuperSok.0047F038                   ;  ReadFromRegister(...) // read RegName
0050D165   .  6A 00         PUSH 0
0050D167   .  8D85 30FFFFFF LEA EAX,DWORD PTR SS:[EBP-D0]            ;  buf for RegEmail
0050D16D   .  50            PUSH EAX
0050D16E   .  A1 4C735200   MOV EAX,DWORD PTR DS:[52734C]
0050D173   .  8B00          MOV EAX,DWORD PTR DS:[EAX]
0050D175   .  B9 F4E45000   MOV ECX,SuperSok.0050E4F4                ;  ASCII "Email"
0050D17A   .  BA 04E55000   MOV EDX,SuperSok.0050E504                ;  ASCII "RegEmail"
0050D17F   .  E8 B41EF7FF   CALL SuperSok.0047F038                   ;  ReadFreomRegister(...) // read RegEmail
0050D184   .  8B95 30FFFFFF MOV EDX,DWORD PTR SS:[EBP-D0]            ;  str_Email
0050D18A   .  8D45 F4       LEA EAX,DWORD PTR SS:[EBP-C]             ;  str_Name
0050D18D   .  E8 F26DEFFF   CALL SuperSok.00403F84                   ;  strNameEmail = strcat(Name, Email)
0050D192   .  837D F4 00    CMP DWORD PTR SS:[EBP-C],0
0050D196   .  0F84 CB010000 JE SuperSok.0050D367
0050D19C   .  8B45 F4       MOV EAX,DWORD PTR SS:[EBP-C]
0050D19F   .  E8 6097FEFF   CALL SuperSok.004F6904                   ;  magic_num = Func1(strNameEmail);
0050D1A4   .  8D95 2CFFFFFF LEA EDX,DWORD PTR SS:[EBP-D4]
0050D1AA   .  E8 BD96FEFF   CALL SuperSok.004F686C                   ;  sprintf(magic_buf, "%10u", magic_num);
0050D1AF   .  8B95 2CFFFFFF MOV EDX,DWORD PTR SS:[EBP-D4]
0050D1B5   .  A1 FC6E5200   MOV EAX,DWORD PTR DS:[526EFC]            ;  String @ [526EFC]   ***************
0050D1BA   .  E8 916BEFFF   CALL SuperSok.00403D50                   ;  String.buf=magic_buf;
0050D1BF   .  A1 206F5200   MOV EAX,DWORD PTR DS:[526F20]
0050D1C4   .  FF30          PUSH DWORD PTR DS:[EAX]
0050D1C6   .  68 18E55000   PUSH SuperSok.0050E518                   ;  ASCII "fsk"
0050D1CB   .  6A 00         PUSH 0
0050D1CD   .  6A 7B         PUSH 7B
0050D1CF   .  6A 00         PUSH 0
0050D1D1   .  68 A0860100   PUSH 186A0                               ;  100000
0050D1D6   .  A1 FC6E5200   MOV EAX,DWORD PTR DS:[526EFC]            ;  String @[526EFC]
0050D1DB   .  8B00          MOV EAX,DWORD PTR DS:[EAX]               ;  String.buf
0050D1DD   .  E8 0ABFEFFF   CALL SuperSok.004090EC                   ;  magic_num = sscanf("%10u", buf);
0050D1E2   .  E8 EA99EFFF   CALL SuperSok.00406BD1                   ;  magic_num%10000
0050D1E7   .  8985 20FFFFFF MOV DWORD PTR SS:[EBP-E0],EAX
0050D1ED   .  8995 24FFFFFF MOV DWORD PTR SS:[EBP-DC],EDX
0050D1F3   .  DFAD 20FFFFFF FILD QWORD PTR SS:[EBP-E0]               ;  (double)int
0050D1F9   .  DB2D 1CE55000 FLD TBYTE PTR DS:[50E51C]                ;  3.14
0050D1FF   .  DEC9          FMULP ST(1),ST
0050D201   .  D9FA          FSQRT
0050D203   .  E8 D058EFFF   CALL SuperSok.00402AD8
0050D208   .  E8 8B98EFFF   CALL SuperSok.00406A98
0050D20D   .  52            PUSH EDX                                 ; /Arg2
0050D20E   .  50            PUSH EAX                                 ; |Arg1
0050D20F   .  8D85 28FFFFFF LEA EAX,DWORD PTR SS:[EBP-D8]            ; |
0050D215   .  E8 26BEEFFF   CALL SuperSok.00409040                   ; \SuperSok.00409040
0050D21A   .  FFB5 28FFFFFF PUSH DWORD PTR SS:[EBP-D8]
0050D220   .  68 30E55000   PUSH SuperSok.0050E530                   ; ASCII ".fsk"
0050D225   .  8D45 F0       LEA EAX,DWORD PTR SS:[EBP-10]
0050D228   .  BA 04000000   MOV EDX,4
0050D22D   .  E8 0A6EEFFF   CALL SuperSok.0040403C
0050D232   .  8B45 F0       MOV EAX,DWORD PTR SS:[EBP-10]
0050D235   .  E8 C6C0EFFF   CALL SuperSok.00409300
*/

5. 分析总结:
 Crack的难点:
    a. 注册没有错误提示, 文件名动态计算
    b. CALL FindFirstFileA 判断文件是否存在, 而不是用 CreateFileA
    c. keyfile SIZE 大, >10K
    d. Read Keyfile 是 有多少就读多少, 在分析清楚前, 不好确定 SIZE
    e. 不是一次判断, 很多地方, 很难暴破
  作者加密/算法的不足
    a. 加密壳等于没有
    b. 没有反跟踪, 没有防 DEDE
    c. 加密算法强度不高, 
  d. 判断点很多,分析一处就可解决相同的其它多处: OFFSET 与 index 成正比


6. 注册机

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <math.h>
#include <time.h>

// @00526B28
unsigned long value1[51] = {
    0x0000CE6D,    0x000084C3,    0x00007176,    0x00004B82,
    0x0000E387,    0x00018605,    0x0000F66F,    0x00005C04,
    0x00005C45,    0x0000B0BC,    0x0000AB60,    0x0000AB83,
    0x0000CFFA,    0x0000A8CD,    0x000108F8,    0x00015DCB,
    0x0000D2B1,    0x00011EC5,    0x0000CC79,    0x0000B2B1,
    0x0000BEE9,    0x0000337D,    0x0000AA70,    0x00012253,
    0x0000E058,    0x00014A72,    0x00005AF2,    0x0000DFEA,
    0x0000B2A4,    0x00015D4E,    0x00017FBA,    0x0000809E,
    0x0000D4FA,    0x0000B5D0,    0x0000B6C9,    0x00015D71,
    0x00016B9B,    0x0001802A,    0x000121F0,    0x00013648,
    0x000181C2,    0x000102C8,    0x0000B236,    0x0000DC16,
    0x000152D7,    0x0000328F,    0x00011E21,    0x000123E2,
  0x0000536B,    0x0000B257,    0x0000B045
};

// @00526BF4
unsigned long value2[51] = {
    0x000058BF,    0x000086DB,    0x00010A02,    0x0000C468,
    0x00003980,    0x000181BF,    0x000102C1,    0x0000B23C,
    0x0000DC1B,    0x000152D7,    0x00014A70,    0x00005AF2,
    0x0000DFF0,    0x0000B2A9,    0x00015D54,    0x0000AB63,
    0x0000AB7E,    0x0000CFFA,    0x0000A8D1,    0x000108F8,
    0x0000BEEC,    0x0000337E,    0x0000AA71,    0x00012254,
    0x0000E05E,    0x00015D72,    0x00016B9C,    0x00018026,
    0x000121F0,    0x00013648,    0x0000328E,    0x00011E1D,
    0x000123E1,    0x0000536B,    0x0000B256,    0x00017FBC,
    0x0000809D,    0x0000D4F9,    0x0000B5D0,    0x0000B6CE,
    0x00015DCC,    0x0000D2AF,    0x00011EC4,    0x0000CC79,
    0x0000B2B0,    0x0001560A,    0x0000758C,    0x00005CFB,
    0x0001251A,    0x00012280,    0x00015542,
};

// @00526CC0
unsigned short value3[51] = {
   0x0052,   0x004A,   0x001D,   0x001D,   0x001A,   0x0036,   0x0062,   
0x0038,
   0x0017,   0x002D,   0x0062,   0x037D,   0x02F7,   0x0905,   0x1F07,   
0x0359,
   0x03AF,   0x2668,   0x2673,   0x165A,   0x221E,   0x2675,   0x1C35,   
0x0D68,
   0x11C9,   0x0D7D,   0x0022,   0x2694,   0x1C6A,   0x02AA,   0x02AF,   
0x0223,
   0x095E,   0x0009,   0x18BC,   0x021F,   0x01B2,   0x0980,   0x11AA,   
0x10E4,
   0x2248,   0x0296,   0x0156,   0x0023,   0x00EA,   0x0233,   0x0E32,   
0x0D7D,
   0x1916,   0x0D7F,   0x2213
};


//@004F6904
unsigned long Func1(char *str)
{
  int i, len;
  unsigned char ch1, ch2;
  unsigned long num1, num2;

  len = strlen(str);
  num1 = len;
  for(i=0;i<len;i++)
  {
    ch1 = str[i];
    ch2 = ch1 ^ (unsigned char)(num1>>8);
    num2 = value1[len%50];
    num1 += ch2;
    num2 *= num1;
    num2 += value2[49-len%50];
    num1 = num2;
  }
  return num1;
}

const char Progpath[]="C:\\Program Files\\Supersoko\\";
unsigned long getFilename(char *name, char *email, char *filename)
{
  char buf[100];
  unsigned long num1, num2, num3, num4;
  double d1;
  strcpy(buf, name);
  strcat(buf, email);
  num1 = Func1(buf);
  num2 = num1 % 100000;
  d1 = (double) num2;
  d1 *= 3.14;
  d1 = sqrt(d1);
  num3 = (int)(d1+0.5);
  num4 = num3 * 0x7B;
  sprintf(filename, "%sfsk%u.fsk", Progpath, num4);
  return num1;
}

//@004F6980
void Func2(char *in, char *out, int index)
{
  int i;
  unsigned char  ch;
  unsigned short num;

  num = value3[index];
  for (i=0;i<10;i++)
  {
    ch = in[i];
    out[i] = ch ^ (unsigned char)(num>>8);
    num += ch;
    num *= (unsigned short)value1[index];
    num += (unsigned short)value2[index];
  }
}

void Reverse_Func2(char *in, char *out, int index)
{
  int i;
  unsigned char  ch;
  unsigned short num;

  num = value3[index];
  for (i=0;i<10;i++)
  {
    ch = in[i];
    out[i] = ch ^ (unsigned char)(num>>8);
    ch = out[i];
    num += ch;
    num *= (unsigned short)value1[index];
    num += (unsigned short)value2[index];
  }
}


char User[100];
char Email[100];
char Filename[100];
int main(void)
{
  int i,j;
  unsigned long magic_num, checksum[51];
  FILE *fp;
  unsigned char ch;
  char big_buf1[200];
  char small_buf1[20],small_buf2[20];
  printf("Username:");
  gets(User);
  printf("Email:");
  gets(Email);
  magic_num = getFilename(User, Email, Filename);
  printf("filename=%s\n", Filename);

  fp = fopen(Filename,"wb");
  if (!fp) {
    printf("fopen error\n");
    return 0;
  }
  sprintf(small_buf1, "%010u", magic_num);
  memset(big_buf1, 0, 200);
  for(i=0;i<50;i++)
  {
    Reverse_Func2(small_buf1, small_buf2, i);
    for(j=0;j<10;j++)
    {
      big_buf1[20*j] = small_buf2[j];
    }
    fwrite(big_buf1, 1, 200, fp);
    checksum[i] = 0;
    for(j=0;j<200;j++)
    {
      ch = (unsigned char)big_buf1[j];
      checksum[i] += (unsigned long)ch;
    }
  }
  checksum[50] = 0;

  for(i=0;i<51;i++)
  {
    sprintf(small_buf1, "%010u", checksum[i]);
    Reverse_Func2(small_buf1, small_buf2, i);
    fwrite(small_buf2, 1, 10, fp);
  }
  fclose(fp);

  return 0;

}

  • 标 题: 编译成功
  • 作 者:menglv
  • 时 间:2005-10-18 13:44

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <math.h>
#include <time.h>

/* @00526B28 */
unsigned long value1[51] = {
    0x0000CE6D,    0x000084C3,    0x00007176,    0x00004B82,
    0x0000E387,    0x00018605,    0x0000F66F,    0x00005C04,
    0x00005C45,    0x0000B0BC,    0x0000AB60,    0x0000AB83,
    0x0000CFFA,    0x0000A8CD,    0x000108F8,    0x00015DCB,
    0x0000D2B1,    0x00011EC5,    0x0000CC79,    0x0000B2B1,
    0x0000BEE9,    0x0000337D,    0x0000AA70,    0x00012253,
    0x0000E058,    0x00014A72,    0x00005AF2,    0x0000DFEA,
    0x0000B2A4,    0x00015D4E,    0x00017FBA,    0x0000809E,
    0x0000D4FA,    0x0000B5D0,    0x0000B6C9,    0x00015D71,
    0x00016B9B,    0x0001802A,    0x000121F0,    0x00013648,
    0x000181C2,    0x000102C8,    0x0000B236,    0x0000DC16,
    0x000152D7,    0x0000328F,    0x00011E21,    0x000123E2,
  0x0000536B,    0x0000B257,    0x0000B045
};

/* @00526BF4 */
unsigned long value2[51] = {
    0x000058BF,    0x000086DB,    0x00010A02,    0x0000C468,
    0x00003980,    0x000181BF,    0x000102C1,    0x0000B23C,
    0x0000DC1B,    0x000152D7,    0x00014A70,    0x00005AF2,
    0x0000DFF0,    0x0000B2A9,    0x00015D54,    0x0000AB63,
    0x0000AB7E,    0x0000CFFA,    0x0000A8D1,    0x000108F8,
    0x0000BEEC,    0x0000337E,    0x0000AA71,    0x00012254,
    0x0000E05E,    0x00015D72,    0x00016B9C,    0x00018026,
    0x000121F0,    0x00013648,    0x0000328E,    0x00011E1D,
    0x000123E1,    0x0000536B,    0x0000B256,    0x00017FBC,
    0x0000809D,    0x0000D4F9,    0x0000B5D0,    0x0000B6CE,
    0x00015DCC,    0x0000D2AF,    0x00011EC4,    0x0000CC79,
    0x0000B2B0,    0x0001560A,    0x0000758C,    0x00005CFB,
    0x0001251A,    0x00012280,    0x00015542,
};

/* @00526CC0 */
unsigned short value3[51] = {
   0x0052,   0x004A,   0x001D,   0x001D,   0x001A,   0x0036,   0x0062,   
0x0038,
   0x0017,   0x002D,   0x0062,   0x037D,   0x02F7,   0x0905,   0x1F07,   
0x0359,
   0x03AF,   0x2668,   0x2673,   0x165A,   0x221E,   0x2675,   0x1C35,   
0x0D68,
   0x11C9,   0x0D7D,   0x0022,   0x2694,   0x1C6A,   0x02AA,   0x02AF,   
0x0223,
   0x095E,   0x0009,   0x18BC,   0x021F,   0x01B2,   0x0980,   0x11AA,   
0x10E4,
   0x2248,   0x0296,   0x0156,   0x0023,   0x00EA,   0x0233,   0x0E32,   
0x0D7D,
   0x1916,   0x0D7F,   0x2213
};


/* @004F6904 */
unsigned long Func1(char *str)
{
  int i, len;
  unsigned char ch1, ch2;
  unsigned long num1, num2;

  len = strlen(str);
  num1 = len;
  for(i=0;i<len;i++)
  {
    ch1 = str[i];
    ch2 = ch1 ^ (unsigned char)(num1>>8);
    num2 = value1[len%50];
    num1 += ch2;
    num2 *= num1;
    num2 += value2[49-len%50];
    num1 = num2;
  }
  return num1;
}

const char Progpath[]="C:\\Progra~1\\Supers~1\\";
unsigned long getFilename(char *name, char *email, char *filename)
{
  char buf[100];
  unsigned long num1, num2, num3, num4;
  double d1;
  strcpy(buf, name);
  strcat(buf, email);
  num1 = Func1(buf);
  num2 = num1 % 100000;
  d1 = (double) num2;
  d1 *= 3.14;
  d1 = sqrt(d1);
  num3 = (int)(d1+0.5);
  num4 = num3 * 0x7B;
  sprintf(filename, "%sfsk%u.fsk", Progpath, num4);
  return num1;
}

/* @004F6980 */
void Func2(char *in, char *out, int index)
{
  int i;
  unsigned char  ch;
  unsigned short num;

  num = value3[index];
  for (i=0;i<10;i++)
  {
    ch = in[i];
    out[i] = ch ^ (unsigned char)(num>>8);
    num += ch;
    num *= (unsigned short)value1[index];
    num += (unsigned short)value2[index];
  }
}

void Reverse_Func2(char *in, char *out, int index)
{
  int i;
  unsigned char  ch;
  unsigned short num;

  num = value3[index];
  for (i=0;i<10;i++)
  {
    ch = in[i];
    out[i] = ch ^ (unsigned char)(num>>8);
    ch = out[i];
    num += ch;
    num *= (unsigned short)value1[index];
    num += (unsigned short)value2[index];
  }
}


char User[100];
char Email[100];
char Filename[100];
int main(void)
{
  int i,j;
  unsigned long magic_num, checksum[51];
  FILE *fp;
  unsigned char ch;
  char big_buf1[200];
  char small_buf1[20],small_buf2[20];
  printf("Username:");
  gets(User);
  printf("Email:");
  gets(Email);
  magic_num = getFilename(User, Email, Filename);
  printf("filename=%s\n", Filename);

  fp = fopen(Filename,"wb");
  if (!fp) {
    printf("fopen error\n");
    return 0;
  }
  sprintf(small_buf1, "%010u", magic_num);
  memset(big_buf1, 0, 200);
  for(i=0;i<50;i++)
  {
    Reverse_Func2(small_buf1, small_buf2, i);
    for(j=0;j<10;j++)
    {
      big_buf1[20*j] = small_buf2[j];
    }
    fwrite(big_buf1, 1, 200, fp);
    checksum[i] = 0;
    for(j=0;j<200;j++)
    {
      ch = (unsigned char)big_buf1[j];
      checksum[i] += (unsigned long)ch;
    }
  }
  checksum[50] = 0;

  for(i=0;i<51;i++)
  {
    sprintf(small_buf1, "%010u", checksum[i]);
    Reverse_Func2(small_buf1, small_buf2, i);
    fwrite(small_buf2, 1, 10, fp);
  }
  fclose(fp);

  return 0;

}