好友
阅读权限10
听众
最后登录1970-1-1
|
本帖最后由 nnezyj 于 2013-10-30 22:56 编辑
六、分析makemkv.004032B3子程序
00404595 |. E8 19EDFFFF call makemkv.004032B3 ; 关键点:“注册码比对”,F7单步步入
剩下的就需要懂些汇编的基础知识了
========================================================================================
004032B3 ┌$ 33D2 xor edx,edx ; 清空EDX寄存器
004032B5 |. 8BC1 mov eax,ecx ; 将输入注册码地址存入EAX寄存器
004032B7 |. 66:3911 cmp word ptr ds:[ecx],dx ;
004032BA |. 74 07 je Xmakemkv.004032C3 ; 用于判断输入的注册码是否为空,为空跳转
004032BC |> 40 ┌inc eax ; 004032BC→004032C1是一个循环,用来判定输入的注册码长度
004032BD |. 40 |inc eax ;
004032BE |. 66:3910 |cmp word ptr ds:[eax],dx ;
004032C1 |.^ 75 F9 └jnz Xmakemkv.004032BC ;
004032C3 |> 2BC1 sub eax,ecx ; 末字符地址减去首字符地址
004032C5 |. 83E0 FE and eax,0xFFFFFFFE ; EAX内容与0xFFFFFFFE相与,使地址为偶数
004032C8 |. 3D 88000000 cmp eax,0x88 ; 一个字符两个字节,就是注册码长度为0x88除以2,注册码有68个字符
004032CD |. 74 03 je Xmakemkv.004032D2 ; 判断注册码长度是否为68个字符,相等则跳转
004032CF |. 32C0 xor al,al ; al=0x00
004032D1 C3 retn ; 位数不够弹出
========================================================================================
通过分析这一段知道注册码有68个字符
继续往下看
==================================================================================================
004032D2 |> 56 push esi
004032D3 |. 33F6 xor esi,esi ; 清空ESI寄存器
004032D5 |. 57 push edi
004032D6 |> 83FE 02 ┌cmp esi,0x2 ; ESI(0~0x43)对应字符编号
004032D9 |. 72 25 |jb Xmakemkv.00403300 ; 判断为小于结果跳转
004032DB |. 0FB70471 |movzx eax,word ptr ds:[ecx+esi*2] ; EAX=(ECX地址+2n) 对应地址内容
004032DF |. 66:83F8 5F |cmp ax,0x5F ; 0x5F( ASCII "_" )
004032E3 |. 74 1B |je Xmakemkv.00403300 ; ax=0x5F 跳转
004032E5 |. 8D78 D0 |lea edi,dword ptr ds:[eax-0x30] ; EDI=ASCII码-0x30
004032E8 |. 66:83FF 09 |cmp di,0x9 ; 0x30~0x39 ( ASCII "0~9" )
004032EC |. 76 12 |jbe Xmakemkv.00403300 ; di≤0x9 跳转
004032EE |. 8D78 C0 |lea edi,dword ptr ds:[eax-0x40] ; EDI=ASCII码-0x40
004032F1 |. 66:83FF 1A |cmp di,0x1A ; 0x41~0x5A ( ASCII "A~Z" )
004032F5 |. 76 09 |jbe Xmakemkv.00403300 ; di≤0x1A 跳转
004032F7 |. 83C0 9F |add eax,-0x61 ; EAX=EAX(ASCII码)-0x61
004032FA |. 66:83F8 19 |cmp ax,0x19 ; 0x61~0x7A ( ASCII "a~z" )
004032FE |. 77 3E |ja Xmakemkv.0040333E ; ax>0x19 跳转
00403300 |> 8A0471 |mov al,byte ptr ds:[ecx+esi*2] ; a(n) | 将对应ESI编号的字符存入al,如al=0x31("1")
00403303 |. 24 7F |and al,0x7F ; a(n) | al与01111111B相与
00403305 |. 66:0FB6C0 |movzx ax,al ; a(n) | 寄存器扩展 如ax=0x0031("1")
00403309 |. 66:03C2 |add ax,dx ; a(n)+b(n) | ax+bx,初始EDX为0,dx=0x0000
0040330C |. 0FB7C0 |movzx eax,ax ; a(n)+b(n) | 寄存器扩展 如EAX=0x00000031("1")
0040330F |. 8D56 0B |lea edx,dword ptr ds:[esi+0xB] ; n+0xB | EDX=ESI+0xB
00403312 |. 0FAFC2 |imul eax,edx ; [a(n)+b(n)]*(n+0xB)
00403315 |. 33D2 |xor edx,edx ; EDX=0 清空EDX寄存器
00403317 |. BF FD0F0000 |mov edi,0xFFD ; EDI=0xFFD
0040331C |. F7F7 |div edi ; {[a(n)+b(n)]*(n+0xB)}/0xFFD | EAX存商 EDX存余数 [EDX,EAX]串连成一个寄存器,最为被除数,EDI为除数
0040331E |. 46 |inc esi ; dl=b(n+1)={[a(n)+b(n)]*(n+0xB)}%0xFFD | “%”求余运算符 ESI加1
0040331F |. 0FB7D2 |movzx edx,dx ; 由EDI=0xFFD知道余数不会大于0xFFD
00403322 |. 83FE 42 |cmp esi,0x42 ; 总共进行0x42(66)次运算
00403325 |.^ 72 AF └jb Xmakemkv.004032D6
==================================================================================================
这段使用前66个字符运算来获取一个关键数,用来比对最后两个字符
==================================================================================================
00403327 |. 8AC2 mov al,dl ; al=dl[b(0x42)] 前面66次运算所得b(42) 如dx=0x088C dl=0x8C
00403329 |. 24 3F and al,0x3F ; al与00111111B相与 即al所存数不大于0x3F al≤0x3F
0040332B |. E8 62FFFFFF call makemkv.00403292 ; Key:“关键字符比对”,F7单步步入
00403330 |. 0FB7B1 840000>movzx esi,word ptr ds:[ecx+0x84] ; ESI=a(0x42) 输入注册码倒数第二个字符
00403337 |. 0FBEC0 movsx eax,al ; 扩展寄存器
0040333A |. 3BC6 cmp eax,esi ; 计算所得a(0x42) 与 输入的a(0x42) 比对
0040333C |. 74 04 je Xmakemkv.00403342 ; 相等跳转
0040333E |> 32C0 xor al,al ; 不相等则 al=0x00
00403340 |. EB 1B jmp Xmakemkv.0040335D
00403342 |> 8BC2 mov eax,edx ; EAX=b(0x42) 前面66次运算所得b(0x42)
00403344 |. C1E8 06 shr eax,0x6 ; b(42)/(2^6) | EAX右移6位
00403347 |. 24 3F and al,0x3F ; al与00111111B相与 即al所存数不大于0x3F al≤0x3F
00403349 |. E8 44FFFFFF call makemkv.00403292 ; Key:“关键字符比对”,F7单步步入
0040334E |. 0FB789 860000>movzx ecx,word ptr ds:[ecx+0x86] ; ECX=a(0x43) 输入注册码最后一个字符
00403355 |. 0FBEC0 movsx eax,al ; 扩展寄存器
00403358 |. 3BC1 cmp eax,ecx ; 计算所得a(0x43) 与 输入的a(0x43) 比对
0040335A |. 0F94C0 sete al ; ZF=1则al=0x01 ZF=0则al=0x00 | cmp结果相等则ZF=1,不相等则ZF=0
0040335D |> 5F pop edi
0040335E |. 5E pop esi
0040335F └. C3 retn
========================================================================================
========================================================================================
00403292 ┌$ 84C0 test al,al ; al与al相与,判断al是否为0
00403294 |. 75 03 jnz Xmakemkv.00403299 ; al不为0则跳转
00403296 |. 04 5F add al,0x5F ; al=0x5F( ASCII "_" )
00403298 |. C3 retn ; 返回al值
00403299 |> 3C 0B cmp al,0xB
0040329B |. 73 07 jnb Xmakemkv.004032A4 ; al≥0xB跳转
0040329D |. 0FB6C0 movzx eax,al ; al(0x1~0xA)
004032A0 |. 83C0 2F add eax,0x2F ; EAX=0x30~0x39 ( ASCII "0~9" )
004032A3 |. C3 retn ; 返回al值
004032A4 |> 3C 26 cmp al,0x26
004032A6 |. 0FB6C0 movzx eax,al
004032A9 |. 73 04 jnb Xmakemkv.004032AF ; al≥0x26跳转
004032AB |. 83C0 35 add eax,0x35 ; al(0xB~0x25) EAX=0x40~0x5A ( ASCII "@,A~Z" )
004032AE |. C3 retn ; 返回al值
004032AF |> 83C0 3B add eax,0x3B ; al(0x26~0x3F) EAX=0x61~0x7A ( ASCII "a~z" )
004032B2 └. C3 retn ; 返回al值
==================================================================================================
公式为:b(n+1)={[a(n)+b(n)]*(n+0xB)}%0xFFD
n=0x0~0x41,b(0)=0,a(0)~a(65):注册码前66位
“%”求余运算符
a(66) : b'(1)=b(0x42)%0x3F
a(67) : b'(2)=[b(0x42)/0x40]%0x3F
┌ 0x5F ; b'=0 ( ASCII "_" )
a=│ b'+0x2F ; 0x1≤b'≤0xA 0x30~0x39 ( ASCII "0~9" )
│ b'+0x35 ; 0xB≤b'≤0x25) 0x40~0x5A ( ASCII "@,A~Z" )
└ b'+0x3B ; 0x26≤b'≤0x3F) 0x61~0x7A ( ASCII "a~z" )
==================================================================================================
忙乎半天,发一个最后我算出来的CDKEY
123456789012345678901234567890123456789012345678901234567890123456AW
|
|