好友
阅读权限25
听众
最后登录1970-1-1
|
〇〇木一
发表于 2013-12-16 10:27
CM是什么?Crackme是什么?这是什么东西?楼主发的什么?
他们都是一些公开给别人尝试破解的小程序,制作 Crackme 的人可能是程序员,想测试一下自己的软件保护技术,也可能是一位 Cracker,想挑战一下其它 Cracker 的破解实力,也可能是一些正在学习破解的人,自己编一些小程序给自己破解,KeyGenMe是要求别人做出它的 keygen (序号产生器), ReverseMe 要求别人把它的算法做出逆向分析, UnpackMe 是要求别人把它成功脱壳,本版块禁止回复非技术无关水贴。
本帖最后由 〇〇木一 于 2013-12-16 12:41 编辑
【文章标题】: 【吾爱2013CM大赛解答】--KeyGenMe-- a070458 -- 算法分析[〇〇木一]
【文章作者】: 〇〇木一[OoWoodOne]
【软件名称】: KeyGenMe-- a070458
【下载地址】: http://www.52pojie.cn/thread-228709-1-1.html
【操作平台】: win 7
第一次写的代码有点小错误现在已经改好了。
分析这个算法真是搞得我蛋蛋碎光了..
不用说,首先先找到他比较验证的的地方,这个很好找中断回溯,按钮事件,API断点随便可以找到。
[AppleScript] 纯文本查看 复制代码 00401DA0 .>push -0x1
00401DA2 .>push KeyGenMe.004025B0 ; SE 处理程序安装
00401DA7 .>mov eax,dword ptr fs:[0]
00401DAD .>push eax
00401DAE .>mov dword ptr fs:[0],esp
00401DB5 .>sub esp,0x14
00401DB8 .>push ebx
00401DB9 .>push ebp
00401DBA .>mov ebp,ecx
00401DBC .>push esi
00401DBD .>push edi
00401DBE .>lea ecx,dword ptr ss:[esp+0x10]
00401DC2 .>call <jmp.&MFC42.#540>
00401DC7 .>lea ecx,dword ptr ss:[esp+0x14]
00401DCB .>mov dword ptr ss:[esp+0x2C],0x0
00401DD3 .>call <jmp.&MFC42.#540>
00401DD8 .>push KeyGenMe.0040403C ; UNICODE "5"
00401DDD .>lea ecx,dword ptr ss:[esp+0x14]
00401DE1 .>mov byte ptr ss:[esp+0x30],0x1
00401DE6 .>call <jmp.&MFC42.#941>
00401DEB .>push KeyGenMe.00404038 ; UNICODE "2"
00401DF0 .>lea ecx,dword ptr ss:[esp+0x14]
00401DF4 .>call <jmp.&MFC42.#941>
00401DF9 .>push KeyGenMe.00404034 ; UNICODE "P"
00401DFE .>lea ecx,dword ptr ss:[esp+0x14]
00401E02 .>call <jmp.&MFC42.#941>
00401E07 .>push KeyGenMe.00404030 ; UNICODE "o"
00401E0C .>lea ecx,dword ptr ss:[esp+0x14]
00401E10 .>call <jmp.&MFC42.#941>
00401E15 .>push KeyGenMe.0040402C ; UNICODE "J"
00401E1A .>lea ecx,dword ptr ss:[esp+0x14]
00401E1E .>call <jmp.&MFC42.#941>
00401E23 .>push KeyGenMe.00404028 ; UNICODE "i"
00401E28 .>lea ecx,dword ptr ss:[esp+0x14]
00401E2C .>call <jmp.&MFC42.#941>
00401E31 .>push KeyGenMe.00404024 ; UNICODE "e"
00401E36 .>lea ecx,dword ptr ss:[esp+0x14]
00401E3A .>call <jmp.&MFC42.#941> ; 组成"52PoJie"字串
00401E3F .>push 0x1
00401E41 .>mov ecx,ebp
00401E43 .>call <jmp.&MFC42.#6334> ; 取文本框内容
00401E48 .>mov eax,dword ptr ss:[ebp+0x60]
00401E4B .>lea esi,dword ptr ss:[ebp+0x60]
00401E4E .>mov eax,dword ptr ds:[eax-0x8]
00401E51 .>cdq
00401E52 .>sub eax,edx
00401E54 .>sar eax,1
00401E56 .>push eax
00401E57 .>call <jmp.&MFC42.#823>
00401E5C .>mov ecx,dword ptr ss:[ebp+0x64]
00401E5F .>add ebp,0x64
00401E62 .>mov edi,eax
00401E64 .>add esp,0x4
00401E67 .>mov eax,dword ptr ds:[ecx-0x8]
00401E6A .>test eax,eax
00401E6C .>je short KeyGenMe.00401EB9 ; 1 l
00401E6E .>mov edx,dword ptr ds:[esi]
00401E70 .>mov eax,dword ptr ds:[edx-0x8]
00401E73 .>test eax,eax
00401E75 .>je short KeyGenMe.00401EB9 ; 2 l
00401E77 .>push ecx
00401E78 .>mov ecx,esp
00401E7A .>mov dword ptr ss:[esp+0x1C],esp
00401E7E .>push esi
00401E7F .>call <jmp.&MFC42.#535>
00401E84 .>call KeyGenMe.004012D0 ; 判断注册码是否为16进制字串(要大写)
00401E89 .>add esp,0x4
00401E8C .>test al,al
00401E8E .>je short KeyGenMe.00401EB9
00401E90 .>mov eax,dword ptr ds:[esi]
00401E92 .>mov eax,dword ptr ds:[eax-0x8] ; 取注册码长度
00401E95 .>mov ecx,eax
00401E97 .>and ecx,0x80000001
00401E9D .>jns short KeyGenMe.00401EA4
00401E9F .>dec ecx
00401EA0 .>or ecx,0xFFFFFFFE
00401EA3 .>inc ecx
00401EA4 >>jnz short KeyGenMe.00401EB9
00401EA6 .>mov edx,dword ptr ss:[ebp]
00401EA9 .>mov ecx,dword ptr ds:[edx-0x8] ; 取用户名长度
00401EAC .>cmp ecx,0x5
00401EAF .>jl short KeyGenMe.00401EB9 ; >=5
00401EB1 .>lea ecx,dword ptr ds:[ecx+ecx+0x2]
00401EB5 .>cmp eax,ecx
00401EB7 .>je short KeyGenMe.00401EC4 ; 注册码长度必须为[用户名长度]*2+2
00401EB9 >>call dword ptr ds:[0x40410C] ; KeyGenMe.004019B0
00401EBF .>jmp KeyGenMe.00401FBA
00401EC4 >>push eax
00401EC5 .>push edi
00401EC6 .>push ecx
00401EC7 .>mov ecx,esp
00401EC9 .>mov dword ptr ss:[esp+0x24],esp
00401ECD .>push esi
00401ECE .>call <jmp.&MFC42.#535>
00401ED3 .>call KeyGenMe.00401360 ; 注册码转为16进制
00401ED8 .>mov edx,dword ptr ds:[esi]
00401EDA .>mov eax,dword ptr ds:[edx-0x8]
00401EDD .>cdq
00401EDE .>sub eax,edx
00401EE0 .>sar eax,1
00401EE2 .>push eax
00401EE3 .>push edi
00401EE4 .>call KeyGenMe.00401260 ; 并转化为链表形式
00401EE9 .>mov bl,byte ptr ds:[eax] ; 链表头(注册码前两位16进制值)
00401EEB .>mov esi,dword ptr ds:[eax+0x4] ; esi-next
00401EEE .>push eax
00401EEF .>mov byte ptr ss:[esp+0x30],bl
00401EF3 .>call <jmp.&MFC42.#825>
00401EF8 .>mov edi,dword ptr ss:[esp+0x30]
00401EFC .>add esp,0x18
00401EFF .>lea eax,dword ptr ss:[esp+0x10]
00401F03 .>push edi
00401F04 .>push esi
00401F05 .>push ecx
00401F06 .>mov ecx,esp
00401F08 .>mov dword ptr ss:[esp+0x24],esp
00401F0C .>push eax
00401F0D .>call <jmp.&MFC42.#535>
00401F12 .>call KeyGenMe.004013D0 ; 对注册码的运算1
00401F17 .>add esp,0xC
00401F1A .>push edi
00401F1B .>push ecx
00401F1C .>mov ecx,esp
00401F1E .>mov dword ptr ss:[esp+0x24],esp
00401F22 .>push ebp
00401F23 .>call <jmp.&MFC42.#535>
00401F28 .>push ecx
00401F29 .>lea edx,dword ptr ss:[esp+0x1C]
00401F2D .>mov ecx,esp
00401F2F .>mov dword ptr ss:[esp+0x2C],esp
00401F33 .>push edx
00401F34 .>mov byte ptr ss:[esp+0x3C],0x2
00401F39 .>call <jmp.&MFC42.#535>
00401F3E .>lea eax,dword ptr ss:[esp+0x24]
00401F42 .>mov byte ptr ss:[esp+0x38],0x1
00401F47 .>push eax
00401F48 .>call KeyGenMe.00401430 ; 对用户名的运算1
00401F4D .>add esp,0x10
00401F50 .>push eax
00401F51 .>lea ecx,dword ptr ss:[esp+0x18]
00401F55 .>mov byte ptr ss:[esp+0x30],0x3
00401F5A .>call <jmp.&MFC42.#858>
00401F5F .>lea ecx,dword ptr ss:[esp+0x18]
00401F63 .>mov byte ptr ss:[esp+0x2C],0x1
00401F68 .>call <jmp.&MFC42.#800>
00401F6D .>mov ecx,dword ptr ss:[esp+0x14]
00401F71 .>mov eax,dword ptr ds:[ecx-0x8]
00401F74 .>lea ecx,dword ptr ss:[esp+0x14]
00401F78 .>push eax
00401F79 .>push 0x0
00401F7B .>call <jmp.&MFC42.#2915>
00401F80 .>push eax
00401F81 .>call KeyGenMe.00401260
00401F86 .>push eax
00401F87 .>call KeyGenMe.004011D0 ; 对用户名的运算2
00401F8C .>push esi
00401F8D .>mov ebp,eax
00401F8F .>call KeyGenMe.004011D0 ; 对注册码的运算2
00401F94 .>push edi
00401F95 .>push ebp
00401F96 .>mov esi,eax
00401F98 .>call KeyGenMe.004015D0 ; 对用户名的运算3
00401F9D .>inc bl
00401F9F .>mov edi,eax
00401FA1 .>push ebx
00401FA2 .>push esi
00401FA3 .>call KeyGenMe.004015D0 ; 对注册码的运算3
00401FA8 .>push eax
00401FA9 .>push edi
00401FAA .>call KeyGenMe.004017A0 ; 判断最后操作后两字是否相等
00401FAF .>add esp,0x28 ; 如果eax==1,则正确
00401FB2 .>inc eax
00401FB3 .>call dword ptr ds:[eax*4+0x40410C]
00401FBA >>lea ecx,dword ptr ss:[esp+0x14]
00401FBE .>mov byte ptr ss:[esp+0x2C],0x0
00401FC3 .>call <jmp.&MFC42.#800>
00401FC8 .>lea ecx,dword ptr ss:[esp+0x10]
00401FCC .>mov dword ptr ss:[esp+0x2C],-0x1
00401FD4 .>call <jmp.&MFC42.#800>
00401FD9 .>mov ecx,dword ptr ss:[esp+0x24]
00401FDD .>pop edi
00401FDE .>pop esi
00401FDF .>pop ebp
00401FE0 .>mov dword ptr fs:[0],ecx
00401FE7 .>pop ebx
00401FE8 .>add esp,0x20
00401FEB .>retn
分析可以得到,用户名和注册码都是经过3次运算得到值后比较是否相等
因为这里运算后不是以普通的每个元素相邻的字符串形式,而是链表模式
struct XXX
{
char value;
XXX *next;
}
这样就很难看到直观的数据,很难分析
但是可以发现因为next指针的地址都在value的地址+4,所以可以用个小脚本来获取直观的数据
[AppleScript] 纯文本查看 复制代码 mov mem,XXXXXXXX
mov long,0
mov tmp,eax
loop:
mov [mem+long],[tmp],1
inc long
mov tmp,[tmp+4]
cmp tmp,0
jne loop
pause
pause
获取直观数据后就可以了解个大概
下面是测试的数据:
[AppleScript] 纯文本查看 复制代码 用户名:
11111
第一次运算后:
E1 D1 30 2D 4A
第二次运算后:
0E 01 0D 01 03 00 02 0D 04 0A
第三次运算后:
0E 0D 01 03 01 02 00 04 0D 0A
注册码:
222222222222
转化为16进制后:
22 22 22 22 22 22
第一次运算后:
F4 ED 50 2B 46
第二次运算后:
0F 04 0E 0D 05 00 02 0B 04 06
第三次运算后:
0F 0E 05 04 02 0D 04 00 06 0B
最后只要它们第3次运算后的值相等就成功了
然后可以一步步的解决:
对用户名的运算1:
00401F48 .>call KeyGenMe.00401430 ; 对用户名的运算1
[AppleScript] 纯文本查看 复制代码 00401430 /$ >push -0x1
00401432 |. >push KeyGenMe.0040250F ; SE 处理程序安装
00401437 |. >mov eax,dword ptr fs:[0]
0040143D |. >push eax
0040143E |. >mov dword ptr fs:[0],esp
00401445 |. >sub esp,0xC
00401448 |. >push ebx
00401449 |. >push esi
0040144A |. >push edi
0040144B |. >mov dword ptr ss:[esp+0x14],0x0
00401453 |. >lea ecx,dword ptr ss:[esp+0x10]
00401457 |. >mov dword ptr ss:[esp+0x20],0x2
0040145F |. >call <jmp.&MFC42.#540>
00401464 |. >mov eax,dword ptr ss:[esp+0x30]
00401468 |. >xor esi,esi
0040146A |. >xor edi,edi
0040146C |. >mov byte ptr ss:[esp+0x20],0x3
00401471 |. >mov ecx,dword ptr ds:[eax-0x8]
00401474 |. >test ecx,ecx
00401476 |. >jle short KeyGenMe.004014DC
00401478 |. >mov edx,dword ptr ss:[esp+0x2C]
0040147C |. >mov bl,byte ptr ss:[esp+0x34] ; 传进的参数[注册码的第一个值]
00401480 |> >/mov cl,byte ptr ds:[edi+eax] ; 逐个取用户名字符值
00401483 |. >|mov al,byte ptr ds:[esi+edx] ; 逐个取"52PoJie"字符串
00401486 |. >|xor al,cl ; 异或
00401488 |. >|cmp al,bl
0040148A |. >|mov byte ptr ss:[esp+0xC],al
0040148E |. >|jb short KeyGenMe.00401494
00401490 |. >|sub al,bl ; 减
00401492 |. >|jmp short KeyGenMe.004014AE
00401494 |> >|mov eax,dword ptr ss:[esp+0xC]
00401498 |. >|mov edx,dword ptr ss:[esp+0x34]
0040149C |. >|and eax,0xFF
004014A1 |. >|and edx,0xFF
004014A7 |. >|sub eax,edx ; 减
004014A9 |. >|add eax,0xFF
004014AE |> >|mov byte ptr ss:[esp+0xC],al
004014B2 |. >|mov bl,cl
004014B4 |. >|mov eax,dword ptr ss:[esp+0xC]
004014B8 |. >|lea ecx,dword ptr ss:[esp+0x10]
004014BC |. >|push eax
004014BD |. >|mov byte ptr ss:[esp+0x38],bl
004014C1 |. >|call <jmp.&MFC42.#940>
004014C6 |. >|mov edx,dword ptr ss:[esp+0x2C]
004014CA |. >|inc esi
004014CB |. >|cmp esi,dword ptr ds:[edx-0x8]
004014CE |. >|jl short KeyGenMe.004014D2 ; 超过从头开始
004014D0 |. >|xor esi,esi
004014D2 |> >|mov eax,dword ptr ss:[esp+0x30]
004014D6 |. >|inc edi
004014D7 |. >|cmp edi,dword ptr ds:[eax-0x8]
004014DA |.^>\jl short KeyGenMe.00401480
004014DC |> >mov esi,dword ptr ss:[esp+0x28]
004014E0 |. >lea ecx,dword ptr ss:[esp+0x10]
004014E4 |. >push ecx
004014E5 |. >mov ecx,esi
004014E7 |. >call <jmp.&MFC42.#535>
004014EC |. >mov ebx,0x1
004014F1 |. >mov dword ptr ss:[esp+0x14],ebx
004014F5 |. >lea ecx,dword ptr ss:[esp+0x10]
004014F9 |. >mov byte ptr ss:[esp+0x20],0x2
004014FE |. >call <jmp.&MFC42.#800>
00401503 |. >lea ecx,dword ptr ss:[esp+0x2C]
00401507 |. >mov byte ptr ss:[esp+0x20],bl
0040150B |. >call <jmp.&MFC42.#800>
00401510 |. >lea ecx,dword ptr ss:[esp+0x30]
00401514 |. >mov byte ptr ss:[esp+0x20],0x0
00401519 |. >call <jmp.&MFC42.#800>
0040151E |. >mov ecx,dword ptr ss:[esp+0x18]
00401522 |. >mov eax,esi
00401524 |. >pop edi
00401525 |. >pop esi
00401526 |. >pop ebx
00401527 |. >mov dword ptr fs:[0],ecx
0040152E |. >add esp,0x18
00401531 \. >retn
其中有一个参数是注册码16进制的第一个值
这样就可以写代码了
[C++] 纯文本查看 复制代码 string dealT1(string t0,string t1,char t2h)//用户名第1次运算,需要注册码16进制的前两位
{
int i=0;
int i0=0;
int th=t2h;
th&=0xFF;
string rs="";
while(t1)
{
int tmp=t1;
int tmp1=t0[i0];
tmp&=0xFF;
tmp1&=0xFF;
tmp^=tmp1;
tmp-=th;
if(tmp<0)
{
tmp&=0xFF;
tmp--;
}
char tmp3=tmp;
rs+=tmp3;
th=t1;
i0++;
if(i0==7)
i0=0;
i++;
}
return rs;
}
第二次运算只是将第一次运算结果的高位低位分离
CALL在004011D0
转化为代码为
[C++] 纯文本查看 复制代码 string deal2(string s)//运算的第2次,高位低位分开
{
string str="";
int i=0;
while(i<s.length())
{
int v=s;
v&=0xFF;
char c1=v/16;
char c2=v%16;
str+=c1;
str+=c2;
i++;
}
return str;
}
用户名的第3次运算为将第2次结果重新排序
[AppleScript] 纯文本查看 复制代码 004016FF |> \8B7C24 1C mov edi,dword ptr ss:[esp+0x1C] ; 案例 0 --> 分支 0040160C
00401703 |. 57 push edi
00401704 |. E8 37FEFFFF call KeyGenMe.00401540
00401709 |. 99 cdq
0040170A |. 2BC2 sub eax,edx
0040170C |. 83C4 04 add esp,0x4
0040170F |. D1F8 sar eax,1
00401711 |. 83F8 01 cmp eax,0x1
00401714 |. 7E 4F jle short KeyGenMe.00401765
00401716 |. 8D68 FF lea ebp,dword ptr ds:[eax-0x1]
00401719 |> 6A 01 /push 0x1 ; 取第一个元素
0040171B |. 57 |push edi
0040171C |. E8 2FFEFFFF |call KeyGenMe.00401550
00401721 |. 6A 08 |push 0x8
00401723 |. 8BFA |mov edi,edx
00401725 |. 8806 |mov byte ptr ds:[esi],al
00401727 |. E8 EC090000 |call <jmp.&MFC42.#823> ; 删除
0040172C |. 33C9 |xor ecx,ecx
0040172E |. 8946 04 |mov dword ptr ds:[esi+0x4],eax
00401731 |. 8908 |mov dword ptr ds:[eax],ecx
00401733 |. 6A 02 |push 0x2 ; 取第二个元素
00401735 |. 8948 04 |mov dword ptr ds:[eax+0x4],ecx
00401738 |. 8B76 04 |mov esi,dword ptr ds:[esi+0x4]
0040173B |. 57 |push edi
0040173C |. E8 0FFEFFFF |call KeyGenMe.00401550
00401741 |. 6A 08 |push 0x8
00401743 |. 8BD8 |mov ebx,eax
00401745 |. 8BFA |mov edi,edx
00401747 |. E8 CC090000 |call <jmp.&MFC42.#823> ; 删除
0040174C |. 33D2 |xor edx,edx
0040174E |. 8946 04 |mov dword ptr ds:[esi+0x4],eax
00401751 |. 8910 |mov dword ptr ds:[eax],edx
00401753 |. 83C4 18 |add esp,0x18
00401756 |. 8950 04 |mov dword ptr ds:[eax+0x4],edx
00401759 |. 881E |mov byte ptr ds:[esi],bl
0040175B |. 8B76 04 |mov esi,dword ptr ds:[esi+0x4]
0040175E |. 4D |dec ebp
0040175F |.^ 75 B8 \jnz short KeyGenMe.00401719 ; 循环直到都取完
00401761 |. 8B5C24 10 mov ebx,dword ptr ss:[esp+0x10]
00401765 |> 6A 01 push 0x1
00401767 |. 57 push edi
00401768 |. E8 E3FDFFFF call KeyGenMe.00401550
0040176D |. 6A 08 push 0x8
0040176F |. 8BFA mov edi,edx
00401771 |. 8806 mov byte ptr ds:[esi],al
00401773 |. E8 A0090000 call <jmp.&MFC42.#823>
00401778 |. 33C9 xor ecx,ecx
0040177A |. 8946 04 mov dword ptr ds:[esi+0x4],eax
0040177D |. 8908 mov dword ptr ds:[eax],ecx
0040177F |. 6A 01 push 0x1
00401781 |. 8948 04 mov dword ptr ds:[eax+0x4],ecx
00401784 |. 8B76 04 mov esi,dword ptr ds:[esi+0x4]
00401787 |. 57 push edi
00401788 |. E8 C3FDFFFF call KeyGenMe.00401550
0040178D |. 83C4 14 add esp,0x14
00401790 |. 895424 14 mov dword ptr ss:[esp+0x14],edx
00401794 |. 8806 mov byte ptr ds:[esi],al
00401796 |> 5F pop edi ; 分支 0040160C 默认案例
00401797 |. 5E pop esi
00401798 |. 8BC3 mov eax,ebx
0040179A |. 5D pop ebp
0040179B |. 5B pop ebx
0040179C |. 83C4 08 add esp,0x8
0040179F \. C3 retn
写成代码很简单:
[C++] 纯文本查看 复制代码 string dealT1_1(string s)//用户名第3次运算,
{
string s0=s;
string str="";
while(s0.length()!=0)
{
str+=s0[0];
s0.erase(0,1);
if(s0.length()==1)
{
str+=s0[0];
s0.erase(0,1);
}
else
{
str+=s0[1];
s0.erase(1,1);
}
}
return str;
}
然后就是注册码第3次运算的逆运算了
先看看正运算:
[AppleScript] 纯文本查看 复制代码 0040161C |. 8B7424 1C mov esi,dword ptr ss:[esp+0x1C] ; 案例 1 --> 分支 0040160C
00401620 |. 56 push esi
00401621 |. E8 1AFFFFFF call KeyGenMe.00401540
00401626 |. 99 cdq
00401627 |. 2BC2 sub eax,edx
00401629 |. 6A 01 push 0x1 ; 先取第1个
0040162B |. 8BE8 mov ebp,eax
0040162D |. 56 push esi
0040162E |. D1FD sar ebp,1
00401630 |. 83ED 02 sub ebp,0x2
00401633 |. E8 18FFFFFF call KeyGenMe.00401550
00401638 |. 6A 02 push 0x2 ; 再取第3个
0040163A |. 52 push edx
0040163B |. 8803 mov byte ptr ds:[ebx],al
0040163D |. E8 0EFFFFFF call KeyGenMe.00401550
00401642 |. 6A 08 push 0x8
00401644 |. 894424 28 mov dword ptr ss:[esp+0x28],eax
00401648 |. 8BFA mov edi,edx
0040164A |. E8 C90A0000 call <jmp.&MFC42.#823> ; 删除
0040164F |. 33D2 xor edx,edx
00401651 |. 8943 04 mov dword ptr ds:[ebx+0x4],eax
00401654 |. 8910 mov dword ptr ds:[eax],edx
00401656 |. 83C4 18 add esp,0x18
00401659 |. 8950 04 mov dword ptr ds:[eax+0x4],edx
0040165C |. 8B73 04 mov esi,dword ptr ds:[ebx+0x4]
0040165F |. 8A4424 10 mov al,byte ptr ss:[esp+0x10]
00401663 |. 83FD 01 cmp ebp,0x1
00401666 |. 8806 mov byte ptr ds:[esi],al
00401668 |. 7C 46 jl short KeyGenMe.004016B0
0040166A |> 6A 08 /push 0x8
0040166C |. E8 A70A0000 |call <jmp.&MFC42.#823> ; 删除
00401671 |. 33C9 |xor ecx,ecx
00401673 |. 8946 04 |mov dword ptr ds:[esi+0x4],eax
00401676 |. 8908 |mov dword ptr ds:[eax],ecx
00401678 |. 6A 03 |push 0x3 ; 取第3个
0040167A |. 8948 04 |mov dword ptr ds:[eax+0x4],ecx
0040167D |. 8B76 04 |mov esi,dword ptr ds:[esi+0x4]
00401680 |. 57 |push edi
00401681 |. E8 CAFEFFFF |call KeyGenMe.00401550
00401686 |. 6A 08 |push 0x8
00401688 |. 8BFA |mov edi,edx
0040168A |. 8806 |mov byte ptr ds:[esi],al
0040168C |. E8 870A0000 |call <jmp.&MFC42.#823> ; 删除
00401691 |. 33D2 |xor edx,edx
00401693 |. 8946 04 |mov dword ptr ds:[esi+0x4],eax
00401696 |. 8910 |mov dword ptr ds:[eax],edx
00401698 |. 6A 01 |push 0x1 ; 取第一个
0040169A |. 8950 04 |mov dword ptr ds:[eax+0x4],edx
0040169D |. 8B76 04 |mov esi,dword ptr ds:[esi+0x4]
004016A0 |. 57 |push edi
004016A1 |. E8 AAFEFFFF |call KeyGenMe.00401550
004016A6 |. 83C4 18 |add esp,0x18
004016A9 |. 4D |dec ebp
004016AA |. 8806 |mov byte ptr ds:[esi],al
004016AC |. 8BFA |mov edi,edx
004016AE |.^ 75 BA \jnz short KeyGenMe.0040166A ; 循环直到取完
004016B0 |> 6A 08 push 0x8
004016B2 |. E8 610A0000 call <jmp.&MFC42.#823>
004016B7 |. 33C9 xor ecx,ecx
004016B9 |. 8946 04 mov dword ptr ds:[esi+0x4],eax
004016BC |. 8908 mov dword ptr ds:[eax],ecx
004016BE |. 6A 02 push 0x2
004016C0 |. 8948 04 mov dword ptr ds:[eax+0x4],ecx
004016C3 |. 8B76 04 mov esi,dword ptr ds:[esi+0x4]
004016C6 |. 57 push edi
004016C7 |. E8 84FEFFFF call KeyGenMe.00401550
004016CC |. 6A 08 push 0x8
004016CE |. 8BFA mov edi,edx
004016D0 |. 8806 mov byte ptr ds:[esi],al
004016D2 |. E8 410A0000 call <jmp.&MFC42.#823>
004016D7 |. 33D2 xor edx,edx
004016D9 |. 8946 04 mov dword ptr ds:[esi+0x4],eax
004016DC |. 8910 mov dword ptr ds:[eax],edx
004016DE |. 6A 01 push 0x1
004016E0 |. 8950 04 mov dword ptr ds:[eax+0x4],edx
004016E3 |. 8B76 04 mov esi,dword ptr ds:[esi+0x4]
004016E6 |. 57 push edi
004016E7 |. E8 64FEFFFF call KeyGenMe.00401550
004016EC |. 83C4 18 add esp,0x18
004016EF |. 8806 mov byte ptr ds:[esi],al
004016F1 |. 8BC3 mov eax,ebx
004016F3 |. 895424 14 mov dword ptr ss:[esp+0x14],edx
004016F7 |. 5F pop edi
004016F8 |. 5E pop esi
004016F9 |. 5D pop ebp
004016FA |. 5B pop ebx
004016FB |. 83C4 08 add esp,0x8
004016FE |. C3 retn
逆运算代码为:
[C++] 纯文本查看 复制代码 string dealT2_1(string s)//注册码第3次运算的逆运算
{
string s0=s;
string str="";
int i=s0.length()-1;
str+=s0;
str+=s0[i-1];
i-=2;
while(i>1)
{
str.insert(0,s0,i,1);
i--;
str.insert(2,s0,i,1);
i--;
}
str.insert(1,s0,1,1);
str.insert(0,s0,0,1);
return str;
}
然后是第二次运算的逆运算
就是奇数变高位,偶数变低位
[C++] 纯文本查看 复制代码 string deal2_1(string s)//第2次运算的逆运算
{
string str="";
int i=0;
while(i<s.length())
{
char c=s*16;
c+=s[i+1];
str+=c;
i+=2;
}
return str;
}
最后就是注册码第一次运算的逆运算了:
先看看call:
[AppleScript] 纯文本查看 复制代码
; 参数有注册码16进制的第一个,注册码第二位开始的链表,"52PoJie"
004013D0 /$ 8B4C24 08 mov ecx,dword ptr ss:[esp+0x8]
004013D4 |. 8B4424 04 mov eax,dword ptr ss:[esp+0x4]
004013D8 |. 56 push esi
004013D9 |. 33F6 xor esi,esi
004013DB |> 33D2 /xor edx,edx
004013DD |. 8A1406 |mov dl,byte ptr ds:[esi+eax] ; 逐个取"52PoJie"字符
004013E0 |. 8BC2 |mov eax,edx
004013E2 |. 33D2 |xor edx,edx
004013E4 |. 8A11 |mov dl,byte ptr ds:[ecx] ; 逐个取注册码的16进制
004013E6 |. 33C2 |xor eax,edx ; 异或
004013E8 |. 8B5424 10 |mov edx,dword ptr ss:[esp+0x10] ; 这个参数是注册码的前1位16进制
004013EC |. 81E2 FF000000 |and edx,0xFF
004013F2 |. 2BC2 |sub eax,edx ; 相减
004013F4 |. 79 05 |jns short KeyGenMe.004013FB ; 符号问题
004013F6 |. 05 FF000000 |add eax,0xFF
004013FB |> 8A11 |mov dl,byte ptr ds:[ecx]
004013FD |. 8801 |mov byte ptr ds:[ecx],al
004013FF |. 8B4424 08 |mov eax,dword ptr ss:[esp+0x8]
00401403 |. 8B49 04 |mov ecx,dword ptr ds:[ecx+0x4]
00401406 |. 885424 10 |mov byte ptr ss:[esp+0x10],dl
0040140A |. 46 |inc esi
0040140B |. 3B70 F8 |cmp esi,dword ptr ds:[eax-0x8] ; 超出"52PoJie"长度,从头开始
0040140E |. 7C 02 |jl short KeyGenMe.00401412
00401410 |. 33F6 |xor esi,esi
00401412 |> 85C9 |test ecx,ecx
00401414 |.^ 75 C5 \jnz short KeyGenMe.004013DB ; 直到取完
00401416 |. 8D4C24 08 lea ecx,dword ptr ss:[esp+0x8]
0040141A |. E8 E10C0000 call <jmp.&MFC42.#800>
0040141F |. 5E pop esi
00401420 \. C3 retn
这个的逆运算是我的最蛋疼的了,因为这个符号问题
[C++] 纯文本查看 复制代码 string dealT2_2(string s,string t0,char t2h)//注册码第一次运算的逆运算
{
string s0=s;
string str="";
str+=t2h;
int i=0;
int i0=0;
int tmp;
while(i<s0.length())
{
int p0=str;
tmp=s0;
tmp+=p0;
tmp^=t0[i0];
int p1=tmp^t0[i0];
p1=p1&0xFF;
int p2=p0&0xFF;
p1=p1-p2;
if(p1<0)
{
tmp=s0;
tmp&=0xFF;
tmp+=p0;
tmp++;
tmp^=t0[i0];
}
str+=tmp;
i++;
i0++;
if(i0==7)
i0=0;
}
return str;
}
所以注册机就可以完成了,先输入用户名,再输入一个两位的16进制数作为注册码的前两位
一个用户名有很多个注册码。
注册机:
代码文件:
vc6工程:
|
免费评分
-
查看全部评分
|