goushibee 发表于 2014-8-5 11:36:37

WinCHM Pro v4.45 算法分析

本帖最后由 goushibee 于 2014-8-5 18:01 编辑

搜索字符串很快定位到下面位置,。。

00553FA3|.8B4D F0       mov ecx,dword ptr ss:
00553FA6|.BA AC405500   mov edx,winchm.005540AC                  ;RegCode
00553FAB|.8BC3          mov eax,ebx
00553FAD|.E8 3AE5EFFF   call winchm.004524EC
00553FB2|.8BC3          mov eax,ebx
00553FB4|.E8 270FEBFF   call winchm.00404EE0
00553FB9|.E8 D2F8FFFF   call winchm.00553890                     ;关键函数
00553FBE|.A1 E0F55C00   mov eax,dword ptr ds:
00553FC3|.8338 00       cmp dword ptr ds:,0x0
00553FC6|.74 57         je Xwinchm.0055401F
00553FC8|.8B0D E0F55C00 mov ecx,dword ptr ds:          ;winchm.005D5484
00553FCE|.8B09          mov ecx,dword ptr ds:
00553FD0|.8D45 FC       lea eax,dword ptr ss:
00553FD3|.BA C8405500   mov edx,winchm.005540C8                  ;Thank you for purchasing our product!\r\n\r\nLicense type:
00553FD8|.E8 0B32EBFF   call winchm.004071E8
00553FDD|.A1 FCF95C00   mov eax,dword ptr ds:[0x5CF9FC]       ;很明显这个全局变量要等于1才是 pro版本
00553FE2|.8338 01       cmp dword ptr ds:,0x1
00553FE5|.75 1C         jnz Xwinchm.00554003                  ;!!
00553FE7|.FF75 FC       push dword ptr ss:
00553FEA|.68 44415500   push winchm.00554144                     ;\r\n
00553FEF|.68 58415500   push winchm.00554158                     ;Version: WinCHM Pro
00553FF4|.8D45 FC       lea eax,dword ptr ss:
00553FF7|.BA 03000000   mov edx,0x3
00553FFC|.E8 CB32EBFF   call winchm.004072CC
00554001|.EB 29         jmp Xwinchm.0055402C
00554003|>FF75 FC       push dword ptr ss:
00554006|.68 44415500   push winchm.00554144                     ;\r\n
0055400B|.68 8C415500   push winchm.0055418C                     ;Version: WinCHM (Standard)


关键函数call winchm.00553890 中:
0055399E   .8B00          mov eax,dword ptr ds:
005539A0   .E8 77F6FFFF call winchm.0055301C                   ;返回值要等于270e +1pro版本
005539A5   .8BD8          mov ebx,eax
005539A7   .8BC3          mov eax,ebx
005539A9   .83E8 01       sub eax,0x1                              ;
005539AC   .72 0B         jb Xwinchm.005539B9
005539AE   .74 17         je Xwinchm.005539C7
005539B0   .2D 0E270000   sub eax,0x270E                           ;这里可以看到eax要等于0x270E 之前eax已经-1了
005539B5   .74 21         je Xwinchm.005539D8                      ; // 跳到Unlimited-user
005539B7   .EB 30         jmp Xwinchm.005539E9
005539B9   >A1 E0F55C00   mov eax,dword ptr ds:          ;
005539BE   .33D2          xor edx,edx
005539C0   .E8 6733EBFF   call winchm.00406D2C
005539C5   .EB 3E         jmp Xwinchm.00553A05
005539C7   >A1 E0F55C00   mov eax,dword ptr ds:          ;
005539CC   .BA 9C3A5500   mov edx,winchm.00553A9C                  ;Single-user License
005539D1   .E8 5633EBFF   call winchm.00406D2C
005539D6   .EB 2D         jmp Xwinchm.00553A05
005539D8   >A1 E0F55C00   mov eax,dword ptr ds:          ;
005539DD   .BA D03A5500   mov edx,winchm.00553AD0                  ;Unlimited-user License
005539E2   .E8 4533EBFF   call winchm.00406D2C
005539E7   .EB 1C         jmp Xwinchm.00553A05


关键计算位置call winchm.0055301C

刚进入函数
00553090|.C700 FFFFFFFF mov dword ptr ds:,-0x1
00553096|.8B45 F4       mov eax,dword ptr ss:
00553099|.E8 FEF6FFFF   call winchm.0055279C                     ;serial*n 求和   结果要等于2BD2
0055309E|.8945 D8       mov dword ptr ss:,eax
005530A1|.8955 DC       mov dword ptr ss:,edx
……
00553159      817D D8 D22B0>cmp dword ptr ss:,0x2BD2       ;所以值要等于0x2BD2
00553160|.75 0A         jnz Xwinchm.0055316C
00553162|.BB 0F270000   mov ebx,0x270F                           ;上一层call已经知道要返回0x270F
00553167|.E9 EE040000   jmp winchm.0055365A                      ;!!
0055316C|>A1 FCF95C00   mov eax,dword ptr ds:         
00553171|.C700 FFFFFFFF mov dword ptr ds:,-0x1            ;可以看到直接给这个全局赋值了-1
所以这里得到的码也不是Pro版本。。。。继续向下看


00553177|.83FB 14       cmp ebx,0x14                           ;Switch (cases 14..22)
0055317A|.0F85 09010000 jnz winchm.00553289                      ;注册码长度0x14的话
00553180|.A1 FCF95C00   mov eax,dword ptr ds:          ;Case 14 of switch 00553177
00553185|.33D2          xor edx,edx
00553187|.8910          mov dword ptr ds:,edx
00553189|.8B45 F4       mov eax,dword ptr ss:
0055318C|.E8 9FFDFFFF   call winchm.00552F30                     ;结果要 7ED2A128
00553191|.8945 D8       mov dword ptr ss:,eax
……
00553264|.817D D8 28A1D>cmp dword ptr ss:,0x7ED2A128
0055326B|.75 0A         jnz Xwinchm.00553277
0055326D|.BB 0F270000   mov ebx,0x270F                           ;!!
00553272|.E9 E3030000   jmp winchm.0055365A
00553277|>33DB          xor ebx,ebx
00553279|.A1 FCF95C00   mov eax,dword ptr ds:
0055327E|.C700 FFFFFFFF mov dword ptr ds:,-0x1               ; 可以看到全局变量还是给了-1
00553284|.E9 D1030000   jmp winchm.0055365A
这里也不是Pro版本 。。。 继续


密码长度为0x19情况下
005532B9|.E8 7EB5EBFF   call winchm.0040E83C                     ;0x16位开始取4位
005532BE|.8B45 EC       mov eax,dword ptr ss:
005532C1|.E8 6AFCFFFF   call winchm.00552F30                     ;可以看到结果要等于 2797
005532C6|.83FA 00       cmp edx,0x0
005532C9|.75 14         jnz Xwinchm.005532DF
005532CB|.3D 97270000   cmp eax,0x2797                            ; // !!
005532D0|.75 0D         jnz Xwinchm.005532DF
005532D2|.A1 FCF95C00   mov eax,dword ptr ds:[0x5CF9FC]
005532D7|.C700 01000000 mov dword ptr ds:,0x1               ;赋值1
005532DD|.EB 09         jmp Xwinchm.005532E8
005532DF|>A1 FCF95C00   mov eax,dword ptr ds:
005532E4|.33D2          xor edx,edx                              ;赋值0
005532E6|.8910          mov dword ptr ds:,edx
……
00553292|.8D45 F0       lea eax,dword ptr ss:          ;Case 19 of switch 00553177
00553295|.50            push eax
00553296|.B9 14000000   mov ecx,0x14
0055329B|.BA 01000000   mov edx,0x1
005532A0|.8B45 F4       mov eax,dword ptr ss:
005532A3|.E8 94B5EBFF   call winchm.0040E83C                     ;0x1开始取14位
。。。。
005532E8|> \8B45 F0       mov eax,dword ptr ss:
005532EB|.E8 40FCFFFF   call winchm.00552F30                     ; 高32位267低32位7ED2A128
005532F0|.8945 D8       mov dword ptr ss:,eax
……
005533BA|> \817D DC 67020>cmp dword ptr ss:,0x267
005533C1|.75 13         jnz Xwinchm.005533D6
005533C3|.817D D8 28A1D>cmp dword ptr ss:,0x7ED2A128
005533CA|.75 0A         jnz Xwinchm.005533D6
005533CC|.BB 0F270000   mov ebx,0x270F                           ;!!


调用都是同一个函数。。call winchm.00552F30 。。
00552F9E|> /68 00400000   /push 0x4000
00552FA3|. |68 3D0AD7D3   |push 0xD3D70A3D
00552FA8|. |68 0AD7A370   |push 0x70A3D70A                            ;=3.3099999999999999990
00552FAD|. |895D DC       |mov dword ptr ss:,ebx
00552FB0|. |DB45 DC       |fild dword ptr ss:               ;将整数转化为长双精FP80压栈
00552FB3|. |83C4 F4       |add esp,-0xC
00552FB6|. |DB3C24      |fstp tbyte ptr ss:                  ;fstp是将弹栈指令,将st0弹出
00552FB9|. |9B            |wait
00552FBA|. |E8 1DB2EBFF   |call winchm.0040E1DC                     ;f(n) =3.3099999999999999990 ^n
00552FBF|. |8B45 F8       |mov eax,dword ptr ss:
00552FC2|. |0FB74458 FE   |movzx eax,word ptr ds:
00552FC7|. |0FB7C0      |movzx eax,ax
00552FCA|. |8945 DC       |mov dword ptr ss:,eax
00552FCD|. |DB45 DC       |fild dword ptr ss:
00552FD0|. |DEC9          |fmulp st(1),st                           ;f(n)* 每个码的ascii值
00552FD2|. |DB6D E0       |fld tbyte ptr ss:
00552FD5|. |DEC1          |faddp st(1),st                            ; 求和
00552FD7|. |DB7D E0       |fstp tbyte ptr ss:
00552FDA|. |9B            |wait
00552FDB|. |43            |inc ebx
00552FDC|. |4E            |dec esi
00552FDD|.^\75 BF         \jnz Xwinchm.00552F9E
00552FDF|>DB6D E0       fld tbyte ptr ss:
00552FE2      E8 ED16EBFF   call winchm.004046D4                        ;取整数部分
00552FE7      8945 F0       mov dword ptr ss:,eax             ;低32位
00552FEA|.8955 F4       mov dword ptr ss:,edx            ;高32位



第一次看浮点运算。。还好比较简单
      call winchm.0040E1DC中
      0040E212      DB6D 14       fld tbyte ptr ss:      ;=3.3099999999999999990
      0040E215|.EB 02         jmp Xwinchm.0040E219
      0040E217|>D8C8          /fmul st,st
      0040E219|>D1E8         shr eax,1                         ;eax 是传进来的n
      0040E21B|.^ 73 FA         |jnb Xwinchm.0040E217            ;这里就是进行3.3099999999999999990 n次方
      0040E21D|.DCC9          |fmul st(1),st
      0040E21F|.^ 75 F6         \jnz Xwinchm.0040E217


后面还有注册码为0x1D、0x22、0x18的情况。。用到的函数都一样的 不分析了。。。

总结下:
    密码长度为25位时候要求:
    1.注册码的最后4位的计算结果要等于0x 2797
    2.注册码前20位的计算结果要等于0x2677ED2A128

用户名不参与验证,随便填
最后提供一组可用的注册码:TKYZ0001021012603ZOHXIGB8


l0v3cr4ck 发表于 2014-8-5 13:33:58

感谢分享,学习一下。

冷月孤心 发表于 2014-8-5 14:04:04

评不了分,只能顶一下,抱歉

DaShanRen 发表于 2014-8-5 16:21:29

这也算算法分析?
{:tongue:}吓唬我。

goushibee 发表于 2014-8-5 16:39:07

本帖最后由 goushibee 于 2014-8-5 16:42 编辑

DaShanRen 发表于 2014-8-5 16:21
这也算算法分析?
吓唬我。
献丑了

wanap571 发表于 2014-8-5 17:11:33


感谢分享,我也来学习一下。

wkxq 发表于 2014-8-5 18:05:07

学习一下{:2_148:}

vipcrack 发表于 2014-8-5 19:35:31

只有膜拜!

阳光宅男 发表于 2014-8-5 23:40:30

感谢分享了,不错,学习了

zzjj2005 发表于 2015-6-24 18:30:55

感谢楼主的分享,学习了!
页: [1] 2
查看完整版本: WinCHM Pro v4.45 算法分析