└文章标题┐:XnView v1.91最新版-软柿子算法分析及注册机
└破文作者┐:大菜一号
└破解对象┐:XnView v1.91
└下载地址┐:自已搜吧
└对象大小┐:不知
└加壳方式┐:aspack
└保护方式┐:普通软柿子算法
└编写语言┐:vc6
└使用工具┐:OD,peid
└破解平台┐:D-XP
└破解声明┐:软柿子真好~~~^-^
----------------------------------------------------------------------------------
└破解过程┐:
嘿嘿``近来嫌ACDsee5.0速度太慢,看个图也要几秒!就下了个XnView!呵呵`虽说它不能简单地编辑一个图,不过看图速度较快,还有十六进制什么什么的!!饿也没用过啦~~西西~~~~~~~~~~
好了``aspack的壳`,Peid帮我们搞定了!下断GetDlgItemText,name:jiangwu,serial:123456!,点注册后断在:
0052E0AA . 56 push esi
0052E0AB . 8BB424 700100>mov esi, dword ptr [esp+170]
0052E0B2 . 57 push edi
0052E0B3 . 8B3D 70366600 mov edi, dword ptr [<&USER32.GetDlgI>; USER32.GetDlgItemTextA
0052E0B9 . 68 00010000 push 100 ; /Count = 100 (256.)
0052E0BE . 50 push eax ; |Buffer
0052E0BF . 68 D0070000 push 7D0 ; |ControlID = 7D0 (2000.)
0052E0C4 . 56 push esi ; |hWnd
0052E0C5 . FFD7 call edi ; \GetDlgItemTextA<=============断在这里,取注册名
0052E0C7 . 8D4C24 10 lea ecx, dword ptr [esp+10]
0052E0CB . 6A 20 push 20 ; /Count = 20 (32.)
0052E0CD . 51 push ecx ; |Buffer
0052E0CE . 68 D1070000 push 7D1 ; |ControlID = 7D1 (2001.)
0052E0D3 . 56 push esi ; |hWnd
0052E0D4 . FFD7 call edi ; \GetDlgItemTextA<=============这里,取注册码
0052E0D6 . 8A4424 70 mov al, byte ptr [esp+70]<============注册名第一位到al
0052E0DA . 84C0 test al, al<===========================是否为空
0052E0DC . 0F84 3A010000 je 0052E21C<=========================没输入注册名就出错
0052E0E2 . 8A4424 10 mov al, byte ptr [esp+10]<============注册码第一位到al
0052E0E6 . 84C0 test al, al<===========================是否为空
0052E0E8 . 0F84 2E010000 je 0052E21C<=========================没输入注册码就出错
0052E0EE . 8D5424 08 lea edx, dword ptr [esp+8]
0052E0F2 . 8D4424 70 lea eax, dword ptr [esp+70]
0052E0F6 . 52 push edx
0052E0F7 . 50 push eax<==============================注册名地址进栈
0052E0F8 . E8 E32CFAFF call 004D0DE0<=========================关键call
0052E0FD . 8D4C24 18 lea ecx, dword ptr [esp+18]
0052E101 . 51 push ecx
0052E102 . E8 EC5F0200 call 005540F3
0052E107 . 8B4C24 14 mov ecx, dword ptr [esp+14]
0052E10B . 83C4 0C add esp, 0C
0052E10E . 3BC8 cmp ecx, eax
0052E110 . 74 5D je short 0052E16F
0052E112 . A1 582A6E00 mov eax, dword ptr [6E2A58]
0052E117 . 8D5424 30 lea edx, dword ptr [esp+30]
0052E11B . 6A 40 push 40 ; /Count = 40 (64.)
0052E11D . 52 push edx ; |Buffer
0052E11E . 68 93130000 push 1393 ; |RsrcID = STRING "Invalid registration"
0052E123 . 50 push eax ; |hInst => 10000000
0052E124 . FF15 08376600 call dword ptr [<&USER32.LoadStringA>>; \LoadStringA<==========加载错误字符串
0052E12A . 6A 10 push 10 ; /Style = MB_OK|MB_ICONHAND|MB_APPLMODAL
0052E12C . 8D4C24 34 lea ecx, dword ptr [esp+34] ; |
0052E130 . 68 9CAA6D00 push 006DAA9C ; |Title = ""
0052E135 . 51 push ecx ; |Text
0052E136 . 56 push esi ; |hOwner
0052E137 . FF15 90366600 call dword ptr [<&USER32.MessageBoxA>>; \MessageBoxA<==========显示错误字符串
0052E13D . 68 D0070000 push 7D0 ; /ControlID = 7D0 (2000.)
0052E142 . 56 push esi ; |hWnd
0052E143 . FF15 88366600 call dword ptr [<&USER32.GetDlgItem>] ; \GetDlgItem
0052E149 . 50 push eax ; /hWnd
0052E14A . FF15 C8366600 call dword ptr [<&USER32.SetFocus>] ; \SetFocus
0052E150 . 68 9CAA6D00 push 006DAA9C ; /Text = ""
0052E155 . 68 D1070000 push 7D1 ; |ControlID = 7D1 (2001.)
0052E15A . 56 push esi ; |hWnd
0052E15B . FF15 84366600 call dword ptr [<&USER32.SetDlgItemTe>; \SetDlgItemTextA<=====注册错误之后设置注册码输入框为空
0052E161 . 5F pop edi
0052E162 . B8 01000000 mov eax, 1
0052E167 . 5E pop esi
0052E168 . 81C4 68010000 add esp, 168
0052E16E . C3 retn
0052E16F > 8D5424 70 lea edx, dword ptr [esp+70]
0052E173 . 68 00010000 push 100
0052E178 . 52 push edx
0052E179 . 68 D0070000 push 7D0
0052E17E . 56 push esi
0052E17F . FFD7 call edi
0052E181 . 8D4424 10 lea eax, dword ptr [esp+10]
0052E185 . 6A 20 push 20
0052E187 . 50 push eax
0052E188 . 68 D1070000 push 7D1
0052E18D . 56 push esi
0052E18E . FFD7 call edi
0052E190 . 8D4C24 70 lea ecx, dword ptr [esp+70]
0052E194 . 51 push ecx
0052E195 . 68 84716B00 push 006B7184 ; ASCII "LicenseName"
0052E19A . 6A 00 push 0
0052E19C . E8 0FC1F7FF call 004AA2B0
0052E1A1 . 8D5424 1C lea edx, dword ptr [esp+1C]
0052E1A5 . 52 push edx
0052E1A6 . 68 74716B00 push 006B7174 ; ASCII "LicenseNumber"
0052E1AB . 6A 00 push 0
0052E1AD . E8 FEC0F7FF call 004AA2B0
0052E1B2 . A1 602A6E00 mov eax, dword ptr [6E2A60]
0052E1B7 . 83C4 18 add esp, 18
0052E1BA . C705 882A6E00>mov dword ptr [6E2A88], 1
0052E1C4 . 6A 01 push 1 ; /Flags = MF_BYCOMMAND|MF_GRAYED|MF_STRING
0052E1C6 . 68 F2000000 push 0F2 ; |ItemID = F2 (242.)
0052E1CB . 50 push eax ; |/hWnd => 00180068 ('XnView - [浏览器 - E:\工具\Sk...',class='XmainClass')
0052E1CC . FF15 F4366600 call dword ptr [<&USER32.GetMenu>] ; |\GetMenu
0052E1D2 . 50 push eax ; |hMenu
0052E1D3 . FF15 DC366600 call dword ptr [<&USER32.EnableMenuIt>; \EnableMenuItem
0052E1D9 . 8B15 582A6E00 mov edx, dword ptr [6E2A58] ; xnviewzh.10000000
0052E1DF . 8D4C24 30 lea ecx, dword ptr [esp+30]
0052E1E3 . 6A 40 push 40 ; /Count = 40 (64.)
0052E1E5 . 51 push ecx ; |Buffer
0052E1E6 . 68 94130000 push 1394 ; |RsrcID = STRING "Registration successful.
Thank you for purchasing XnView."
0052E1EB . 52 push edx ; |hInst => 10000000
0052E1EC . FF15 08376600 call dword ptr [<&USER32.LoadStringA>>; \LoadStringA<=========加载注册成功字符串
0052E1F2 . 6A 40 push 40 ; /Style = MB_OK|MB_ICONASTERISK|MB_APPLMODAL
0052E1F4 . 8D4424 34 lea eax, dword ptr [esp+34] ; |
0052E1F8 . 68 9CAA6D00 push 006DAA9C ; |Title = ""
0052E1FD . 50 push eax ; |Text
0052E1FE . 56 push esi ; |hOwner
0052E1FF . FF15 90366600 call dword ptr [<&USER32.MessageBoxA>>; \MessageBoxA<=========显示注册成功字符串
0052E205 . 6A 00 push 0 ; /Result = 0
0052E207 . 56 push esi ; |hWnd
0052E208 . FF15 74366600 call dword ptr [<&USER32.EndDialog>] ; \EndDialog<===========结束注册对话框
0052E20E . 5F pop edi
0052E20F . B8 01000000 mov eax, 1
0052E214 . 5E pop esi
0052E215 . 81C4 68010000 add esp, 168
0052E21B . C3 retn
0052E21C > 8B15 582A6E00 mov edx, dword ptr [6E2A58] ; xnviewzh.10000000
0052E222 . 8D4C24 30 lea ecx, dword ptr [esp+30]
0052E226 . 6A 40 push 40 ; /Count = 40 (64.)
0052E228 . 51 push ecx ; |Buffer
0052E229 . 68 93130000 push 1393 ; |RsrcID = STRING "Invalid registration"
0052E22E . 52 push edx ; |hInst => 10000000
0052E22F . FF15 08376600 call dword ptr [<&USER32.LoadStringA>>; \LoadStringA
0052E235 . 6A 10 push 10 ; /Style = MB_OK|MB_ICONHAND|MB_APPLMODAL
0052E237 . 8D4424 34 lea eax, dword ptr [esp+34] ; |
0052E23B . 68 9CAA6D00 push 006DAA9C ; |Title = ""
0052E240 . 50 push eax ; |Text
0052E241 . 56 push esi ; |hOwner
0052E242 . FF15 90366600 call dword ptr [<&USER32.MessageBoxA>>; \MessageBoxA
关键call:
F7跟进后到这里:
004D0DE0 /$ 8B5424 04 mov edx, dword ptr [esp+4]
004D0DE4 |. 53 push ebx
004D0DE5 |. 55 push ebp
004D0DE6 |. 56 push esi
004D0DE7 |. 57 push edi
004D0DE8 |. 8BFA mov edi, edx
004D0DEA |. 83C9 FF or ecx, FFFFFFFF
004D0DED |. 33C0 xor eax, eax
004D0DEF |. F2:AE repne scas byte ptr es:[edi]
004D0DF1 |. F7D1 not ecx
004D0DF3 |. 49 dec ecx
004D0DF4 |. BE C0656B00 mov esi, 006B65C0
004D0DF9 |. 8BE9 mov ebp, ecx
004D0DFB |. B9 05000000 mov ecx, 5
004D0E00 |. BF 30C76D00 mov edi, 006DC730
004D0E05 |. F3:A5 rep movs dword ptr es:[edi], dword p>
004D0E07 |. 8BF0 mov esi, eax
004D0E09 |. 74 21 je short 004D0E2C
004D0E0B |> 8A0C16 /mov cl, byte ptr [esi+edx]<============注册名字符传到cl
004D0E0E |. 8AD9 |mov bl, cl<============================再传到bl
004D0E10 |. 3298 30C76D00 |xor bl, byte ptr [eax+6DC730]<=========与一串十六进制数异或
004D0E16 |. 40 |inc eax<===============================eax+1
004D0E17 |. 83F8 05 |cmp eax, 5<============================eax和5比较
004D0E1A |. 881C16 |mov byte ptr [esi+edx], bl<============异或结果传到12f608
004D0E1D |. 8888 2FC76D00 |mov byte ptr [eax+6DC72F], cl<=========原字符传到6dc730
004D0E23 |. 75 02 |jnz short 004D0E27<====================eax不等于5就跳
004D0E25 |. 33C0 |xor eax, eax<==========================eax等于5,eax就为0
004D0E27 |> 46 |inc esi<===============================计数器加一
004D0E28 |. 3BF5 |cmp esi, ebp
004D0E2A |.^ 72 DF \jb short 004D0E0B<====================没完跳上去
根据eax,可以知道十六进制数串只算其前五位
004D0E2C |> 33FF xor edi, edi
004D0E2E |. 33C9 xor ecx, ecx
004D0E30 |. 85ED test ebp, ebp
004D0E32 |. 76 26 jbe short 004D0E5A
004D0E34 |> 8A9F 35C76D00 /mov bl, byte ptr [edi+6DC735]<=========十六进制数串从第六位开始循环依次传到bl
004D0E3A |. 8BF5 |mov esi, ebp
004D0E3C |. 2BF1 |sub esi, ecx<==========================注册名长度减去计数器值
004D0E3E |. 4E |dec esi<===============================结果减一(指向第一区循环结果的尾部)
004D0E3F |. 8A0416 |mov al, byte ptr [esi+edx]<============从上面循环结果后面开始取字符到al
004D0E42 |. 32D8 |xor bl, al<============================两者异或
004D0E44 |. 47 |inc edi<===============================edi+1
004D0E45 |. 881C16 |mov byte ptr [esi+edx], bl
004D0E48 |. 8887 34C76D00 |mov byte ptr [edi+6DC734], al
004D0E4E |. 83FF 05 |cmp edi, 5<============================edi是否为5
004D0E51 |. 75 02 |jnz short 004D0E55
004D0E53 |. 33FF |xor edi, edi<==========================edi为5,edi就清零
004D0E55 |> 41 |inc ecx
004D0E56 |. 3BCD |cmp ecx, ebp<==========================是否算完
004D0E58 |.^ 72 DA \jb short 004D0E34<====================没完跳上去
根据edi,可以知道十六进制数串在这个循环只算期第六到第十位
004D0E5A |> 33F6 xor esi, esi
004D0E5C |. 33FF xor edi, edi
004D0E5E |. 85ED test ebp, ebp
004D0E60 |. 76 21 jbe short 004D0E83
004D0E62 |> 8A0417 /mov al, byte ptr [edi+edx]<============从上面循环结果的前面开始取字符
004D0E65 |. 8A8E 3AC76D00 |mov cl, byte ptr [esi+6DC73A]<=========十六进制数串的一个字节到cl
004D0E6B |. 32C8 |xor cl, al<============================两者异或
004D0E6D |. 46 |inc esi<===============================esi+1
004D0E6E |. 880C17 |mov byte ptr [edi+edx], cl<============传回去
004D0E71 |. 8886 39C76D00 |mov byte ptr [esi+6DC739], al
004D0E77 |. 83FE 05 |cmp esi, 5<============================esi是否为5
004D0E7A |. 75 02 |jnz short 004D0E7E
004D0E7C |. 33F6 |xor esi, esi<==========================esi为5时,esi就清零
004D0E7E |> 47 |inc edi
004D0E7F |. 3BFD |cmp edi, ebp<==========================是否已算完
004D0E81 |.^ 72 DF \jb short 004D0E62<====================没完就跳上去
根据esi,可以知道十六进制数串在这个循不只算其第十一位到第十五位
004D0E83 |> 33FF xor edi, edi
004D0E85 |. 33C9 xor ecx, ecx
004D0E87 |. 85ED test ebp, ebp
004D0E89 |. 76 26 jbe short 004D0EB1
004D0E8B |> 8A9F 3FC76D00 /mov bl, byte ptr [edi+6DC73F]<========= 从十六进制的第十五位开始取字符
004D0E91 |. 8BF5 |mov esi, ebp
004D0E93 |. 2BF1 |sub esi, ecx
004D0E95 |. 4E |dec esi
004D0E96 |. 8A0416 |mov al, byte ptr [esi+edx]<============从上面循环结果的尾部开始向前取字符
004D0E99 |. 32D8 |xor bl, al<============================两者异或
004D0E9B |. 47 |inc edi<===============================edi+1
004D0E9C |. 881C16 |mov byte ptr [esi+edx], bl
004D0E9F |. 8887 3EC76D00 |mov byte ptr [edi+6DC73E], al
004D0EA5 |. 83FF 05 |cmp edi, 5<============================edi是否为5
004D0EA8 |. 75 02 |jnz short 004D0EAC
004D0EAA |. 33FF |xor edi, edi<==========================edi为5,edi就清零
004D0EAC |> 41 |inc ecx
004D0EAD |. 3BCD |cmp ecx, ebp<==========================是否已算完
004D0EAF |.^ 72 DA \jb short 004D0E8B<====================没完就跳上去
004D0EB1 |> 8B7C24 18 mov edi, dword ptr [esp+18]
004D0EB5 |. 33C0 xor eax, eax
004D0EB7 |. 85ED test ebp, ebp
004D0EB9 |. C707 00000000 mov dword ptr [edi], 0
004D0EBF |. 76 17 jbe short 004D0ED8
004D0EC1 |> 8BC8 /mov ecx, eax<==========================计数器值传到ecx
004D0EC3 |. 83E1 03 |and ecx, 3<============================ecx与上3
004D0EC6 |. 8A1C39 |mov bl, byte ptr [ecx+edi]<============根据与的结果从上面循环结果中取出字符
004D0EC9 |. 8D3439 |lea esi, dword ptr [ecx+edi]<==========把该位字符相应的地址传到esi
004D0ECC |. 8A0C10 |mov cl, byte ptr [eax+edx]<============从上面循环结果的前面开始取字符
004D0ECF |. 02D9 |add bl, cl<============================两者相加
004D0ED1 |. 40 |inc eax <==============================计数器加一
004D0ED2 |. 3BC5 |cmp eax, ebp
004D0ED4 |. 881E |mov byte ptr [esi], bl<================结果传到与bl字符相应的内存地址
004D0ED6 |.^ 72 E9 \jb short 004D0EC1<====================没完跳上去
004D0ED8 |> 5F pop edi
004D0ED9 |. 5E pop esi
004D0EDA |. 5D pop ebp
004D0EDB |. 5B pop ebx
004D0EDC \. C3 retn
算法总结一下吧:
其实是简单的xor加密,呵呵!!不过就是内存位置乱了点~~~
还是不要总结了!!自已看了都烦~~哦呵呵呵!!反正就是异或异或,传回去传过来!取前面,取后面!`就是这样了!~~自己看清楚一点吧~~
呵呵`
注册机还是要写滴!mfc的button事件代码!!:
char name[100],code[100],a[10];
long int key[]={0xaa,0x89,0xc4,0xfe,0x46,0x78,0xf0,
0xd0,0x03,0xe7,0xf7,0xfd,0xf4,0xe7,0xb9,0xb5,0x1b,//对了`这就是那个传说中的十六进制数串
0xc9,0x50,0x73};
int i,len=0,k=0;
unsigned int num=0,max1=0,max2=0;
DWORD* p;
GetDlgItemText(IDC_EDIT1,name,-1);
len=strlen(name);
i=0;
for(;i<len;i++)
{
num=name[i]^key[k];
k++;
key[k-1]=name[i];
name[i]=num;
if(5==k)
k=0;
}
k=0;
for(i=0;i<len;i++)
{
max1=(BYTE)name[len-i-1];
max2=(BYTE)key[k+5];
num=max1^max2;
key[k+5]=max1;
name[len-i-1]=num;
k++;
if(5==k)
k=0;
}
k=0;
for(i=0;i<len;i++)
{
max1=(BYTE)name[i];
max2=(BYTE)key[k+10];
num=max1^max2;
key[k+10]=name[i];
name[i]=num;
k++;
if(5==k)
k=0;
}
k=0;
for(i=0;i<len;i++)
{
max1=(BYTE)name[len-i-1];
max2=(BYTE)key[k+15];
num=max1^max2;
key[k+15]=name[len-i-1];
name[len-i-1]=num;
k++;
if(5==k)
k=0;
}
memset(a,0,10);
for(i=0;i<len;i++)
{
k=i&3;
max1=a[k];
max2=(BYTE)name[i];
num=max1+max2;
a[k]=(BYTE)num;
}
p=(DWORD*)a;
sprintf(name,"%d",*p);
SetDlgItemText(IDC_EDIT2,name);
}
其实注册机可以写得非常简洁``因为想让大家看得更清楚一点这个算法,所以,原封不动地还原了反汇编代码!
----------------------------------------------------------------------------------
└经验总结┐:
嘿嘿``原来crack一个软件也不难嘛!至少这个是这样~~呵呵~
----------------------------------------------------------------------------------
└版权声明┐ 本文原创于看雪软件安全论坛, 转载请注明作者并保持文章的完整, 谢谢!
2007年6月6日 22:28:16
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)