吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 6875|回复: 12
收起左侧

[CrackMe] 【吾爱2013CM大赛解答】--KeyGenMe-- a070458 -- 算法分析-注册机编写[〇〇木一]

[复制链接]
〇〇木一 发表于 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工程:

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册[Register]

x

点评

100%正确 主要我都用链表的方式来弄增加强度!膜拜 请收下我的膝盖  发表于 2013-12-16 21:14

免费评分

参与人数 4热心值 +4 收起 理由
a070458 + 1 我很赞同!
Chief + 1 吾爱破解2013CM大赛,有你更精彩!
Cari丶 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩.
brack + 1 感谢发布算法分析.

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

brack 发表于 2013-12-16 10:28
厉害...膜拜算法牛.学习了.
258239234 发表于 2013-12-16 10:37
Cari丶 发表于 2013-12-16 11:01
头像被屏蔽
bambooqj 发表于 2013-12-16 11:44
师傅 你太流弊了。。。
xjun 发表于 2013-12-16 11:54
我是来膜拜的,感谢大牛分享精彩文章。
头像被屏蔽
Ylca 发表于 2013-12-16 11:57
xjun 发表于 2013-12-16 11:54
我是来膜拜的,感谢大牛分享精彩文章。

膜拜xjun大牛 !!
YooGa 发表于 2013-12-16 12:03
唉,好复杂的样子
20120427 发表于 2013-12-16 17:21
膜拜大牛
87412598 发表于 2013-12-16 17:24
楼主辛苦了、
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则 警告:本版块禁止回复与主题无关非技术内容,违者重罚!

快速回复 收藏帖子 返回列表 搜索

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-4-29 05:07

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表