飘云阁

 找回密码
 加入我们

QQ登录

只需一步,快速开始

查看: 4251|回复: 6

Crackme1 by qxtianlong 的算法分析

[复制链接]
  • TA的每日心情

    2024-4-11 22:10
  • 签到天数: 53 天

    [LV.5]常住居民I

    发表于 2005-10-26 08:17:57 | 显示全部楼层 |阅读模式
    【破文作者】   rdsnow[BCG][PYG][D.4s]

    【作者主页】   http://rdsnow.ys168.com

    【 E-mail 】   [email protected]

    【 作者QQ 】   83757177

    【文章题目】   Crackme1 by qxtianlong 的算法分析

    【软件名称】   Crackme1 by qxtianlong

    【下载地址】   https://www.chinapyg.com/attachm ... a1e2&download=1

    破解平台】   Microsoft Windows XP Professional --SP2

    ----------------------------------------------------------------------------------------------
    【文章简介】

    最近被Asprotect 2.11壳的Stolen Code搞的头疼,看来偶在脱壳上前途渺茫啊,只能精力集中到算法上了,发现在硬盘上竟然还有个Crackme,打开提示“难度高”,于是就跟进看看。发现这个Crackme爆破难度不大,很容易找到爆破点,看来作者是要找到真注册码,跟出算法。

    程序采用了MD5(Usename)=F_En(code)的非明码比较方式。

    MD5( )是标准的MD5加密算法没有变形。

    F_En( )是作者自己设计的一个加密算法。

    F_En( )算法中使用了固定的密钥,给算法注册机制作带来方便,因为密钥的固定,导致在任何机器上密钥初始化过程完全相同。

    F_En( )算法中使用的SBox[44]是有44个DWORD元素。

    ----------------------------------------------------------------------------------------------
    【破解过程】

    OD插件和W32DASM都没有找到字符串,看来字符加密了。

    但是有错误对话框弹出,命令行下断:bp MessageBoxA返回程序领空后向上来到这里:

    00401B40   .  6A FF           PUSH -1
    00401B42   .  68 3B5A4200     PUSH Crackme1.00425A3B                   ;  SE 句柄安装
    00401B47   .  64:A1 00000000  MOV EAX,DWORD PTR FS:[0]
    00401B4D   .  50              PUSH EAX
    00401B4E   .  64:8925 0000000>MOV DWORD PTR FS:[0],ESP
    00401B55   .  81EC D4010000   SUB ESP,1D4
    00401B5B   .  A1 EC204300     MOV EAX,DWORD PTR DS:[4320EC]
    00401B60   .  898424 D0010000 MOV DWORD PTR SS:[ESP+1D0],EAX
    00401B67   .  53              PUSH EBX
    00401B68   .  B0 5C           MOV AL,5C                                ;  以下给密钥Key赋初值,固定密钥
    00401B6A   .  8BD9            MOV EBX,ECX                              ;  Key共128位,分16个byte赋值
    00401B6C   .  B1 47           MOV CL,47
    00401B6E   .  884424 07       MOV BYTE PTR SS:[ESP+7],AL               ;  byte3=0x5C
    00401B72   .  884424 11       MOV BYTE PTR SS:[ESP+11],AL              ;  byte13=0x5C
    00401B76   .  68 04010000     PUSH 104
    00401B7B   .  8D8424 D4000000 LEA EAX,DWORD PTR SS:[ESP+D4]
    00401B82   .  884C24 09       MOV BYTE PTR SS:[ESP+9],CL               ;  byte1=0x47
    00401B86   .  884C24 17       MOV BYTE PTR SS:[ESP+17],CL              ;  byte15=0x47
    00401B8A   .  50              PUSH EAX
    00401B8B   .  8D8B C4000000   LEA ECX,DWORD PTR DS:[EBX+C4]
    00401B91   .  C64424 0C 35    MOV BYTE PTR SS:[ESP+C],35               ;  byte0=0x35
    00401B96   .  C64424 0E 82    MOV BYTE PTR SS:[ESP+E],82               ;  byte2=0x82
    00401B9B   .  C64424 10 33    MOV BYTE PTR SS:[ESP+10],33              ;  byte4=0x33
    00401BA0   .  C64424 11 8C    MOV BYTE PTR SS:[ESP+11],8C              ;  byte5=0x8C
    00401BA5   .  C64424 12 85    MOV BYTE PTR SS:[ESP+12],85              ;  byte6=0x85
    00401BAA   .  C64424 13 77    MOV BYTE PTR SS:[ESP+13],77              ;  byte7=0x77
    00401BAF   .  C64424 14 9A    MOV BYTE PTR SS:[ESP+14],9A              ;  byte8=0x9A
    00401BB4   .  C64424 15 67    MOV BYTE PTR SS:[ESP+15],67              ;  byte9=0x67
    00401BB9   .  C64424 16 45    MOV BYTE PTR SS:[ESP+16],45              ;  byte10=0x45
    00401BBE   .  C64424 17 7A    MOV BYTE PTR SS:[ESP+17],7A              ;  byte11=0x7A
    00401BC3   .  C64424 18 6D    MOV BYTE PTR SS:[ESP+18],6D              ;  byte12=0x6D
    00401BC8   .  C64424 1A 16    MOV BYTE PTR SS:[ESP+1A],16              ;  byte14=0x16
    00401BCD   .  E8 D9C30100     CALL Crackme1.0041DFAB                   ;  读取用户名"rdsnow[BCG][PYG][D.4s]"
    00401BD2   .  8D4C24 34       LEA ECX,DWORD PTR SS:[ESP+34]
    00401BD6   .  E8 350D0000     CALL Crackme1.00402910                   ;  MD5( )初始化

    --> 00402910  /$  8BD1            MOV EDX,ECX
    --> 00402912  |.  56              PUSH ESI
    --> 00402913  |.  57              PUSH EDI
    --> 00402914  |.  33C0            XOR EAX,EAX
    --> 00402916  |.  8D72 5C         LEA ESI,DWORD PTR DS:[EDX+5C]
    --> 00402919  |.  8BFE            MOV EDI,ESI
    --> 0040291B  |.  8942 18         MOV DWORD PTR DS:[EDX+18],EAX
    --> 0040291E  |.  8942 14         MOV DWORD PTR DS:[EDX+14],EAX
    --> 00402921  |.  B9 10000000     MOV ECX,10
    --> 00402926  |.  C702 1C7A4200   MOV DWORD PTR DS:[EDX],Crackme1.00427A1C
    --> 0040292C  |.  C742 04 0123456>MOV DWORD PTR DS:[EDX+4],67452301    ;这里看到MD5的四个基本常数了
    --> 00402933  |.  C742 08 89ABCDE>MOV DWORD PTR DS:[EDX+8],EFCDAB89
    --> 0040293A  |.  C742 0C FEDCBA9>MOV DWORD PTR DS:[EDX+C],98BADCFE
    --> 00402941  |.  C742 10 7654321>MOV DWORD PTR DS:[EDX+10],10325476
    --> 00402948  |.  F3:AB           REP STOS DWORD PTR ES:[EDI]
    --> 0040294A  |.  5F              POP EDI
    --> 0040294B  |.  C606 80         MOV BYTE PTR DS:[ESI],80
    --> 0040294E  |.  8BC2            MOV EAX,EDX
    --> 00402950  |.  5E              POP ESI
    --> 00402951  \.  C3              RETN

    00401BDB   .  8D8424 D0000000 LEA EAX,DWORD PTR SS:[ESP+D0]
    00401BE2   .  C78424 E0010000>MOV DWORD PTR SS:[ESP+1E0],0
    00401BED   .  8D50 01         LEA EDX,DWORD PTR DS:[EAX+1]
    00401BF0   >  8A08            MOV CL,BYTE PTR DS:[EAX]
    00401BF2   .  40              INC EAX
    00401BF3   .  84C9            TEST CL,CL
    00401BF5   .^ 75 F9           JNZ SHORT Crackme1.00401BF0
    00401BF7   .  2BC2            SUB EAX,EDX                              ;  相减得到用户名的长度 22
    00401BF9   .  50              PUSH EAX
    00401BFA   .  8D8C24 D4000000 LEA ECX,DWORD PTR SS:[ESP+D4]
    00401C01   .  51              PUSH ECX
    00401C02   .  8D4C24 3C       LEA ECX,DWORD PTR SS:[ESP+3C]
    00401C06   .  E8 550D0000     CALL Crackme1.00402960                   ;  转存用户名
    00401C0B   .  8D5424 24       LEA EDX,DWORD PTR SS:[ESP+24]
    00401C0F   .  52              PUSH EDX                                 ; /MD5结果保存地址
    00401C10   .  8D4C24 38       LEA ECX,DWORD PTR SS:[ESP+38]            ; |
    00401C14   .  E8 170E0000     CALL Crackme1.00402A30                   ; \MD5(用户名)
    00401C19   .  68 04010000     PUSH 104
    00401C1E   .  8D8424 D4000000 LEA EAX,DWORD PTR SS:[ESP+D4]
    00401C25   .  50              PUSH EAX
    00401C26   .  8D4B 74         LEA ECX,DWORD PTR DS:[EBX+74]
    00401C29   .  E8 7DC30100     CALL Crackme1.0041DFAB                   ;  读取假码
    00401C2E   .  8D8C24 D0000000 LEA ECX,DWORD PTR SS:[ESP+D0]
    00401C35   .  51              PUSH ECX
    00401C36   .  8BCB            MOV ECX,EBX
    00401C38   .  E8 73F7FFFF     CALL Crackme1.004013B0                   ;  检查注册码的长度和格式,跟进
    00401C3D   .  85C0            TEST EAX,EAX
    00401C3F   .  74 54           JE SHORT Crackme1.00401C95               ;  上面的call检查假码是否由数字和大写A-F组成
    00401C41   .  56              PUSH ESI
    00401C42   .  57              PUSH EDI
    00401C43   .  8D5424 1C       LEA EDX,DWORD PTR SS:[ESP+1C]
    00401C47   .  52              PUSH EDX
    00401C48   .  8D8424 DC000000 LEA EAX,DWORD PTR SS:[ESP+DC]
    00401C4F   .  50              PUSH EAX
    00401C50   .  8BCB            MOV ECX,EBX
    00401C52   .  E8 F9F7FFFF     CALL Crackme1.00401450                   ;  将假码分成四组Sn0,Sn1,Sn2,Sn3
    00401C57   .  8D4C24 0C       LEA ECX,DWORD PTR SS:[ESP+C]
    00401C5B   .  6A 10           PUSH 10
    00401C5D   .  51              PUSH ECX
    00401C5E   .  E8 FDF4FFFF     CALL Crackme1.00401160                   ;  F_En( )初始化,跟进
    00401C63   .  8D5424 24       LEA EDX,DWORD PTR SS:[ESP+24]
    00401C67   .  52              PUSH EDX
    00401C68   .  8BC2            MOV EAX,EDX
    00401C6A   .  50              PUSH EAX
    00401C6B   .  E8 F0F5FFFF     CALL Crackme1.00401260                   ;  F_En(假码),跟进
    00401C70   .  83C4 10         ADD ESP,10
    00401C73   .  B9 04000000     MOV ECX,4
    00401C78   .  8D7C24 1C       LEA EDI,DWORD PTR SS:[ESP+1C]
    00401C7C   .  8D7424 2C       LEA ESI,DWORD PTR SS:[ESP+2C]
    00401C80   .  33D2            XOR EDX,EDX
    00401C82   .  F3:A7           REPE CMPS DWORD PTR ES:[EDI],DWORD PTR D>;  MD5(用户名)和F_En(假码)循环比较
    00401C84   .  5F              POP EDI
    00401C85   .  5E              POP ESI
    00401C86   .  75 0D           JNZ SHORT Crackme1.00401C95              ;  关键跳(爆点)
    00401C88   .  52              PUSH EDX
    00401C89   .  68 147A4200     PUSH Crackme1.00427A14                   ;  恭喜
    00401C8E   .  68 087A4200     PUSH Crackme1.00427A08                   ;  注册成功!
    00401C93   .  EB 0C           JMP SHORT Crackme1.00401CA1              ;  F_En( )初始化,跟进
    00401C95   >  6A 10           PUSH 10
    00401C97   .  68 007A4200     PUSH Crackme1.00427A00
    00401C9C   .  68 F0794200     PUSH Crackme1.004279F0                   ;  注册码错误!
    00401CA1   >  8BCB            MOV ECX,EBX
    00401CA3   .  E8 2C950100     CALL Crackme1.0041B1D4                   ;  跳出对话框
    00401CA8   .  8D4C24 34       LEA ECX,DWORD PTR SS:[ESP+34]
    00401CAC   .  C78424 E0010000>MOV DWORD PTR SS:[ESP+1E0],-1
    00401CB7   .  E8 34030000     CALL Crackme1.00401FF0
    00401CBC   .  8B8C24 D8010000 MOV ECX,DWORD PTR SS:[ESP+1D8]
    00401CC3   .  64:890D 0000000>MOV DWORD PTR FS:[0],ECX
    00401CCA   .  8B8C24 D4010000 MOV ECX,DWORD PTR SS:[ESP+1D4]
    00401CD1   .  5B              POP EBX
    00401CD2   .  E8 1AAE0000     CALL Crackme1.0040CAF1
    00401CD7   .  81C4 E0010000   ADD ESP,1E0
    00401CDD   .  C3              RETN

    小结:

    程序采用MD5(Usename)=F_En(Code)的非明码验证方式。

    求注册码的过程应该是:code=F_De( MD5( usename ) )

    看来要找出F_En( )的解密函数F_De( )了。

    ----------------------------------------------------------------------------------------------

    跟进00401C38 CALL Crackme1.004013B0这一行,看看注册码的构成:

    004013B0  /$  56              PUSH ESI
    004013B1  |.  8B7424 08       MOV ESI,DWORD PTR SS:[ESP+8]
    004013B5  |.  8BC6            MOV EAX,ESI
    004013B7  |.  8D50 01         LEA EDX,DWORD PTR DS:[EAX+1]
    004013BA  |.  8D9B 00000000   LEA EBX,DWORD PTR DS:[EBX]
    004013C0  |>  8A08            /MOV CL,BYTE PTR DS:[EAX]
    004013C2  |.  40              |INC EAX
    004013C3  |.  84C9            |TEST CL,CL
    004013C5  |.^ 75 F9           \JNZ SHORT Crackme1.004013C0
    004013C7  |.  2BC2            SUB EAX,EDX                              ;  相减得到假码的长度
    004013C9  |.  83F8 20         CMP EAX,20                               ;  比较假码的长度是否是32
    004013CC  |.  75 74           JNZ SHORT Crackme1.00401442
    004013CE  |.  33C9            XOR ECX,ECX
    004013D0  |>  8A0431          /MOV AL,BYTE PTR DS:[ECX+ESI]
    004013D3  |.  3C 30           |CMP AL,30
    004013D5  |.  7C 04           |JL SHORT Crackme1.004013DB
    004013D7  |.  3C 39           |CMP AL,39
    004013D9  |.  7E 08           |JLE SHORT Crackme1.004013E3             ;  是不是数字
    004013DB  |>  3C 41           |CMP AL,41
    004013DD  |.  7C 55           |JL SHORT Crackme1.00401434
    004013DF  |.  3C 46           |CMP AL,46
    004013E1  |.  7F 51           |JG SHORT Crackme1.00401434              ;  是不是大写字母A-F
    004013E3  |>  8A4431 01       |MOV AL,BYTE PTR DS:[ECX+ESI+1]
    004013E7  |.  3C 30           |CMP AL,30
    004013E9  |.  7C 04           |JL SHORT Crackme1.004013EF
    004013EB  |.  3C 39           |CMP AL,39
    004013ED  |.  7E 08           |JLE SHORT Crackme1.004013F7             ;  是不是数字
    004013EF  |>  3C 41           |CMP AL,41
    004013F1  |.  7C 36           |JL SHORT Crackme1.00401429
    004013F3  |.  3C 46           |CMP AL,46
    004013F5  |.  7F 32           |JG SHORT Crackme1.00401429              ;  是不是大写字母A-F
    004013F7  |>  8A4431 02       |MOV AL,BYTE PTR DS:[ECX+ESI+2]
    004013FB  |.  3C 30           |CMP AL,30
    004013FD  |.  7C 04           |JL SHORT Crackme1.00401403
    004013FF  |.  3C 39           |CMP AL,39
    00401401  |.  7E 08           |JLE SHORT Crackme1.0040140B             ;  是不是数字
    00401403  |>  3C 41           |CMP AL,41
    00401405  |.  7C 25           |JL SHORT Crackme1.0040142C
    00401407  |.  3C 46           |CMP AL,46
    00401409  |.  7F 21           |JG SHORT Crackme1.0040142C              ;  是不是大写字母A-F
    0040140B  |>  8A4431 03       |MOV AL,BYTE PTR DS:[ECX+ESI+3]
    0040140F  |.  3C 30           |CMP AL,30
    00401411  |.  7C 04           |JL SHORT Crackme1.00401417
    00401413  |.  3C 39           |CMP AL,39
    00401415  |.  7E 08           |JLE SHORT Crackme1.0040141F             ;  是不是数字
    00401417  |>  3C 41           |CMP AL,41
    00401419  |.  7C 16           |JL SHORT Crackme1.00401431
    0040141B  |.  3C 46           |CMP AL,46
    0040141D  |.  7F 12           |JG SHORT Crackme1.00401431              ;  是不是大写字母A-F
    0040141F  |>  83C1 04         |ADD ECX,4
    00401422  |.  83F9 20         |CMP ECX,20                              ;  每次校验4个字符
    00401425  |.^ 7C A9           \JL SHORT Crackme1.004013D0              ;  循环检查假码
    00401427  |.  EB 0B           JMP SHORT Crackme1.00401434
    00401429  |>  41              INC ECX
    0040142A  |.  EB 08           JMP SHORT Crackme1.00401434
    0040142C  |>  83C1 02         ADD ECX,2
    0040142F  |.  EB 03           JMP SHORT Crackme1.00401434
    00401431  |>  83C1 03         ADD ECX,3
    00401434  |>  83F9 20         CMP ECX,20
    00401437  |.  75 09           JNZ SHORT Crackme1.00401442
    00401439  |.  B8 01000000     MOV EAX,1                                ;  通过检查,返回1
    0040143E  |.  5E              POP ESI
    0040143F  |.  C2 0400         RETN 4
    00401442  |>  33C0            XOR EAX,EAX                              ;  不通过检查,返回0
    00401444  |.  5E              POP ESI
    00401445  \.  C2 0400         RETN 4

    小结:

    注册码是有数字和大写字母A-F组成,一共32个字符

    ----------------------------------------------------------------------------------------------

    跟进00401C5E CALL Crackme1.00401160看看SBox[44]的初始化。

    00401160  /$  83EC 24         SUB ESP,24
    00401163  |.  8B4C24 2C       MOV ECX,DWORD PTR SS:[ESP+2C]
    00401167  |.  8D41 03         LEA EAX,DWORD PTR DS:[ECX+3]
    0040116A  |.  99              CDQ
    0040116B  |.  83E2 03         AND EDX,3
    0040116E  |.  53              PUSH EBX
    0040116F  |.  03C2            ADD EAX,EDX
    00401171  |.  55              PUSH EBP
    00401172  |.  C1F8 02         SAR EAX,2
    00401175  |.  33ED            XOR EBP,EBP
    00401177  |.  49              DEC ECX
    00401178  |.  3BCD            CMP ECX,EBP
    0040117A  |.  56              PUSH ESI
    0040117B  |.  57              PUSH EDI
    0040117C  |.  894424 10       MOV DWORD PTR SS:[ESP+10],EAX
    00401180  |.  896C84 10       MOV DWORD PTR SS:[ESP+EAX*4+10],EBP
    00401184  |.  7C 25           JL SHORT Crackme1.004011AB
    00401186  |.  8B7424 38       MOV ESI,DWORD PTR SS:[ESP+38]
    0040118A  |.  8D9B 00000000   LEA EBX,DWORD PTR DS:[EBX]
    00401190  |>  0FB63C31        /MOVZX EDI,BYTE PTR DS:[ECX+ESI]
    00401194  |.  8BD1            |MOV EDX,ECX
    00401196  |.  C1EA 02         |SHR EDX,2
    00401199  |.  8B5C94 14       |MOV EBX,DWORD PTR SS:[ESP+EDX*4+14]
    0040119D  |.  8D5494 14       |LEA EDX,DWORD PTR SS:[ESP+EDX*4+14]
    004011A1  |.  C1E3 08         |SHL EBX,8
    004011A4  |.  03FB            |ADD EDI,EBX
    004011A6  |.  49              |DEC ECX
    004011A7  |.  893A            |MOV DWORD PTR DS:[EDX],EDI
    004011A9  |.^ 79 E5           \JNS SHORT Crackme1.00401190             ;  128位Key分成Key0、Key1、Key3、Key3
    004011AB  |>  C705 40304300 6>MOV DWORD PTR DS:[433040],B7E15163       ;  SBox[0]
    004011B5  |.  B9 44304300     MOV ECX,Crackme1.00433044
    004011BA  |.  8D9B 00000000   LEA EBX,DWORD PTR DS:[EBX]
    004011C0  |>  8B51 FC         /MOV EDX,DWORD PTR DS:[ECX-4]
    004011C3  |.  81EA 4786C861   |SUB EDX,61C88647                        ;  SBox[ i]=SBox[i-1]-0x61C88647
    004011C9  |.  8911            |MOV DWORD PTR DS:[ECX],EDX              ;  保存SBox[ i]
    004011CB  |.  83C1 04         |ADD ECX,4
    004011CE  |.  81F9 EC304300   |CMP ECX,Crackme1.004330EC               ;  从SBox[0]填充到SBox[43]
    004011D4  |.^ 7E EA           \JLE SHORT Crackme1.004011C0
    004011D6  |.  BA 2C000000     MOV EDX,2C
    004011DB  |.  33FF            XOR EDI,EDI
    004011DD  |.  33C9            XOR ECX,ECX
    004011DF  |.  33F6            XOR ESI,ESI
    004011E1  |.  3BC2            CMP EAX,EDX
    004011E3  |.  7E 02           JLE SHORT Crackme1.004011E7
    004011E5  |.  8BD0            MOV EDX,EAX
    004011E7  |>  8D0452          LEA EAX,DWORD PTR DS:[EDX+EDX*2]
    004011EA  |.  83F8 01         CMP EAX,1
    004011ED  |.  7C 69           JL SHORT Crackme1.00401258
    004011EF  |.  894424 3C       MOV DWORD PTR SS:[ESP+3C],EAX
    004011F3  |>  8B04BD 40304300 /MOV EAX,DWORD PTR DS:[EDI*4+433040]     ;  取SBox[ i]
    004011FA  |.  03C1            |ADD EAX,ECX                             ;  + 上一轮循环的结果,第一次加0
    004011FC  |.  03F0            |ADD ESI,EAX                             ;  + SBox[i-1],第一次加0
    004011FE  |.  8BC6            |MOV EAX,ESI
    00401200  |.  C1E8 1D         |SHR EAX,1D
    00401203  |.  8D14F5 00000000 |LEA EDX,DWORD PTR DS:[ESI*8]
    0040120A  |.  0BC2            |OR EAX,EDX                              ;  交换相加结果的前3位和后29位
    0040120C  |.  8904BD 40304300 |MOV DWORD PTR DS:[EDI*4+433040],EAX     ;  存回SBox[ i]
    00401213  |.  8BF0            |MOV ESI,EAX
    00401215  |.  8B44AC 14       |MOV EAX,DWORD PTR SS:[ESP+EBP*4+14]     ;  取Key(i%4)
    00401219  |.  03C1            |ADD EAX,ECX                             ;  加上上一轮循环的结果
    0040121B  |.  8D1430          |LEA EDX,DWORD PTR DS:[EAX+ESI]          ;  Key[i%4]+SBox[ i],这个结果准备下面的换位
    0040121E  |.  8D1C31          |LEA EBX,DWORD PTR DS:[ECX+ESI]          ;  上轮结果+SBox[ i]
    00401221  |.  8BC2            |MOV EAX,EDX
    00401223  |.  83E3 1F         |AND EBX,1F                              ;  取相加结果的后五位
    00401226  |.  B9 20000000     |MOV ECX,20                              ;  0x20-后五位=cl
    0040122B  |.  2BCB            |SUB ECX,EBX
    0040122D  |.  D3E8            |SHR EAX,CL
    0040122F  |.  8BCB            |MOV ECX,EBX
    00401231  |.  D3E2            |SHL EDX,CL
    00401233  |.  0BC2            |OR EAX,EDX                              ;  交换相加结果的前(32-cl)位和后cl位
    00401235  |.  8944AC 14       |MOV DWORD PTR SS:[ESP+EBP*4+14],EAX     ;  将结果保存回去
    00401239  |.  8BC8            |MOV ECX,EAX
    0040123B  |.  8D47 01         |LEA EAX,DWORD PTR DS:[EDI+1]
    0040123E  |.  99              |CDQ
    0040123F  |.  BF 2C000000     |MOV EDI,2C
    00401244  |.  F7FF            |IDIV EDI
    00401246  |.  8D45 01         |LEA EAX,DWORD PTR SS:[EBP+1]
    00401249  |.  8BFA            |MOV EDI,EDX
    0040124B  |.  99              |CDQ
    0040124C  |.  F77C24 10       |IDIV DWORD PTR SS:[ESP+10]
    00401250  |.  FF4C24 3C       |DEC DWORD PTR SS:[ESP+3C]
    00401254  |.  8BEA            |MOV EBP,EDX
    00401256  |.^ 75 9B           \JNZ SHORT Crackme1.004011F3
    00401258  |>  5F              POP EDI
    00401259  |.  5E              POP ESI
    0040125A  |.  5D              POP EBP
    0040125B  |.  5B              POP EBX
    0040125C  |.  83C4 24         ADD ESP,24
    0040125F  \.  C3              RETN

    小结:

    因为作者采用的是固定的Key,没有把Key跟电脑的硬件关联,所以SBox的初始化在任何电脑上都一样,所以这个过程就不铺开了。看注释吧。

    初始化后内存中的SBox[44]

    00433040 -->  63D4757A    EE7A3CB4    6D00027A    8831B70F
    00433050 -->  7728D975    E7BA4156    DC92BFAD    CB17967B
    00433060 -->  1F8B0D7A    8E0B0D4F    431C9651    22293C7F
    00433070 -->  0D243845    C23C7BA6    4CAD232E    B35D36FF
    00433080 -->  551BC015    0BF3CF67    DDAF2D46    A72AA80D
    00433090 -->  EC1C33D4    896B736B    189D7F20    E46D20BE
    004330A0 -->  C4DDD5CC    3DBBA1A7    8A692DB8    EEB598C4
    004330B0 -->  0AA88B0C    F506A11A    ADC68F57    1739E928
    004330C0 -->  577803DA    958F416A    DF1C7CA7    0BBAD3FE
    004330D0 -->  AB6DB39C    B8048075    92628ABB    5CEB9507
    004330E0 -->  64CCA67C    D00B10A6    D4181073    9E147749

    ----------------------------------------------------------------------------------------------

    最后当然跟进00401C6B CALL Crackme1.00401260这一行了。这是整个Crackme最核心的部分。

    00401260  /$  83EC 08         SUB ESP,8
    00401263  |.  8B4424 0C       MOV EAX,DWORD PTR SS:[ESP+C]
    00401267  |.  8B50 08         MOV EDX,DWORD PTR DS:[EAX+8]             ;  Sn2
    0040126A  |.  8B08            MOV ECX,DWORD PTR DS:[EAX]               ;  Sn0
    0040126C  |.  53              PUSH EBX
    0040126D  |.  8B58 04         MOV EBX,DWORD PTR DS:[EAX+4]             ;  Sn1
    00401270  |.  55              PUSH EBP
    00401271  |.  8B68 0C         MOV EBP,DWORD PTR DS:[EAX+C]             ;  Sn3
    00401274  |.  A1 44304300     MOV EAX,DWORD PTR DS:[433044]            ;  SBox[1]
    00401279  |.  895424 14       MOV DWORD PTR SS:[ESP+14],EDX
    0040127D  |.  8B15 40304300   MOV EDX,DWORD PTR DS:[433040]            ;  SBox[0]
    00401283  |.  56              PUSH ESI
    00401284  |.  03DA            ADD EBX,EDX                              ;  Sn1=Sn1+SBox[0]
    00401286  |.  57              PUSH EDI
    00401287  |.  03E8            ADD EBP,EAX                              ;  Sn2=Sn3+SBox[1]
    00401289  |.  C74424 10 4C304>MOV DWORD PTR SS:[ESP+10],Crackme1.00433>
    00401291  |.  EB 04           JMP SHORT Crackme1.00401297
    00401293  |>  8B4C24 14       /MOV ECX,DWORD PTR SS:[ESP+14]
    00401297  |>  8D441B 01        LEA EAX,DWORD PTR DS:[EBX+EBX+1]
    0040129B  |.  0FAFC3          |IMUL EAX,EBX                            ;  D1=(Sn1*2+1)*Sn1
    0040129E  |.  8BD0            |MOV EDX,EAX
    004012A0  |.  C1E0 05         |SHL EAX,5
    004012A3  |.  C1EA 1B         |SHR EDX,1B
    004012A6  |.  0BD0            |OR EDX,EAX                              ;  交换D1的前5位和后27位
    004012A8  |.  8D442D 01       |LEA EAX,DWORD PTR SS:[EBP+EBP+1]
    004012AC  |.  0FAFC5          |IMUL EAX,EBP                            ;  D3=(Sn3*2+1)*Sn3
    004012AF  |.  8BF0            |MOV ESI,EAX
    004012B1  |.  C1E0 05         |SHL EAX,5
    004012B4  |.  C1EE 1B         |SHR ESI,1B
    004012B7  |.  0BF0            |OR ESI,EAX                              ;  交换D3的前5位和后27位
    004012B9  |.  8BC6            |MOV EAX,ESI
    004012BB  |.  83E0 1F         |AND EAX,1F                              ;  a=D3的后5位
    004012BE  |.  8BFA            |MOV EDI,EDX
    004012C0  |.  33F9            |XOR EDI,ECX                             ;  D1=D1^Sn0 (Sn0是上轮循环结果中未被处理的Sn0)
    004012C2  |.  894424 14       |MOV DWORD PTR SS:[ESP+14],EAX
    004012C6  |.  B9 20000000     |MOV ECX,20
    004012CB  |.  2BC8            |SUB ECX,EAX
    004012CD  |.  8BC7            |MOV EAX,EDI
    004012CF  |.  D3E8            |SHR EAX,CL
    004012D1  |.  8B4C24 14       |MOV ECX,DWORD PTR SS:[ESP+14]
    004012D5  |.  D3E7            |SHL EDI,CL
    004012D7  |.  895C24 14       |MOV DWORD PTR SS:[ESP+14],EBX           ;  保存:Sn0=Sn1
    004012DB  |.  83E2 1F         |AND EDX,1F                              ;  b=D1的后5位
    004012DE  |.  0BC7            |OR EAX,EDI                              ;  交换D3的前a位和后(32-a)位
    004012E0  |.  8B7C24 10       |MOV EDI,DWORD PTR SS:[ESP+10]
    004012E4  |.  0347 FC         |ADD EAX,DWORD PTR DS:[EDI-4]            ;  保存:Sn3=D1+SBox[2]
    004012E7  |.  337424 1C       |XOR ESI,DWORD PTR SS:[ESP+1C]           ;  D3=D3^Sn2 (Sn2是上轮循环结果中未被处理的Sn2)
    004012EB  |.  B9 20000000     |MOV ECX,20
    004012F0  |.  2BCA            |SUB ECX,EDX
    004012F2  |.  8BDE            |MOV EBX,ESI
    004012F4  |.  D3EB            |SHR EBX,CL
    004012F6  |.  8BCA            |MOV ECX,EDX
    004012F8  |.  D3E6            |SHL ESI,CL
    004012FA  |.  83C7 08         |ADD EDI,8
    004012FD  |.  896C24 1C       |MOV DWORD PTR SS:[ESP+1C],EBP           ;  保存:Sn2=Sn3(未保存前的Sn3)
    00401301  |.  8BE8            |MOV EBP,EAX
    00401303  |.  0BDE            |OR EBX,ESI                              ;  交换D3的前b位和后(32-b)位
    00401305  |.  8B77 F8         |MOV ESI,DWORD PTR DS:[EDI-8]
    00401308  |.  03DE            |ADD EBX,ESI                             ;  保存:Sn1=D3+SBox[3]
    0040130A  |.  81FF E4304300   |CMP EDI,Crackme1.004330E4
    00401310  |.  897C24 10       |MOV DWORD PTR SS:[ESP+10],EDI           ;  循环20轮
    00401314  |.^ 0F8E 79FFFFFF   \JLE Crackme1.00401293
    0040131A  |.  8B0D EC304300   MOV ECX,DWORD PTR DS:[4330EC]            ;  取SBox[43]
    00401320  |.  8B5424 1C       MOV EDX,DWORD PTR SS:[ESP+1C]            ;  取出Sn2
    00401324  |.  8B7424 14       MOV ESI,DWORD PTR SS:[ESP+14]            ;  取出Sn0
    00401328  |.  03D1            ADD EDX,ECX                              ;  Sn2+SBox[43]
    0040132A  |.  8B0D E8304300   MOV ECX,DWORD PTR DS:[4330E8]            ;  取出SBox[42]
    00401330  |.  03F1            ADD ESI,ECX                              ;  Sn0+SBox[42]
    00401332  |.  8B4C24 20       MOV ECX,DWORD PTR SS:[ESP+20]
    00401336  |.  5F              POP EDI
    00401337  |.  8931            MOV DWORD PTR DS:[ECX],ESI               ;  保存Sn0
    00401339  |.  5E              POP ESI
    0040133A  |.  5D              POP EBP
    0040133B  |.  8959 04         MOV DWORD PTR DS:[ECX+4],EBX             ;  保存Sn1
    0040133E  |.  8951 08         MOV DWORD PTR DS:[ECX+8],EDX             ;  保存Sn2
    00401341  |.  8941 0C         MOV DWORD PTR DS:[ECX+C],EAX             ;  保存Sn3
    00401344  |.  5B              POP EBX
    00401345  |.  83C4 08         ADD ESP,8
    00401348  \.  C3              RETN

    小结:

    算法中用到一个函数f( )

    f(a)就是 (a*2+1)*a,然后将32位结果的前5位和后27位换位。

    上面的注释说得不够清楚,用图表示吧:

    加密过程:

    将待加密的128数据分成四组:Sn0、Sn1、Sn2、Sn3

    _____Sn0__________Sn1__________Sn2__________Sn3_____
                       |                         |
                    +SBox[0]                  +SBox[1]
                       |                         |
    _____Sn0__________Sn1__________Sn2__________Sn3_____ 简单处理后进入循环(循环开始)
          |         /  |            |         /  |
          |        / f( )           |        / f( )
          |       /    |            |       /    |
          |______/____Xor           |______/____Xor
                /      |                  /      |
               /      换位a              /      换位b
              /        |                /        |
             /      +SBox[2]           /      +SBox[3]
            /          |______________/___       |
           /                         /   |       |
          |            _____________|____|_______|
          |            |            |    |________
          |            |            |            |
    _____Sn0__________Sn1__________Sn2__________Sn3_____ 第一轮循环的结果
          |         /  |            |         /  |
          |        / f( )           |        / f( )
          |       /    |            |       /    |
          |______/____Xor           |______/____Xor
                /      |                  /      |
               /      换位a              /      换位b
              /        |                /        |
             /      +SBox[4]           /      +SBox[5]
            /          |______________/___       |
           /                         /   |       |
          |            _____________|____|_______|
          |            |            |    |________
          |            |            |            |
    _____Sn0__________Sn1__________Sn2__________Sn3_____ 第二轮循环的结果

    ……………………………………………………………………

    _____Sn0__________Sn1__________Sn2__________Sn3_____ 第十九轮循环的结果
          |         /  |            |         /  |
          |        / f( )           |        / f( )
          |       /    |            |       /    |
          |______/____Xor           |______/____Xor
                /      |                  /      |
               /      换位a              /      换位b
              /        |                /        |
             /      +SBox[40]          /      +SBox[41]
            /          |______________/___       |
           /                         /   |       |
          |            _____________|____|_______|
          |            |            |    |________
          |            |            |            |
    _____Sn0__________Sn1__________Sn2__________Sn3_____ 第二十轮循环的结果(循环结束)
          |                         |
       +SBox[42]                 +SBox[43]
          |                         |
    _____Sn0__________Sn1__________Sn2__________Sn3_____ 最终结果

    说明:

    F_En( )的处理过程分20轮循环完成。

    每一轮循环中都有换位,对上表中的换位做一个说明:

    换位a:就是将32位结果的前a位和后(32-a)位换位,a取每一轮中f(Sn3)的后五位

    换位b:就是将32位结果的前b位和后(32-b)位换位,b取每一轮中f(Sn1)的后五位

    ----------------------------------------------------------------------------------------------

    最后分析一下 F_En( ) 的逆过程:

    解密过程:

    _____Sn0__________Sn1__________Sn2__________Sn3_____
          |                         |
       -SBox[42]                 -SBox[43]
          |                         |
    _____Sn0__________Sn1__________Sn2__________Sn3_____ 简单处理后进入循环(循环开始)
          | \          |____________|_\________  |
          |  \         _____________|__\______|__|
          |   \        |            |   \     |___
          |    \       |            |    \       |
        f( )    \   -SBox[40]     f( )    \   -SBox[41]
          |     |      |            |     |      |
          |     |     换位c         |     |     换位d
          |     |      |            |     |      |
         XOR____|______|           XOR____|______|
          |     |_______            |     |_______
          |            |            |            |
    _____Sn0__________Sn1__________Sn2__________Sn3_____ 第一轮循环的结果
          | \          |____________|_\________  |
          |  \         _____________|__\______|__|
          |   \        |            |   \     |___
          |    \       |            |    \       |
        f( )    \   -SBox[38]     f( )    \   -SBox[39]
          |     |      |            |     |      |
          |     |     换位c         |     |     换位d
          |     |      |            |     |      |
         XOR____|______|           XOR____|______|
          |     |_______            |     |_______
          |            |            |            |
    _____Sn0__________Sn1__________Sn2__________Sn3_____ 第二轮循环的结果

    ……………………………………………………………………

    _____Sn0__________Sn1__________Sn2__________Sn3_____ 第十九轮循环的结果
          | \          |____________|_\________  |
          |  \         _____________|__\______|__|
          |   \        |            |   \     |___
          |    \       |            |    \       |
        f( )    \   -SBox[2]      f( )    \   -SBox[3]
          |     |      |            |     |      |
          |     |     换位c         |     |     换位d
          |     |      |            |     |      |
         XOR____|______|           XOR____|______|
          |     |_______            |     |_______
          |            |            |            |
    _____Sn0__________Sn1__________Sn2__________Sn3_____ 第二十轮循环的结果
                       |                         |
                    -SBox[0]                  -SBox[1]
                       |                         |
    _____Sn0__________Sn1__________Sn2__________Sn3_____ 最终结果

    F_De( )也分20轮循环完成:

    每一轮循环中都有换位,对上表中的换位做一个说明:

    换位c:就是将32位结果的前c位和后(32-c)位换位,a取每一轮中f(Sn2)的后五位

    换位d:就是将32位结果的前d位和后(32-d)位换位,b取每一轮中f(Sn0)的后五位

    ----------------------------------------------------------------------------------------------
    【注册机源码】

    Microsoft Visual C++ 6.0 编写的MFC,变量的命名跟上面注释相同,不过代码写得太烂了,大家不要笑我。

    /////////////////////////////////////////////////////////////////
    //
    //  FileName        :   CrackMe1_qxtianlongDlg.cpp
    //  Author        :   rdsnow[BCG][PYG][D.4s]
    //  Date        :   2005-10-25
    //  Comment        :   KeyGen for crackme1 by qxtianlong(关键代码)
    //
    /////////////////////////////////////////////////////////////////

    void CCrackMe1_qxtianlongDlg::OnOK()
    {
            // TODO: Add extra validation here
           
            //CDialog::OnOK();

            DWORD Sn0,Sn1,Sn2,Sn3;
            unsigned char inbuff[512],outbuff[16];
            int i;
           
            UpdateData(true);
           
            //对UseName进行MD5编码,这里使用不同的MD5类,代码也不相同
            i=m_Edit1.GetLength ();
            memcpy(inbuff,m_Edit1,i+1);
            MD5_CTX context;
            context.MD5Update (inbuff,i);
            context.MD5Final (outbuff);

            //将MD5的结果分成四个DWORD
            Sn0=outbuff[0]+(outbuff[1]<<8)+(outbuff[2]<<16)+(outbuff[3]<<24);
            Sn1=outbuff[4]+(outbuff[5]<<8)+(outbuff[6]<<16)+(outbuff[7]<<24);
            Sn2=outbuff[8]+(outbuff[9]<<8)+(outbuff[10]<<16)+(outbuff[11]<<24);
            Sn3=outbuff[12]+(outbuff[13]<<8)+(outbuff[14]<<16)+(outbuff[15]<<24);

            //用四个分组解密
            m_Edit2=F_De(Sn0,Sn1,Sn2,Sn3);
           
            //输出结果
            UpdateData(false);       
           
    }


    DWORD CCrackMe1_qxtianlongDlg::Exchange(DWORD Sn, int i)
    {       
            //将32位的Sn的前i位和后(32-i)位交换

            DWORD TempData=Sn;
            Sn=Sn << i;
            i=32-i;
            TempData=TempData>>i;
            Sn |=TempData;

            return Sn;
    }

    DWORD CCrackMe1_qxtianlongDlg::Function1(DWORD Sn)
    {
            //算法中用到的一个函数,即f( )

            //Sn=(Sn×2+1)×Sn,然后交换结果的前5位和后27位

            Sn=(Sn*2+1)*Sn;
            Sn=Exchange(Sn,5);

            return Sn;
    }

    CString CCrackMe1_qxtianlongDlg::F_De(DWORD Sn0, DWORD Sn1, DWORD Sn2, DWORD Sn3)
    {

            //解密函数

            CString Code="",TempChar;

            //因为作者使用的是固定的key,所以偶偷懒
            //直接将SBox[44]复制过来了,省掉SBox初始化编程

            DWORD SBox[44]={
                    0x63D4757A , 0xEE7A3CB4 , 0x6D00027A , 0x8831B70F,
                    0x7728D975 , 0xE7BA4156 , 0xDC92BFAD , 0xCB17967B,
                    0x1F8B0D7A , 0x8E0B0D4F , 0x431C9651 , 0x22293C7F,
                    0x0D243845 , 0xC23C7BA6 , 0x4CAD232E , 0xB35D36FF,
                    0x551BC015 , 0x0BF3CF67 , 0xDDAF2D46 , 0xA72AA80D,
                    0xEC1C33D4 , 0x896B736B , 0x189D7F20 , 0xE46D20BE,
                    0xC4DDD5CC , 0x3DBBA1A7 , 0x8A692DB8 , 0xEEB598C4,
                    0x0AA88B0C , 0xF506A11A , 0xADC68F57 , 0x1739E928,
                    0x577803DA , 0x958F416A , 0xDF1C7CA7 , 0x0BBAD3FE,
                    0xAB6DB39C , 0xB8048075 , 0x92628ABB , 0x5CEB9507,
                    0x64CCA67C , 0xD00B10A6 , 0xD4181073 , 0x9E147749
            };
           
            DWORD TempData1,TempData2;
            int i;

            Sn0-=SBox[42];
            Sn2-=SBox[43];

            for (i=0;i<20;i++){

                    TempData1=Sn0;
                    TempData2=Sn2;

                    Sn0=Function1(Sn0);
                    Sn2=Function1(Sn2);

                    Sn1-=SBox[41-2*i];
                    Sn3-=SBox[40-2*i];

                    Sn3=Exchange(Sn3,32-(Sn2 & 0x1F));
                    Sn1=Exchange(Sn1,32-(Sn0 & 0x1F));

                    Sn0 ^= Sn3;
                    Sn2 ^= Sn1;

                    Sn1=TempData1;
                    Sn3=TempData2;

            }
           
            Sn1-=SBox[0];
            Sn3-=SBox[1];

            TempChar.Format ("%02X%02X%02X%02X",Sn0&0xFF,Sn0>>8&0xFF,Sn0>>16&0xFF,Sn0>>24&0xFF);
            Code+=TempChar;
            TempChar.Format ("%02X%02X%02X%02X",Sn1&0xFF,Sn1>>8&0xFF,Sn1>>16&0xFF,Sn1>>24&0xFF);
            Code+=TempChar;
            TempChar.Format ("%02X%02X%02X%02X",Sn2&0xFF,Sn2>>8&0xFF,Sn2>>16&0xFF,Sn2>>24&0xFF);
            Code+=TempChar;
            TempChar.Format ("%02X%02X%02X%02X",Sn3&0xFF,Sn3>>8&0xFF,Sn3>>16&0xFF,Sn3>>24&0xFF);
            Code+=TempChar;
           
            return Code;       

    }

    ----------------------------------------------------------------------------------------------
    【破解心得】

    这是个对称算法,加密和解密使用同一密钥,建议作者密钥跟机器码关联,不要使用固定的密钥。

    现在的软件更加倾向于使用强壳阻止程序不被调试,所以要向工作在脱壳第一线的大侠致敬,现在感觉到脱壳真是一件辛苦的事情。

    附件:

    Crackme1.exe --> crackme1 by qxtianlong

    keygen.exe --> 算法注册机

    Crackme1 by qxtianlong.txt --> 破文,如果由于流程图显示错位,看txt文档吧!

    ----------------------------------------------------------------------------------------------
    【破解声明】   我是一只小菜鸟,偶得一点心得,愿与大家分享:)

    【版权声明】   本文纯属技术交流, 转载请注明作者并保持文章的完整, 谢谢!
    ----------------------------------------------------------------------------------------------
                                                                         文章写于2005-10-25 22:56:34


    [ Last edited by rdsnow on 2005-10-26 at 08:20 AM ]

    Crackme1.rar

    138.78 KB, 下载次数: 30, 下载积分: 飘云币 -2 枚

    PYG19周年生日快乐!
  • TA的每日心情

    2024-4-11 22:10
  • 签到天数: 53 天

    [LV.5]常住居民I

     楼主| 发表于 2005-10-26 08:21:52 | 显示全部楼层
    qxtianlong 兄到这里做版主了,gxgx!!!
    PYG19周年生日快乐!

    该用户从未签到

    发表于 2005-10-26 11:10:15 | 显示全部楼层
    强,分析的这么透彻,一个Crackme1.0没有要关联机器码,当然在软件中肯定不会这么简单的,要加强壳的!!rdsnow!佩服佩服
    我这个斑竹是临时的!!不过谢谢了!!
    在职一天就做好自己的事!呵呵~
    PYG19周年生日快乐!
  • TA的每日心情
    开心
    前天 15:35
  • 签到天数: 1637 天

    [LV.Master]伴坛终老

    发表于 2005-10-26 19:54:48 | 显示全部楼层
    分析的真详细,学习。
    PYG19周年生日快乐!
  • TA的每日心情
    擦汗
    2017-9-28 11:05
  • 签到天数: 3 天

    [LV.2]偶尔看看I

    发表于 2005-11-2 13:33:17 | 显示全部楼层
    牛人啊~~~
    看的心里痒痒的~~~
    什么时候偶也能到达这个小平啊~~~
    PYG19周年生日快乐!
  • TA的每日心情

    2024-8-1 20:40
  • 签到天数: 8 天

    [LV.3]偶尔看看II

    发表于 2005-11-4 18:46:34 | 显示全部楼层
    详细……无语……
    PYG19周年生日快乐!

    该用户从未签到

    发表于 2005-11-5 10:47:45 | 显示全部楼层
    同意5楼的看法.....
    PYG19周年生日快乐!
    您需要登录后才可以回帖 登录 | 加入我们

    本版积分规则

    快速回复 返回顶部 返回列表