【破文作者】   rdsnow[BCG][PYG][D.4s]
【作者主页】   http://rdsnow.ys168.com
【 E-mail 】   rdsnow@163.com
【 作者QQ 】   83757177
【文章题目】   变形的 MD5
【软件名称】   AutoRunPro Enterprise
【软件版本】   V4.0.0.32
【下载地址】   http://www.longtion.com

----------------------------------------------------------------------------------------
【加密方式】   序列号
【破解工具】   ODbyDYK v1.10[05.09]
【软件限制】   功能限制
【破解平台】   Microsoft Windows XP Professional
【平台版本】   5.1.2600 Service Pack 2 内部版本号 2600

----------------------------------------------------------------------------------------
【软件简介】

AutoRun Pro Enterprise can create, edit professional autorun interface and generate autorun files for CD/DVDs in a WYSIWYG environment.
Display a professional and beautiful interface for users to open or execute files, print documents, send e-mail, visit Web sites, browse CDs, 

play sound, music and so on, when your CD is inserted. It's fast and easy to use. Anyone can quickly create autorun CD-ROMs within minutes.

【文章简介】

我编程只有5、6年前学习的一点 turbo c 的基础,为了学习编程,一般的程序都是尽可能的学出 keygen ,这下遇到了个采用变形 MD5 算法的软件,也来试了下。

给变形的 MD5 的程序要写出 keygen ,必须找到变形的地方,然后在标准 MD5 源码中作出相应的修改。

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

程序注册窗口要输入三个编辑框:username,serial 和 key,从后面代码看出 serial 的前四位必须是 "0018"

所以输入:
username= rdsnow[BCG][PYG][D.4s]
serial  = 001812345678cdef
key     = 9898989832323232

因为有注册码错误的对话框,所以很容易找到关键的地方。

00562BD2 .  8B83 14030000 MOV EAX,DWORD PTR [EBX+314]
00562BD8 .  E8 3F78F1FF   CALL AutoRunP.0047A41C         ;  取得 username
00562BDD .  8B45 E4       MOV EAX,DWORD PTR [EBP-1C]
00562BE0 .  8D55 FC       LEA EDX,DWORD PTR [EBP-4]
00562BE3 .  E8 8460EAFF   CALL AutoRunP.00408C6C
00562BE8 .  8D55 E0       LEA EDX,DWORD PTR [EBP-20]
00562BEB .  8B83 F8020000 MOV EAX,DWORD PTR [EBX+2F8]
00562BF1 .  E8 2678F1FF   CALL AutoRunP.0047A41C         ;  取得 serial
00562BF6 .  8B45 E0       MOV EAX,DWORD PTR [EBP-20]
00562BF9 .  8D55 F8       LEA EDX,DWORD PTR [EBP-8]
00562BFC .  E8 6B60EAFF   CALL AutoRunP.00408C6C
00562C01 .  8D55 DC       LEA EDX,DWORD PTR [EBP-24]
00562C04 .  8B83 FC020000 MOV EAX,DWORD PTR [EBX+2FC]
00562C0A .  E8 0D78F1FF   CALL AutoRunP.0047A41C         ;  取得 key
00562C0F .  8B45 DC       MOV EAX,DWORD PTR [EBP-24]
00562C12 .  8D55 F4       LEA EDX,DWORD PTR [EBP-C]
00562C15 .  E8 5260EAFF   CALL AutoRunP.00408C6C
00562C1A .  8B45 F4       MOV EAX,DWORD PTR [EBP-C]
00562C1D .  50            PUSH EAX                       ;  压入 key
00562C1E .  A1 709E5600   MOV EAX,DWORD PTR [569E70]
00562C23 .  8B00          MOV EAX,DWORD PTR [EAX]
00562C25 .  8B4D F8       MOV ECX,DWORD PTR [EBP-8]      ;  serial
00562C28 .  8B55 FC       MOV EDX,DWORD PTR [EBP-4]      ;  username
00562C2B .  E8 5466FFFF   CALL AutoRunP.00559284         ;  关键 CALL
00562C30 .  84C0          TEST AL,AL
00562C32 .  75 1D         JNZ SHORT AutoRunP.00562C51    ;  关键跳转
00562C34 .  6A 10         PUSH 10
00562C36 .  B9 602D5600   MOV ECX,AutoRunP.00562D60      ;  ASCII "Register"
00562C3B .  BA 6C2D5600   MOV EDX,AutoRunP.00562D6C      ;  ASCII "Incomplete or incorrect information."
00562C40 .  A1 5CA15600   MOV EAX,DWORD PTR [56A15C]
00562C45 .  8B00          MOV EAX,DWORD PTR [EAX]
00562C47 .  E8 788DF3FF   CALL AutoRunP.0049B9C4         ;  错误的对话框
00562C4C .  E9 C8000000   JMP AutoRunP.00562D19
00562C51 >  33C0          XOR EAX,EAX

如果是爆破,不建议在 00562C32 关键跳转处改跳转,应该跟进关键 CALL , 修改注册标志

----------------------------------------------------------------------------------------
下面就跟进吧:

005592F5 .  8B45 E4       MOV EAX,DWORD PTR [EBP-1C]
005592F8 .  E8 F7B3EAFF   CALL AutoRunP.004046F4         ;  取 Serial 的长度
005592FD .  8BD8          MOV EBX,EAX
005592FF .  83FB 01       CMP EBX,1
00559302 .  7C 1E         JL SHORT AutoRunP.00559322     ;  Serial 为空就跳走
00559304 >  8B45 E4       MOV EAX,DWORD PTR [EBP-1C]
00559307 .  807C18 FF 20  CMP BYTE PTR [EAX+EBX-1],20
0055930C .  75 0F         JNZ SHORT AutoRunP.0055931D
0055930E .  8D45 E4       LEA EAX,DWORD PTR [EBP-1C]
00559311 .  B9 01000000   MOV ECX,1
00559316 .  8BD3          MOV EDX,EBX
00559318 .  E8 77B6EAFF   CALL AutoRunP.00404994         ;  去掉 Serial 中的空格
0055931D >  4B            DEC EBX
0055931E .  85DB          TEST EBX,EBX
00559320 .^ 75 E2         JNZ SHORT AutoRunP.00559304
00559322 >  8B45 E0       MOV EAX,DWORD PTR [EBP-20]
00559325 .  E8 CAB3EAFF   CALL AutoRunP.004046F4         ;  取 key 的长度
0055932A .  8BD8          MOV EBX,EAX
0055932C .  83FB 01       CMP EBX,1
0055932F .  7C 1E         JL SHORT AutoRunP.0055934F     ;  key 为空就跳走
00559331 >  8B45 E0       MOV EAX,DWORD PTR [EBP-20]
00559334 .  807C18 FF 20  CMP BYTE PTR [EAX+EBX-1],20
00559339 .  75 0F         JNZ SHORT AutoRunP.0055934A
0055933B .  8D45 E0       LEA EAX,DWORD PTR [EBP-20]
0055933E .  B9 01000000   MOV ECX,1
00559343 .  8BD3          MOV EDX,EBX
00559345 .  E8 4AB6EAFF   CALL AutoRunP.00404994         ;  去掉 key 中的空格
0055934A >  4B            DEC EBX
0055934B .  85DB          TEST EBX,EBX
0055934D .^ 75 E2         JNZ SHORT AutoRunP.00559331
0055934F >  8B45 E4       MOV EAX,DWORD PTR [EBP-1C]
00559352 .  E8 9DB3EAFF   CALL AutoRunP.004046F4         ;  取 Serial 的长度
00559357 .  83F8 10       CMP EAX,10
0055935A .  0F85 98010000 JNZ AutoRunP.005594F8          ;  Serial 的长度不等于 16 就跳走
00559360 .  8B45 E0       MOV EAX,DWORD PTR [EBP-20]
00559363 .  E8 8CB3EAFF   CALL AutoRunP.004046F4         ;  取 key 的长度
00559368 .  83F8 10       CMP EAX,10
0055936B .  0F85 87010000 JNZ AutoRunP.005594F8          ;  key 的长度不等于 16 就跳走
00559371 .  33C0          XOR EAX,EAX
00559373 .  55            PUSH EBP
00559374 .  68 4B945500   PUSH AutoRunP.0055944B
00559379 .  64:FF30       PUSH DWORD PTR FS:[EAX]
0055937C .  64:8920       MOV DWORD PTR FS:[EAX],ESP
0055937F .  8D45 D4       LEA EAX,DWORD PTR [EBP-2C]
00559382 .  50            PUSH EAX
00559383 .  B9 08000000   MOV ECX,8
00559388 .  BA 01000000   MOV EDX,1
0055938D .  8B45 E4       MOV EAX,DWORD PTR [EBP-1C]
00559390 .  E8 BFB5EAFF   CALL AutoRunP.00404954         ;  取 Serial 的前 8 个字符
00559395 .  8B4D D4       MOV ECX,DWORD PTR [EBP-2C]
00559398 .  8D45 D8       LEA EAX,DWORD PTR [EBP-28]
0055939B .  BA 3C955500   MOV EDX,AutoRunP.0055953C
005593A0 .  E8 9BB3EAFF   CALL AutoRunP.00404740         ;  准备转换
005593A5 .  8B45 D8       MOV EAX,DWORD PTR [EBP-28]
005593A8 .  E8 63FCEAFF   CALL AutoRunP.00409010         ;  将 8 个字符组成的 Hex 文本转为数值 a
005593AD .  8945 F8       MOV DWORD PTR [EBP-8],EAX      ;  保存 a 进 inbuff
005593B0 .  8D45 CC       LEA EAX,DWORD PTR [EBP-34]
005593B3 .  50            PUSH EAX
005593B4 .  B9 08000000   MOV ECX,8
005593B9 .  BA 09000000   MOV EDX,9
005593BE .  8B45 E4       MOV EAX,DWORD PTR [EBP-1C]
005593C1 .  E8 8EB5EAFF   CALL AutoRunP.00404954         ;  取 Serial 的后 8 个字符
005593C6 .  8B4D CC       MOV ECX,DWORD PTR [EBP-34]
005593C9 .  8D45 D0       LEA EAX,DWORD PTR [EBP-30]
005593CC .  BA 3C955500   MOV EDX,AutoRunP.0055953C
005593D1 .  E8 6AB3EAFF   CALL AutoRunP.00404740         ;  准备转换
005593D6 .  8B45 D0       MOV EAX,DWORD PTR [EBP-30]
005593D9 .  E8 32FCEAFF   CALL AutoRunP.00409010         ;  将 8 个字符组成的 Hex 文本转为数值 b
005593DE .  8945 F4       MOV DWORD PTR [EBP-C],EAX      ;  保存 b 进入 inbuff
005593E1 .  8D45 C4       LEA EAX,DWORD PTR [EBP-3C]
005593E4 .  50            PUSH EAX
005593E5 .  B9 08000000   MOV ECX,8
005593EA .  BA 01000000   MOV EDX,1
005593EF .  8B45 E0       MOV EAX,DWORD PTR [EBP-20]
005593F2 .  E8 5DB5EAFF   CALL AutoRunP.00404954         ;  取 key 的前 8 个字符
005593F7 .  8B4D C4       MOV ECX,DWORD PTR [EBP-3C]
005593FA .  8D45 C8       LEA EAX,DWORD PTR [EBP-38]
005593FD .  BA 3C955500   MOV EDX,AutoRunP.0055953C
00559402 .  E8 39B3EAFF   CALL AutoRunP.00404740         ;  准备转换
00559407 .  8B45 C8       MOV EAX,DWORD PTR [EBP-38]
0055940A .  E8 01FCEAFF   CALL AutoRunP.00409010         ;  将 8 个字符组成的 Hex 文本转为数值 c
0055940F .  8BD8          MOV EBX,EAX                    ;  c 保存到 EBX
00559411 .  8D45 BC       LEA EAX,DWORD PTR [EBP-44]
00559414 .  50            PUSH EAX
00559415 .  B9 08000000   MOV ECX,8
0055941A .  BA 09000000   MOV EDX,9
0055941F .  8B45 E0       MOV EAX,DWORD PTR [EBP-20]
00559422 .  E8 2DB5EAFF   CALL AutoRunP.00404954         ;  取 key 的后 8 个字符
00559427 .  8B4D BC       MOV ECX,DWORD PTR [EBP-44]
0055942A .  8D45 C0       LEA EAX,DWORD PTR [EBP-40]
0055942D .  BA 3C955500   MOV EDX,AutoRunP.0055953C
00559432 .  E8 09B3EAFF   CALL AutoRunP.00404740         ;  准备转换
00559437 .  8B45 C0       MOV EAX,DWORD PTR [EBP-40]
0055943A .  E8 D1FBEAFF   CALL AutoRunP.00409010         ;  将 8 个字符组成的 Hex 文本转为数值 d
0055943F .  8BF0          MOV ESI,EAX                    ;  d 保存到 ESI
00559441 .  33C0          XOR EAX,EAX
00559443 .  5A            POP EDX
00559444 .  59            POP ECX
00559445 .  59            POP ECX
00559446 .  64:8910       MOV DWORD PTR FS:[EAX],EDX
00559449 .  EB 14         JMP SHORT AutoRunP.0055945F
0055944B .^ E9 90A6EAFF   JMP AutoRunP.00403AE0
00559450 .  E8 F3A9EAFF   CALL AutoRunP.00403E48
00559455 .  E9 9E000000   JMP AutoRunP.005594F8
0055945A .  E8 E9A9EAFF   CALL AutoRunP.00403E48
0055945F >  8B45 F4       MOV EAX,DWORD PTR [EBP-C]      ;  取出 b
00559462 .  83E0 0F       AND EAX,0F                     ;  取 b 的低 4 位
00559465 .  8945 DC       MOV DWORD PTR [EBP-24],EAX     ;  保存,他会作为其中一个注册标志,不要等于0
00559468 .  8B45 F8       MOV EAX,DWORD PTR [EBP-8]      ;  取出 a
0055946B .  C1E8 10       SHR EAX,10                     ;  取 a 的高 16 位
0055946E .  66:83F8 18    CMP AX,18
00559472 .  0F85 80000000 JNZ AutoRunP.005594F8          ;  a 的高 16 位不等于 0x18 就跳
00559478 .  8B45 F8       MOV EAX,DWORD PTR [EBP-8]      ;  取 a
0055947B .  8945 F0       MOV DWORD PTR [EBP-10],EAX     ;  保存 a 进 inbuff
0055947E .  8B45 F4       MOV EAX,DWORD PTR [EBP-C]      ;  取 b
00559481 .  8945 EC       MOV DWORD PTR [EBP-14],EAX     ;  保存 b 进 inbuff
00559484 .  8B45 F8       MOV EAX,DWORD PTR [EBP-8]      ;  取 a
00559487 .  25 FFFF0000   AND EAX,0FFFF                  ;  取 a 的低  16 位
0055948C .  8BF8          MOV EDI,EAX
0055948E .  C1E7 10       SHL EDI,10                     ;  放在 32 位数据的高 16 位
00559491 .  8B45 F4       MOV EAX,DWORD PTR [EBP-C]      ;  取 b 的高 16 位
00559494 .  C1E8 10       SHR EAX,10                     ;  放在 32 位数据的低 16 位
00559497 .  03F8          ADD EDI,EAX                    ;  a 的高 16 位 和 b 的低 16 位拼成一个 32 位数值
00559499 .  8D45 EC       LEA EAX,DWORD PTR [EBP-14]
0055949C .  50            PUSH EAX                       ;  此时 inbuff 在内存中显示成 b a b a
0055949D .  8D4D F0       LEA ECX,DWORD PTR [EBP-10]
005594A0 .  8D55 F4       LEA EDX,DWORD PTR [EBP-C]
005594A3 .  8D45 F8       LEA EAX,DWORD PTR [EBP-8]
005594A6 .  E8 295DFCFF   CALL AutoRunP.0051F1D4         ;  b a b a 组成的 128 位进行 MD5 编码
005594AB .  3B5D F8       CMP EBX,DWORD PTR [EBP-8]      ;  c 跟 MD5 结果的前 32 位比较
005594AE .  75 11         JNZ SHORT AutoRunP.005594C1
005594B0 .  3B75 F4       CMP ESI,DWORD PTR [EBP-C]      ;  d 跟 MD5 结果的 32 - 64 位比较
005594B3 .  75 0C         JNZ SHORT AutoRunP.005594C1    ;  即 key 跟 MD5 结果的前 64 位比较
005594B5 .  8B45 E8       MOV EAX,DWORD PTR [EBP-18]     ;  取 name
005594B8 .  E8 FF5BFCFF   CALL AutoRunP.0051F0BC         ;  计算 serial
005594BD .  3BF8          CMP EDI,EAX
005594BF .  74 04         JE SHORT AutoRunP.005594C5
005594C1 >  33C0          XOR EAX,EAX                    ;  = 0
005594C3 .  EB 02         JMP SHORT AutoRunP.005594C7
005594C5 >  B0 01         MOV AL,1                       ;  = 1
005594C7 >  8845 FF       MOV BYTE PTR [EBP-1],AL        ;  保存注册标志
005594CA .  807D FF 00    CMP BYTE PTR [EBP-1],0         ;  判断注册标志是不是 0
005594CE .  74 28         JE SHORT AutoRunP.005594F8
005594D0 .  837D DC 00    CMP DWORD PTR [EBP-24],0       ;  判断另外一个注册标志是不是 0
005594D4 .  75 0A         JNZ SHORT AutoRunP.005594E0

程序是这样判断的:serial 和 key 都是 16 个字符组成。

1、看 serial 的前 4 位是不是 "0018",serial 的最后一位不能是 '0'

2、将 serial 填充到 inbuff 中,注意,因为程序是用 dword 传送的,所以内存中低位在前,高位在后,我的 serial 在buff 中显示成:
   0012F104  EF CD 78 56 34 12 18 00 EF CD 78 56 34 12 18 00  锿xV4.锿xV4.
   
3、inbuff 中数据进行变形 MD5 编码,得到
   0012F104  E5 F9 0F 72 A3 46 9E 09 B2 5A AB E3 43 EE 3D 3F  妁r?瞆C??
   
4、这个结果从后面开始的 3F 3D EE 43 AB 5A B2 09 组成的字符串 "3F3DEE43AB5AB209" 是个符合要求的 key 是个符合要求的 serial,但是这个时候 serial 还没有

得到验证,所以用 serial 生成的 key 只能躲过第一次跳转。

5、程序把 serial 的验证放在最后。

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

大致跟了下 serial 的生成,前四位必须是 "0018" ,中间 8 个字符由 username 生成,最后四位任意。

跟进,在005594B8 CALL AutoRunP.0051F0BC 来到:

0051F0E6  |.  8B45 EC       MOV EAX,DWORD PTR [EBP-14]
0051F0E9  |.  E8 0656EEFF   CALL AutoRunP.004046F4         ;  取 name 的长度 Length
0051F0EE  |.  25 07000080   AND EAX,80000007               ;  长度 % 8 ,准备下面消息分组
0051F0F3  |.  79 05         JNS SHORT AutoRunP.0051F0FA
0051F0F5  |.  48            DEC EAX
0051F0F6  |.  83C8 F8       OR EAX,FFFFFFF8
0051F0F9  |.  40            INC EAX
0051F0FA  |>  BA 08000000   MOV EDX,8
0051F0FF  |.  2BD0          SUB EDX,EAX                    ;  8 - 余数 = 在用户名的后面添加 0 的个数
0051F101  |.  8BC2          MOV EAX,EDX
0051F103  |.  8BD8          MOV EBX,EAX
0051F105  |.  85DB          TEST EBX,EBX
0051F107  |.  7E 10         JLE SHORT AutoRunP.0051F119
0051F109  |>  8D45 EC       / LEA EAX,DWORD PTR [EBP-14]
0051F10C  |.  BA B0F15100   | MOV EDX,AutoRunP.0051F1B0
0051F111  |.  E8 E655EEFF   | CALL AutoRunP.004046FC        ;  在用户名信息后面添加 0
0051F116  |.  4B            | DEC EBX
0051F117  |.^ 75 F0         \ JNZ SHORT AutoRunP.0051F109

这个地方要小心的是即使用户名本身的长度是 8 的倍数,也会在后面加上 8 个0,不是 8 的倍数,正好通过补 0 ,补 0 后的用户名的长度应该是 8 的倍数。

0051F119  |>  8B45 EC       MOV EAX,DWORD PTR [EBP-14]
0051F11C  |.  E8 D355EEFF   CALL AutoRunP.004046F4
0051F121  |.  33D2          XOR EDX,EDX
0051F123  |.  8955 FC       MOV DWORD PTR [EBP-4],EDX
0051F126  |.  33D2          XOR EDX,EDX
0051F128  |.  8955 F8       MOV DWORD PTR [EBP-8],EDX
0051F12B  |.  8BD8          MOV EBX,EAX
0051F12D  |.  85DB          TEST EBX,EBX
0051F12F  |.  79 03         JNS SHORT AutoRunP.0051F134
0051F131  |.  83C3 07       ADD EBX,7
0051F134  |>  C1FB 03       SAR EBX,3
0051F137  |.  4B            DEC EBX
0051F138  |.  85DB          TEST EBX,EBX
0051F13A  |.  7C 3E         JL SHORT AutoRunP.0051F17A
0051F13C  |.  43            INC EBX
0051F13D  |.  33F6          XOR ESI,ESI
0051F13F  |>  8D45 E8       / LEA EAX,DWORD PTR [EBP-18]
0051F142  |.  50            | PUSH EAX
0051F143  |.  8BD6          | MOV EDX,ESI
0051F145  |.  C1E2 03       | SHL EDX,3
0051F148  |.  42            | INC EDX
0051F149  |.  B9 08000000   | MOV ECX,8
0051F14E  |.  8B45 EC       | MOV EAX,DWORD PTR [EBP-14]
0051F151  |.  E8 FE57EEFF   | CALL AutoRunP.00404954        ;  取出分组后的各组消息,每组 8 个字符
0051F156  |.  8B45 E8       | MOV EAX,DWORD PTR [EBP-18]
0051F159  |.  8D4D F0       | LEA ECX,DWORD PTR [EBP-10]
0051F15C  |.  8D55 F4       | LEA EDX,DWORD PTR [EBP-C]
0051F15F  |.  E8 D0FEFFFF   | CALL AutoRunP.0051F034        ;  将得到的 8 个字符顺序颠倒,并填入 inbuff 息的高64位
0051F164  |.  8D45 F0       | LEA EAX,DWORD PTR [EBP-10]
0051F167  |.  50            | PUSH EAX
0051F168  |.  8D4D F4       | LEA ECX,DWORD PTR [EBP-C]
0051F16B  |.  8D55 F8       | LEA EDX,DWORD PTR [EBP-8]
0051F16E  |.  8D45 FC       | LEA EAX,DWORD PTR [EBP-4]
0051F171  |.  E8 5E000000   | CALL AutoRunP.0051F1D4        ;  MD5( inbuff )
0051F176  |.  46            | INC ESI
0051F177  |.  4B            | DEC EBX
0051F178  |.^ 75 C5         \ JNZ SHORT AutoRunP.0051F13F
0051F17A  |>  8B5D FC       MOV EBX,DWORD PTR [EBP-4]
0051F17D  |.  33C0          XOR EAX,EAX

这里就是将 用户名添 0 后成 8 字节的倍数,然后分成 n 组,分别用每一组消息修改 inbuff 的前 8 个字节,然后进行 MD5 编码,循环 n 次。

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

要写出 keygen ,必须跟进 CALL AutoRunP.0051F034 ,跟进 MD5 函数

0051F1FF  |.  64:8920       MOV DWORD PTR FS:[EAX],ESP
0051F202  |.  C745 E4 6745> MOV DWORD PTR [EBP-1C],1234567 ;  传递四个链接变量(已经变形)
0051F209  |.  C745 E8 EFCD> MOV DWORD PTR [EBP-18],89ABCDE>
0051F210  |.  C745 EC DCFE> MOV DWORD PTR [EBP-14],BA98FED>
0051F217  |.  C745 F0 2143> MOV DWORD PTR [EBP-10],7650432>

★★★★★ 变形1 ★★★★★

这里已经不是:
A = 0x67452301
B = 0xefcdab89
C = 0x98badcfe
D = 0x10325476
找到一个变形

0051F21E  |.  8B45 F0       MOV EAX,DWORD PTR [EBP-10]
0051F221  |.  8903          MOV DWORD PTR [EBX],EAX        ;  复制四个链接变量的副本
0051F223  |.  8B45 EC       MOV EAX,DWORD PTR [EBP-14]
0051F226  |.  8906          MOV DWORD PTR [ESI],EAX        ;  复制四个链接变量的副本
0051F228  |.  8B45 E8       MOV EAX,DWORD PTR [EBP-18]
0051F22B  |.  8907          MOV DWORD PTR [EDI],EAX        ;  复制四个链接变量的副本
0051F22D  |.  8B45 E4       MOV EAX,DWORD PTR [EBP-1C]
0051F230  |.  8945 D4       MOV DWORD PTR [EBP-2C],EAX     ;  复制四个链接变量的副本
0051F233  |.  6A 10         PUSH 10
0051F235  |.  8D45 D0       LEA EAX,DWORD PTR [EBP-30]
0051F238  |.  B9 01000000   MOV ECX,1
0051F23D  |.  8B15 B4F15100 MOV EDX,DWORD PTR [51F1B4]     ;  AutoRunP.0051F1B8
0051F243  |.  E8 7465EEFF   CALL AutoRunP.004057BC
0051F248  |.  83C4 04       ADD ESP,4                      ;  下面将 128 位信息填充成 512 位
0051F24B  |.  8B45 FC       MOV EAX,DWORD PTR [EBP-4]
0051F24E  |.  8B00          MOV EAX,DWORD PTR [EAX]
0051F250  |.  8B55 D0       MOV EDX,DWORD PTR [EBP-30]
0051F253  |.  8902          MOV DWORD PTR [EDX],EAX        ;  填充
……………………(总共有16个填充)
0051F2EF  |.  8B45 FC       MOV EAX,DWORD PTR [EBP-4]
0051F2F2  |.  8B00          MOV EAX,DWORD PTR [EAX]
0051F2F4  |.  8B55 D0       MOV EDX,DWORD PTR [EBP-30]
0051F2F7  |.  8942 3C       MOV DWORD PTR [EDX+3C],EAX     ;  填充
0051F2FA  |.  8B45 D4       MOV EAX,DWORD PTR [EBP-2C]


★★★★★ 变形2 ★★★★★

和标准的 MD5 的填充不一样,并不是加个1在消息后然后填充0,最后附上消息长度

而是将消息分为四个 dword ,逆序、顺序、逆序、顺序填充成 512 位

比如消息是:
0012F104  31 32 33 34 35 36 37 38 39 30 41 42 43 44 45 46  1234 5678 90AB CDEF

填充后是:
0106CF74  43 44 45 46 39 30 41 42 35 36 37 38 31 32 33 34  CDEF 90AB 5678 1234
0106CF84  31 32 33 34 35 36 37 38 39 30 41 42 43 44 45 46  1234 5678 90AB CDEF
0106CF94  43 44 45 46 39 30 41 42 35 36 37 38 31 32 33 34  CDEF 90AB 5678 1234
0106CFA4  31 32 33 34 35 36 37 38 39 30 41 42 43 44 45 46  1234 5678 90AB CDEF

//------------- round 1 -------------//
0051F2FD  |.  50            PUSH EAX                       ; /Arg4
0051F2FE  |.  8B45 D0       MOV EAX,DWORD PTR [EBP-30]     ; |
0051F301  |.  8B00          MOV EAX,DWORD PTR [EAX]        ; |
0051F303  |.  50            PUSH EAX                       ; |Arg3
0051F304  |.  6A 07         PUSH 7                         ; |Arg2 = 00000007
0051F306  |.  68 78A46AD7   PUSH D76AA478                  ; |Arg1 = D76AA478
0051F30B  |.  8BC3          MOV EAX,EBX                    ; |
0051F30D  |.  8B0F          MOV ECX,DWORD PTR [EDI]        ; |
0051F30F  |.  8B16          MOV EDX,DWORD PTR [ESI]        ; |
0051F311  |.  E8 CE070000   CALL AutoRunP.0051FAE4         ; \AutoRunP.0051FAE4
0051F316  |.  8B07          MOV EAX,DWORD PTR [EDI]
……………………
0051F4C2  |.  8B17          MOV EDX,DWORD PTR [EDI]        ; |
0051F4C4  |.  E8 1B060000   CALL AutoRunP.0051FAE4         ; \AutoRunP.0051FAE4
0051F4C9  |.  8B45 D4       MOV EAX,DWORD PTR [EBP-2C]

//------------- round 2 -------------//
0051F4CC  |.  50            PUSH EAX                       ; /Arg4
0051F4CD  |.  8B45 D0       MOV EAX,DWORD PTR [EBP-30]     ; |
0051F4D0  |.  8B40 04       MOV EAX,DWORD PTR [EAX+4]      ; |
0051F4D3  |.  50            PUSH EAX                       ; |Arg3
0051F4D4  |.  6A 05         PUSH 5                         ; |Arg2 = 00000005
0051F4D6  |.  68 62251EF6   PUSH F61E2562                  ; |Arg1 = F61E2562
0051F4DB  |.  8BC3          MOV EAX,EBX                    ; |
0051F4DD  |.  8B0F          MOV ECX,DWORD PTR [EDI]        ; |
0051F4DF  |.  8B16          MOV EDX,DWORD PTR [ESI]        ; |
0051F4E1  |.  E8 3A060000   CALL AutoRunP.0051FB20         ; \AutoRunP.0051FB20
0051F4E6  |.  8B07          MOV EAX,DWORD PTR [EDI]
……………………
0051F691  |.  8B17          MOV EDX,DWORD PTR [EDI]        ; |
0051F693  |.  E8 88040000   CALL AutoRunP.0051FB20         ; \AutoRunP.0051FB20
0051F698  |.  8B45 D4       MOV EAX,DWORD PTR [EBP-2C]

//------------- round 3 -------------//
0051F69B  |.  50            PUSH EAX                       ; /Arg4
0051F69C  |.  8B45 D0       MOV EAX,DWORD PTR [EBP-30]     ; |
0051F69F  |.  8B40 14       MOV EAX,DWORD PTR [EAX+14]     ; |
0051F6A2  |.  50            PUSH EAX                       ; |Arg3
0051F6A3  |.  6A 04         PUSH 4                         ; |Arg2 = 00000004
0051F6A5  |.  68 4239FAFF   PUSH FFFA3942                  ; |Arg1 = FFFA3942
0051F6AA  |.  8BC3          MOV EAX,EBX                    ; |
0051F6AC  |.  8B0F          MOV ECX,DWORD PTR [EDI]        ; |
0051F6AE  |.  8B16          MOV EDX,DWORD PTR [ESI]        ; |
0051F6B0  |.  E8 A7040000   CALL AutoRunP.0051FB5C         ; \AutoRunP.0051FB5C
0051F6B5  |.  8B07          MOV EAX,DWORD PTR [EDI]
……………………
0051F860  |.  8B17          MOV EDX,DWORD PTR [EDI]        ; |
0051F862  |.  E8 F5020000   CALL AutoRunP.0051FB5C         ; \AutoRunP.0051FB5C
0051F867  |.  8B45 D4       MOV EAX,DWORD PTR [EBP-2C]

//------------- round 4 -------------//
0051F86A  |.  50            PUSH EAX                       ; /Arg4
0051F86B  |.  8B45 D0       MOV EAX,DWORD PTR [EBP-30]     ; |
0051F86E  |.  8B00          MOV EAX,DWORD PTR [EAX]        ; |
0051F870  |.  50            PUSH EAX                       ; |Arg3
0051F871  |.  6A 06         PUSH 6                         ; |Arg2 = 00000006
0051F873  |.  68 442229F4   PUSH F4292244                  ; |Arg1 = F4292244
0051F878  |.  8BC3          MOV EAX,EBX                    ; |
0051F87A  |.  8B0F          MOV ECX,DWORD PTR [EDI]        ; |
0051F87C  |.  8B16          MOV EDX,DWORD PTR [ESI]        ; |
0051F87E  |.  E8 15030000   CALL AutoRunP.0051FB98         ; \AutoRunP.0051FB98
0051F883  |.  8B07          MOV EAX,DWORD PTR [EDI]
……………………
0051FA2F  |.  8B17          MOV EDX,DWORD PTR [EDI]        ; |
0051FA31  |.  E8 62010000   CALL AutoRunP.0051FB98         ; \AutoRunP.0051FB98
0051FA36  |.  8B45 F0       MOV EAX,DWORD PTR [EBP-10]

0051FA39  |.  0303          ADD EAX,DWORD PTR [EBX]        ;  + d
0051FA3B  |.  8B55 FC       MOV EDX,DWORD PTR [EBP-4]
0051FA3E  |.  8902          MOV DWORD PTR [EDX],EAX        ;  save
0051FA40  |.  8B45 EC       MOV EAX,DWORD PTR [EBP-14]
0051FA43  |.  0306          ADD EAX,DWORD PTR [ESI]        ;  + c
0051FA45  |.  8B55 F8       MOV EDX,DWORD PTR [EBP-8]
0051FA48  |.  8902          MOV DWORD PTR [EDX],EAX        ;  save
0051FA4A  |.  8B45 E8       MOV EAX,DWORD PTR [EBP-18]
0051FA4D  |.  0307          ADD EAX,DWORD PTR [EDI]        ;  + b
0051FA4F  |.  8B55 F4       MOV EDX,DWORD PTR [EBP-C]
0051FA52  |.  8902          MOV DWORD PTR [EDX],EAX        ;  save
0051FA54  |.  8B45 E4       MOV EAX,DWORD PTR [EBP-1C]
0051FA57  |.  0345 D4       ADD EAX,DWORD PTR [EBP-2C]     ;  + a
0051FA5A  |.  8B55 08       MOV EDX,DWORD PTR [EBP+8]
0051FA5D  |.  8902          MOV DWORD PTR [EDX],EAX        ;  save

★★★★★ 变形3 ★★★★★

跟进后发现 HASH 函数本身没有变形,但是参与运算的链接变量的顺序变化了。

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

【破解心得】

要得到正确的 serial 和 key ,按照下面的流程:

先对用户名添 0 后分成 n 组,再反序,分别用每一组消息修改 inbuff 的前 8 个字节,然后进行 MD5 编码,循环 n 次后,结果的最后 32 位作为 dword 转为十六进制

文本作为 serial 的中间 8 个字符。

然后前面接上 "0018" ,后面接上长度是 4 的任意 16进制文本,总共 16 个字符作为 serial

将 serial 填入 inbuff 的高 64 位,同时也填入 低 64 位,MD5(inbuff)得到 key

这个 MD5 有三处变形,变形没有什么新意,还是老一套:
(1) 四个变量的变形
(2) 数据填充变形
(3) 参与 HASH 运算的变量的顺序变形,HASH 本身没有变形。

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

【注册机源码】

因为程序只对 128 位消息进行 MD5 编码,为了便于编辑,没有采用类,大家直接看吧。

// 响应 Generate 按钮
void CkeygenDlg::OnOK() 
{
        // TODO: Add extra validation here
        CkeygenDlg::OnChangeEdit1();
}

void CkeygenDlg::OnChangeEdit1() 
{
        // TODO: If this is a RICHEDIT control, the control will not
        // send this notification unless you override the CDialog::OnInitDialog()
        // function and call CRichEditCtrl().SetEventMask()
        // with the ENM_CHANGE flag ORed into the mask.
        
        // TODO: Add your control notification handler code here
                UpdateData(true);
        Beep(1000,50);
        char inbuff[16] = {0},name[12];
        unsigned long state[4];
        int i, n, namelen;

        //对用户名处理
        namelen = m_Edit1.GetLength ();
        n = namelen >> 3 ;
        for(i = 0;i<n;i++){
                strcpy(name,m_Edit1.Mid (i<<3,8))       //取用户名的8个字符
                strrev(name);                           //将8个字符顺序反转
                memcpy(inbuff,name,8);                  //复制到待加密信息的高64位
                MD5(inbuff,state);                      //MD5编码
                memcpy(inbuff,state,16);                //替换掉待加密信息
        }
        n = namelen & 7 ;                               //判断用户名有没有处理完毕
        strcpy(name,m_Edit1.Mid (i<<3,n));;             //取出剩余字符
        strrev(name);                                   //剩余字符顺序反转
        i = 8 - n ;                                     //计算补0的个数
        memset(inbuff,0,i);                             //将0填入待加密信息
        memcpy(inbuff+i,name,n);                        //将反转字符填入待加密信息
        MD5(inbuff,state);                              //MD5编码
        m_Edit2.Format ("%08X",state[3]);               //将 State[3] 转为16进制字符串作为 Serial 的一部分
        m_Edit2.Insert (0,"0018");                      //serial 前面插入"0018"
        n = rand ();
        sprintf(inbuff,"%04X",n);
        m_Edit2 += inbuff;                              //serial 的最后四位任意,并且传递给编辑框

        memcpy(inbuff,&n,2);
        memcpy(inbuff+2,state+3,4);
        inbuff[6] = char(0x18);
        inbuff[7] = char(0);
        memcpy(inbuff+8,inbuff,8);                      //serial 填充到 inbuff

        MD5(inbuff,state);                              //对 serial MD5编码
        sprintf(inbuff,"%08X",state[2]);
        m_Edit3.Format ("%08X",state[3]);               //取 state[2] 和 state[2] 作为 Code
        m_Edit3 += inbuff;                              //将 code 传递给编辑框
        UpdateData(false);
}

// 将 128 待加密信息填充成 512 位,即16个整数
void CkeygenDlg::FillBuff(unsigned long *buff,char *inbuff)
{
        int *from=(int *)inbuff;
        buff[3]=*from;  buff[2]=*(from+1);  buff[1]=*(from+2);  buff[0]=*(from+3);
        buff[4]=*from;  buff[5]=*(from+1);  buff[6]=*(from+2);  buff[7]=*(from+3);
        buff[11]=*from; buff[10]=*(from+1); buff[9]=*(from+2);  buff[8]=*(from+3);
        buff[12]=*from; buff[13]=*(from+1); buff[14]=*(from+2); buff[15]=*(from+3);
}

//四个函数定义1 FF
unsigned long CkeygenDlg::FF(unsigned long a, unsigned long b, unsigned long c, unsigned long d, unsigned long x, byte s, unsigned long ac)
{
        a = ((b & c)|((~b)&d)) + a + x + ac;
        a = (a<<s)|(a>>(32-s)) ;
        a += b;
        return a;
}

//四个函数定义2 GG
unsigned long CkeygenDlg::GG(unsigned long a, unsigned long b, unsigned long c, unsigned long d, unsigned long x, byte s, unsigned long ac)
{
        a = ((b&d)|(c&(~d))) + a + x + ac ;
        a = (a<<s)|(a>>(32-s)) ;
        a += b;
        return a;
}

//四个函数定义3 HH
unsigned long CkeygenDlg::HH(unsigned long a, unsigned long b, unsigned long c, unsigned long d, unsigned long x, byte s, unsigned long ac)
{
        a = (b^c^d) + a + x + ac ;
        a = (a<<s)|(a>>(32-s)) ;
        a += b;
        return a;
}

//四个函数定义4 II
unsigned long CkeygenDlg::II(unsigned long a, unsigned long b, unsigned long c, unsigned long d, unsigned long x, byte s, unsigned long ac)
{
        a = ( c^(b|(~d)) ) + a + x + ac ;
        a = (a<<s)|(a>>(32-s)) ;
        a += b;
        return a;
}

//MD5运算主函数 待加密信息保存在在inbuff中,结果保存在state[4]中
void CkeygenDlg::MD5(char *inbuff,unsigned long *state)
{
        unsigned long context[16];
        state[0]=0x1234567;
        state[1]=0x89ABCDEF;
        state[2]=0xBA98FEDC;
        state[3]=0x76504321;
        FillBuff(context,inbuff);
        //------------- round 1 -------------//
        state[3] = FF(state[3],state[2],state[1],state[0],context[0],7,0xd76aa478);  // -1
        state[0] = FF(state[0],state[3],state[2],state[1],context[1],12,0xe8c7b756); // -2
        state[1] = FF(state[1],state[0],state[3],state[2],context[2],17,0x242070db); // -3
        state[2] = FF(state[2],state[1],state[0],state[3],context[3],22,0xc1bdceee); // -4
        state[3] = FF(state[3],state[2],state[1],state[0],context[4],7,0xf57c0faf);  // -5
        state[0] = FF(state[0],state[3],state[2],state[1],context[5],12,0x4787c62a); // -6
        state[1] = FF(state[1],state[0],state[3],state[2],context[6],17,0xa8304613); // -7
        state[2] = FF(state[2],state[1],state[0],state[3],context[7],22,0xfd469501); // -8
        state[3] = FF(state[3],state[2],state[1],state[0],context[8],7,0x698098d8);  // -9
        state[0] = FF(state[0],state[3],state[2],state[1],context[9],12,0x8b44f7af); //-10
        state[1] = FF(state[1],state[0],state[3],state[2],context[10],17,0xffff5bb1);//-11
        state[2] = FF(state[2],state[1],state[0],state[3],context[11],22,0x895cd7be);//-12
        state[3] = FF(state[3],state[2],state[1],state[0],context[12],7,0x6b901122); //-13
        state[0] = FF(state[0],state[3],state[2],state[1],context[13],12,0xfd987193);//-14
        state[1] = FF(state[1],state[0],state[3],state[2],context[14],17,0xa679438e);//-15
        state[2] = FF(state[2],state[1],state[0],state[3],context[15],22,0x49b40821);//-16

        //------------- round 2 -------------//
        state[3] = GG(state[3],state[2],state[1],state[0],context[1],5,0xf61e2562);  //-17
        state[0] = GG(state[0],state[3],state[2],state[1],context[6],9,0xc040b340);  //-18
        state[1] = GG(state[1],state[0],state[3],state[2],context[11],14,0x265e5a51);//-19
        state[2] = GG(state[2],state[1],state[0],state[3],context[0],20,0xe9b6c7aa); //-20
        state[3] = GG(state[3],state[2],state[1],state[0],context[5],5,0xd62f105d);  //-21
        state[0] = GG(state[0],state[3],state[2],state[1],context[10],9,0x2441453);  //-22
        state[1] = GG(state[1],state[0],state[3],state[2],context[15],14,0xd8a1e681);//-23
        state[2] = GG(state[2],state[1],state[0],state[3],context[4],20,0xe7d3fbc8); //-24
        state[3] = GG(state[3],state[2],state[1],state[0],context[9],5,0x21e1cde6);  //-25
        state[0] = GG(state[0],state[3],state[2],state[1],context[14],9,0xc33707d6); //-26
        state[1] = GG(state[1],state[0],state[3],state[2],context[3],14,0xf4d50d87); //-27
        state[2] = GG(state[2],state[1],state[0],state[3],context[8],20,0x455a14ed); //-28
        state[3] = GG(state[3],state[2],state[1],state[0],context[13],5,0xa9e3e905); //-28
        state[0] = GG(state[0],state[3],state[2],state[1],context[2],9,0xfcefa3f8);  //-30
        state[1] = GG(state[1],state[0],state[3],state[2],context[7],14,0x676f02d9); //-31
        state[2] = GG(state[2],state[1],state[0],state[3],context[12],20,0x8d2a4c8a);//-32

        //------------- round 3 -------------//
        state[3] = HH(state[3],state[2],state[1],state[0],context[5],4,0xfffa3942);  //-33
        state[0] = HH(state[0],state[3],state[2],state[1],context[8],11,0x8771f681); //-34
        state[1] = HH(state[1],state[0],state[3],state[2],context[11],16,0x6d9d6122);//-35
        state[2] = HH(state[2],state[1],state[0],state[3],context[14],23,0xfde5380c);//-36
        state[3] = HH(state[3],state[2],state[1],state[0],context[1],4,0xa4beea44);  //-37
        state[0] = HH(state[0],state[3],state[2],state[1],context[4],11,0x4bdecfa9); //-38
        state[1] = HH(state[1],state[0],state[3],state[2],context[7],16,0xf6bb4b60); //-39
        state[2] = HH(state[2],state[1],state[0],state[3],context[10],23,0xbebfbc70);//-40
        state[3] = HH(state[3],state[2],state[1],state[0],context[13],4,0x289b7ec6); //-41
        state[0] = HH(state[0],state[3],state[2],state[1],context[0],11,0xeaa127fa); //-42
        state[1] = HH(state[1],state[0],state[3],state[2],context[3],16,0xd4ef3085); //-43
        state[2] = HH(state[2],state[1],state[0],state[3],context[6],23,0x4881d05);  //-44
        state[3] = HH(state[3],state[2],state[1],state[0],context[9],4,0xd9d4d039);  //-45
        state[0] = HH(state[0],state[3],state[2],state[1],context[12],11,0xe6db99e5);//-46
        state[1] = HH(state[1],state[0],state[3],state[2],context[15],16,0x1fa27cf8);//-47
        state[2] = HH(state[2],state[1],state[0],state[3],context[2],23,0xc4ac5665); //-48

        //------------- round 4 -------------//
        state[3] = II(state[3],state[2],state[1],state[0],context[0],6,0xf4292244);  //-49
        state[0] = II(state[0],state[3],state[2],state[1],context[7],10,0x432aff97); //-50
        state[1] = II(state[1],state[0],state[3],state[2],context[14],15,0xab9423a7);//-51
        state[2] = II(state[2],state[1],state[0],state[3],context[5],21,0xfc93a039); //-52
        state[3] = II(state[3],state[2],state[1],state[0],context[12],6,0x655b59c3); //-53
        state[0] = II(state[0],state[3],state[2],state[1],context[3],10,0x8f0ccc92); //-54
        state[1] = II(state[1],state[0],state[3],state[2],context[10],15,0xffeff47d);//-55
        state[2] = II(state[2],state[1],state[0],state[3],context[1],21,0x85845dd1); //-56
        state[3] = II(state[3],state[2],state[1],state[0],context[8],6,0x6fa87e4f);  //-57
        state[0] = II(state[0],state[3],state[2],state[1],context[15],10,0xfe2ce6e0);//-58
        state[1] = II(state[1],state[0],state[3],state[2],context[6],15,0xa3014314); //-59
        state[2] = II(state[2],state[1],state[0],state[3],context[13],21,0x4e0811a1);//-60
        state[3] = II(state[3],state[2],state[1],state[0],context[4],6,0xf7537e82);  //-61
        state[0] = II(state[0],state[3],state[2],state[1],context[11],10,0xbd3af235);//-62
        state[1] = II(state[1],state[0],state[3],state[2],context[2],15,0x2ad7d2bb); //-63
        state[2] = II(state[2],state[1],state[0],state[3],context[9],21,0xeb86d391); //-64

        state[0] += 0x1234567;
        state[1] += 0x89ABCDEF;
        state[2] += 0xBA98FEDC;
        state[3] += 0x76504321;
}

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

【版权声明】   本文纯属技术交流, 转载请注明作者并保持文章的完整, 谢谢! 
----------------------------------------------------------------------------------------
                                                                文章写于2006-1-21 18:10:17