• 标 题:【原创】一个彩票软件算法分析过程(详细)
  • 作 者:liyangsj
  • 时 间:2005-01-06,15:04
  • 链 接:http://bbs.pediy.com

有壳,UPX简单加壳,用OD就可以简单脱
此软件是重新验证,注册码是32位的,有数字,有大写字母,就是16进制组成的。
如果你的输入码经过计算等于机器码……已注册,  
我输入的12345678901234561234567890123456    我的机器码1UI0IN58980863NE
在它输入注册码之后存入Reg.Dll,我们可以查找字符串Reg.Dll
找到两处,一处是

00501820   |.  BA CC185000 mov edx,12_.005018CC                     ;  ASCII "Reg.Dll"
此处是保存时用的,你可以打开同目录下的Reg.Dll看看,你输的注册码就在里面

004F57BC   |.  BA B85C4F00 mov edx,12_.004F5CB8                     ;  ASCII "Reg.Dll"
这样我就在004F57BC下断点
CTRL+F2重新来过,
F9运行,就中断在004F57BC处,

004F57BC   |.  BA B85C4F00 mov edx,12_.004F5CB8                     ;  ASCII "Reg.Dll"
004F57C1   |.  8D86 780A00>lea eax,dword ptr ds:[esi+A78]
004F57C7   |.  E8 F8D7F0FF call 12_.00402FC4
004F57CC   |.  8D86 780A00>lea eax,dword ptr ds:[esi+A78]
004F57D2   |.  E8 7DD5F0FF call 12_.00402D54
004F57D7   |.  E8 CCD1F0FF call 12_.004029A8
004F57DC   |.  8D9E 780A00>lea ebx,dword ptr ds:[esi+A78]
004F57E2   |.  8D96 740A00>lea edx,dword ptr ds:[esi+A74]
004F57E8   |.  8BC3        mov eax,ebx
004F57EA   |.  E8 B1DBF0FF call 12_.004033A0
004F57EF   |.  8BC3        mov eax,ebx
004F57F1   |.  E8 16DCF0FF call 12_.0040340C
004F57F6   |.  E8 ADD1F0FF call 12_.004029A8
004F57FB   |.  8D86 780A00>lea eax,dword ptr ds:[esi+A78]
004F5801   |.  E8 86D8F0FF call 12_.0040308C
004F5806   |.  E8 9DD1F0FF call 12_.004029A8
004F580B   |.  8D4D BC     lea ecx,dword ptr ss:[ebp-44]
004F580E   |.  66:BA FE07  mov dx,7FE
004F5812   |.  8B86 740A00>mov eax,dword ptr ds:[esi+A74]
004F5818   |.  E8 EF9EFFFF call 12_.004EF70C                        ;  算法关键点
004F581D   |.  8B55 BC     mov edx,dword ptr ss:[ebp-44]
004F5820   |.  8B86 700A00>mov eax,dword ptr ds:[esi+A70]
004F5826   |.  E8 B1F6F0FF call 12_.00404EDC                        ;  直接比较了
004F582B   |.  75 2C       jnz short 12_.004F5859                      跳转关键点
004F582D   |.  33D2        xor edx,edx
004F582F   |.  8B86 540900>mov eax,dword ptr ds:[esi+954]
004F5835   |.  E8 5282F6FF call 12_.0045DA8C
004F583A   |.  BA C85C4F00 mov edx,12_.004F5CC8

……………………………………………………………………………………………………
进入004F5818
004EF70C   /$  55          push ebp
004EF70D   |.  8BEC        mov ebp,esp
004EF70F   |.  83C4 F8     add esp,-8
004EF712   |.  53          push ebx
004EF713   |.  56          push esi
004EF714   |.  57          push edi
004EF715   |.  33DB        xor ebx,ebx
004EF717   |.  895D F8     mov dword ptr ss:[ebp-8],ebx
004EF71A   |.  894D FC     mov dword ptr ss:[ebp-4],ecx
004EF71D   |.  8BF2        mov esi,edx
004EF71F   |.  8BD8        mov ebx,eax
004EF721   |.  33C0        xor eax,eax
004EF723   |.  55          push ebp
004EF724   |.  68 D3F74E00 push 12_.004EF7D3
004EF729   |.  64:FF30     push dword ptr fs:[eax]
004EF72C   |.  64:8920     mov dword ptr fs:[eax],esp
004EF72F   |.  8D55 F8     lea edx,dword ptr ss:[ebp-8]
004EF732   |.  8BC3        mov eax,ebx
004EF734   |.  E8 03FFFFFF call 12_.004EF63C                  ;  把输入的注册码转换一下
004EF739   |.  8B45 FC     mov eax,dword ptr ss:[ebp-4]
004EF73C   |.  8B55 F8     mov edx,dword ptr ss:[ebp-8]       ;  储存地址放入EDX
004EF73F   |.  E8 E053F1FF call 12_.00404B24
004EF744   |.  8B45 F8     mov eax,dword ptr ss:[ebp-8]       ;  储存地址放入EAX
004EF747   |.  E8 4456F1FF call 12_.00404D90                  ;  位数的一半给EAX说明要计算16次
004EF74C   |.  8BF8        mov edi,eax
004EF74E   |.  85FF        test edi,edi                       ;  注册码是否为空
004EF750   |.  7E 6B       jle short 12_.004EF7BD
004EF752   |.  BB 01000000 mov ebx,1
004EF757   |>  8B45 F8     /mov eax,dword ptr ss:[ebp-8]      ;  下面是把输入的注册码进行计算
004EF75A   |.  8A4418 FF   |mov al,byte ptr ds:[eax+ebx-1]    ;  得到第1,2个上面算好的注册码
004EF75E   |.  0FB7D6      |movzx edx,si                      ;  第一次是固定值07EE
004EF761   |.  C1EA 08     |shr edx,8                         ;  固定值右移2位还有2位
004EF764   |.  32C2        |xor al,dl                         ;  右移的值与前两位异或
004EF766   |.  84C0        |test al,al                        ;  比较是否等于0
004EF768   |.  75 1F       |jnz short 12_.004EF789
004EF76A   |.  8B45 FC     |mov eax,dword ptr ss:[ebp-4]
004EF76D   |.  E8 7658F1FF |call 12_.00404FE8
004EF772   |.  8B55 F8     |mov edx,dword ptr ss:[ebp-8]
004EF775   |.  8A541A FF   |mov dl,byte ptr ds:[edx+ebx-1]
004EF779   |.  885418 FF   |mov byte ptr ds:[eax+ebx-1],dl
004EF77D   |.  66:6BC6 0B  |imul ax,si,0B
004EF781   |.  66:83C0 0C  |add ax,0C
004EF785   |.  8BF0        |mov esi,eax
004EF787   |.  EB 30       |jmp short 12_.004EF7B9
004EF789   |>  8B45 FC     |mov eax,dword ptr ss:[ebp-4]
004EF78C   |.  E8 5758F1FF |call 12_.00404FE8                 ;  产生一个保存的地址
004EF791   |.  8B55 F8     |mov edx,dword ptr ss:[ebp-8]      ;  输入码地址
004EF794   |.  8A541A FF   |mov dl,byte ptr ds:[edx+ebx-1]    ;  得到两位输入码
004EF798   |.  0FB7CE      |movzx ecx,si                      ;  得到固定值
004EF79B   |.  C1E9 08     |shr ecx,8                         ;  取固定值前2位
004EF79E   |.  32D1        |xor dl,cl                         ;  固定值的前两位与两位输入码XOR准备保存
004EF7A0   |.  885418 FF   |mov byte ptr ds:[eax+ebx-1],dl    ;  储存,其中EAX是004EF78C的CALL算出来的
004EF7A4   |.  8B45 F8     |mov eax,dword ptr ss:[ebp-8]      ;  得到输入码地址
004EF7A7   |.  0FB64418 FF |movzx eax,byte ptr ds:[eax+ebx-1] ;  再次得到前两位输入码
004EF7AC   |.  66:03F0     |add si,ax                         ;  得到的输入码两位与固定值相加
004EF7AF   |.  66:6BC6 0B  |imul ax,si,0B                     ;  上面得到的值与0B相乘,结果给AX
004EF7B3   |.  66:83C0 0C  |add ax,0C
004EF7B7   |.  8BF0        |mov esi,eax                       ;  再加0C作为下一次的固定值
004EF7B9   |>  43          |inc ebx
004EF7BA   |.  4F          |dec edi
004EF7BB   |.^ 75 9A       \jnz short 12_.004EF757
004EF7BD   |>  33C0        xor eax,eax
004EF7BF   |.  5A          pop edx
004EF7C0   |.  59          pop ecx
004EF7C1   |.  59          pop ecx
004EF7C2   |.  64:8910     mov dword ptr fs:[eax],edx
004EF7C5   |.  68 DAF74E00 push 12_.004EF7DA
004EF7CA   |>  8D45 F8     lea eax,dword ptr ss:[ebp-8]
004EF7CD   |.  E8 FE52F1FF call 12_.00404AD0
004EF7D2   \.  C3          retn
004EF7D3    .- E9 984BF1FF jmp 12_.00404370
004EF7D8    .^ EB F0       jmp short 12_.004EF7CA
004EF7DA    .  5F          pop edi
004EF7DB    .  5E          pop esi
004EF7DC    .  5B          pop ebx
004EF7DD    .  59          pop ecx
004EF7DE    .  59          pop ecx
004EF7DF    .  5D          pop ebp
004EF7E0    .  C3          retn

……………………………………………………………………………………………………………………
004EF734   |.  E8 03FFFFFF call 12_.004EF63C           输入码的转换
就这样的 ,在内存中把:
00B1E738  31 32 33 34 35 36 37 38   12345678
00B1E740  39 30 31 32 33 34 35 36   90123456
00B1E748  31 32 33 34 35 36 37 38   12345678
00B1E750  39 30 31 32 33 34 35 36   90123456
转换成:
00B1B8F8  12 34 56 78 90 12 34 56   4Vx?4V
00B1B900  12 34 56 78 90 12 34 56   4Vx?4V


计算过程:每次取输入码的两位,计算出注册码的两位
第一次的前两位输入码与(固定值)07FE的07异或得到注册码的两位
同时用前两位输入码与(固定值)07FE相加,其值再与0B相乘,值加上0C代替原来的(固定值)07FE,用于下一次计算
第二次的两位输入码再与上次得到的固定值异或,得到注册码的3与4位,同样的方法计算5与6位的固定值
如此往复。

我是这样的:如果自己手工一个一个计算太烦,反正是异或,它是这样的A XOR B =C  则A XOR C =B
我就把原来内存中我的输入码改成我的机器码,让程序自己帮我计算出真正的注册码来,!!
但因为计算第2位后面的注册码是,要用到前面两位输入码。所以,第1,2位注册码一定要正确
用32bit Calculator v1.7计算了第1、2位是36(31(1)XOR 07(第一次固定值)=36)
后面的输入码先不动,要一个一个改了
004EF757   |> /8B45 F8     /mov eax,dword ptr ss:[ebp-8]      
004EF75A   |. |8A4418 FF   |mov al,byte ptr ds:[eax+ebx-1]    
004EF75E   |. |0FB7D6      |movzx edx,si                      
004EF761   |. |C1EA 08     |shr edx,8                         
004EF764   |. |32C2        |xor al,dl                在此处在断点每次停在此处时,把AL该成机器码ACII码
004EF766   |. |84C0        |test al,al               再走一步把计算出来的AL中的值替换我的输入码                       

004EF768   |. |75 1F       |jnz short 12_.004EF789
004EF76A   |. |8B45 FC     |mov eax,dword ptr ss:[ebp-4]
004EF76D   |. |E8 7658F1FF |call 12_.00404FE8
004EF772   |. |8B55 F8     |mov edx,dword ptr ss:[ebp-8]
004EF775   |. |8A541A FF   |mov dl,byte ptr ds:[edx+ebx-1]
004EF779   |. |885418 FF   |mov byte ptr ds:[eax+ebx-1],dl
004EF77D   |. |66:6BC6 0B  |imul ax,si,0B
004EF781   |. |66:83C0 0C  |add ax,0C
004EF785   |. |8BF0        |mov esi,eax
004EF787   |. |EB 30       |jmp short 12_.004EF7B9
004EF789   |> |8B45 FC     |mov eax,dword ptr ss:[ebp-4]
004EF78C   |. |E8 5758F1FF |call 12_.00404FE8                 
004EF791   |. |8B55 F8     |mov edx,dword ptr ss:[ebp-8]      
004EF794   |. |8A541A FF   |mov dl,byte ptr ds:[edx+ebx-1]    
004EF798   |. |0FB7CE      |movzx ecx,si                      
004EF79B   |. |C1E9 08     |shr ecx,8                         
004EF79E   |. |32D1        |xor dl,cl                         
004EF7A0   |. |885418 FF   |mov byte ptr ds:[eax+ebx-1],dl    
004EF7A4   |. |8B45 F8     |mov eax,dword ptr ss:[ebp-8]      
004EF7A7   |. |0FB64418 FF |movzx eax,byte ptr ds:[eax+ebx-1] 
004EF7AC   |. |66:03F0     |add si,ax                         
004EF7AF   |. |66:6BC6 0B  |imul ax,si,0B                     
004EF7B3   |. |66:83C0 0C  |add ax,0C
004EF7B7   |. |8BF0        |mov esi,eax                       
004EF7B9   |> |43          |inc ebx
004EF7BA   |. |4F          |dec edi
004EF7BB   |.^\75 9A       \jnz short 12_.004EF757

这样每次在004EF764中断,在004EF766修正我的输入码,这样一个一个的修正我的输入码,直到全部结束
修正好了的输入码就是真正的注册码!!
计算时,它把输入码与,计算出来的伪注册码放在不同的地方,没有覆盖的,
因为计算后面的要用前面的输入码。
结束。