飘云阁

 找回密码
 加入我们

QQ登录

只需一步,快速开始

查看: 3066|回复: 4

[分析] 论坛九宫格CM的算法简单分析

[复制链接]
  • TA的每日心情
    开心
    2019-2-26 11:14
  • 签到天数: 459 天

    [LV.9]以坛为家II

    发表于 2018-11-27 20:18:21 | 显示全部楼层 |阅读模式
    本帖最后由 wgz001 于 2018-11-27 20:22 编辑

    目标地址:类似九宫格算法Crackmehttps://www.chinapyg.com/thread-121565-1-1.html
    (出处: 飘云阁(PYG官方论坛) )
    简单分析:
    一开始作者没有判断为0的情况,比较容易就搞定了,开始我还自己写程序爆破,因为也没看懂算法,现在想想有点好笑,算法的话不难,但是我觉得作者设计的比较好,上一下OD分析的记录,注册码分为18位,我记为N1......N18
    [Asm] 纯文本查看 复制代码
    004013B7  |.  83C4 08       add esp,0x8
    004013BA  |.  F2:AE         repne scas byte ptr es:[edi]
    004013BC  |.  F7D1          not ecx
    004013BE  |.  49            dec ecx
    004013BF  |.  83F9 12       cmp ecx,0x12                             ;  比较注册码长度
    004013C2  |.  0F84 83000000 je test.0040144B
    004013C8  |.  8DB424 E00000>lea esi,dword ptr ss:[esp+0xE0]
    004013CF  |.  BF 19000000   mov edi,0x19
    
    

    这样注释好了,下面就好分析了
    [Asm] 纯文本查看 复制代码
    0040144B  |> \0FBE8424 C401>movsx eax,byte ptr ss:[esp+0x1C4]
    00401453  |.  0FBE9424 C501>movsx edx,byte ptr ss:[esp+0x1C5]
    0040145B  |.  8D0C80        lea ecx,dword ptr ds:[eax+eax*4]
    0040145E  |.  8D844A F0FDFF>lea eax,dword ptr ds:[edx+ecx*2-0x210]
    00401465  |.  83F8 20       cmp eax,0x20                             ;  这里固定了前两位为:32
    00401468  |.  0F85 08030000 jnz test.00401776
    0040146E  |.  0FBE8424 CC01>movsx eax,byte ptr ss:[esp+0x1CC]
    00401476  |.  0FBE9424 CD01>movsx edx,byte ptr ss:[esp+0x1CD]
    0040147E  |.  8D0C80        lea ecx,dword ptr ds:[eax+eax*4]
    00401481  |.  8D844A F0FDFF>lea eax,dword ptr ds:[edx+ecx*2-0x210]
    00401488  |.  83F8 10       cmp eax,0x10                             ;  这里固定了第9,10位为:16
    0040148B  |.  0F85 E5020000 jnz test.00401776
    00401491  |.  0FBE8424 C601>movsx eax,byte ptr ss:[esp+0x1C6]        ;  N3---->EAX
    00401499  |.  0FBE9424 C701>movsx edx,byte ptr ss:[esp+0x1C7]        ;  N4---->EDX
    004014A1  |.  8D0C80        lea ecx,dword ptr ds:[eax+eax*4]         ;  N3*5---->ECX
    004014A4  |.  8D844A F0FDFF>lea eax,dword ptr ds:[edx+ecx*2-0x210]   ;  (N4+N3*0xA-0x210)---->EAX
    004014AB  |.  0FBE9424 C901>movsx edx,byte ptr ss:[esp+0x1C9]        ;  N6---->EDX
    004014B3  |.  894424 14     mov dword ptr ss:[esp+0x14],eax          ;  save eax
    004014B7  |.  0FBE8424 C801>movsx eax,byte ptr ss:[esp+0x1C8]        ;  N5---->EAX
    004014BF  |.  8D0C80        lea ecx,dword ptr ds:[eax+eax*4]         ;  N5*5---->ECX
    004014C2  |.  0FBE8424 CA01>movsx eax,byte ptr ss:[esp+0x1CA]        ;  N7---->EAX
    004014CA  |.  8DAC4A F0FDFF>lea ebp,dword ptr ds:[edx+ecx*2-0x210]   ;  (N6+N5*0xA-0x210)----->ebp
    004014D1  |.  0FBE8C24 CB01>movsx ecx,byte ptr ss:[esp+0x1CB]        ;  N8---->ECX
    004014D9  |.  8D0480        lea eax,dword ptr ds:[eax+eax*4]         ;  N7*5---->EAX
    004014DC  |.  896C24 18     mov dword ptr ss:[esp+0x18],ebp          ;  save ebp
    004014E0  |.  8DBC41 F0FDFF>lea edi,dword ptr ds:[ecx+eax*2-0x210]   ;  (N8+N7*0xA-0x210)----->EDI
    004014E7  |.  0FBE8424 CE01>movsx eax,byte ptr ss:[esp+0x1CE]        ;  N11---->EAX
    004014EF  |.  8D1480        lea edx,dword ptr ds:[eax+eax*4]         ;  N11*5---->EDX
    004014F2  |.  0FBE8424 CF01>movsx eax,byte ptr ss:[esp+0x1CF]        ;  N12---->EAX
    004014FA  |.  8D8C50 F0FDFF>lea ecx,dword ptr ds:[eax+edx*2-0x210]   ;  (N12+N11*0xA-0x210)----->ECX
    00401501  |.  0FBE8424 D001>movsx eax,byte ptr ss:[esp+0x1D0]        ;  N13---->EAX
    00401509  |.  894C24 10     mov dword ptr ss:[esp+0x10],ecx          ;  save ecx
    0040150D  |.  8D1480        lea edx,dword ptr ds:[eax+eax*4]         ;  N13*5---->EDX
    00401510  |.  0FBE8424 D101>movsx eax,byte ptr ss:[esp+0x1D1]        ;  N14---->EAX
    00401518  |.  8DB450 F0FDFF>lea esi,dword ptr ds:[eax+edx*2-0x210]   ;  (N14+N13*0xA-0x210)----->ESI
    0040151F  |.  0FBE8424 D201>movsx eax,byte ptr ss:[esp+0x1D2]        ;  N15----->EAX
    00401527  |.  0FBE9424 D301>movsx edx,byte ptr ss:[esp+0x1D3]        ;  N16----->EDX
    0040152F  |.  8D0C80        lea ecx,dword ptr ds:[eax+eax*4]         ;  N15*5----->ECX
    00401532  |.  0FBE8424 D401>movsx eax,byte ptr ss:[esp+0x1D4]        ;  N17----->EAX
    0040153A  |.  8D8C4A F0FDFF>lea ecx,dword ptr ds:[edx+ecx*2-0x210]   ;  (N16+N15*0xA-0x210)------>ECX
    00401541  |.  0FBE9424 D501>movsx edx,byte ptr ss:[esp+0x1D5]        ;  N18----->EDX
    00401549  |.  8D0480        lea eax,dword ptr ds:[eax+eax*4]         ;  N17*5----->EAX
    0040154C  |.  8D8442 F0FDFF>lea eax,dword ptr ds:[edx+eax*2-0x210]   ;  (N18+N17*0xA-0x210)---->EAX
    
    


    [Asm] 纯文本查看 复制代码
    00401553  |.  3BC3          cmp eax,ebx                              ;  新增加的判断17,18位是不是为0
    00401555  |.  0F84 BD010000 je test.00401718
    
    

    下面就是九宫格中,相乘后的比较,分了5部分
    [Asm] 纯文本查看 复制代码
    0040155B  |.  8B5424 10     mov edx,dword ptr ss:[esp+0x10]
    0040155F  |.  0FAF6C24 14   imul ebp,dword ptr ss:[esp+0x14]
    00401564  |.  0FAFD7        imul edx,edi
    00401567  |.  C1E2 04       shl edx,0x4
    0040156A  |.  C1E5 05       shl ebp,0x5
    0040156D  |.  3BEA          cmp ebp,edx
    0040156F  |.  0F85 45010000 jnz test.004016BA
    00401575  |.  8BE8          mov ebp,eax
    00401577  |.  0FAFE9        imul ebp,ecx
    0040157A  |.  0FAFEE        imul ebp,esi
    0040157D  |.  3BD5          cmp edx,ebp
    0040157F  |.  0F85 35010000 jnz test.004016BA
    00401585  |.  0FAF4C24 14   imul ecx,dword ptr ss:[esp+0x14]
    0040158A  |.  8BD6          mov edx,esi
    0040158C  |.  0FAFD7        imul edx,edi
    0040158F  |.  C1E1 04       shl ecx,0x4
    00401592  |.  C1E2 05       shl edx,0x5
    00401595  |.  3BD1          cmp edx,ecx
    00401597  |.  0F85 BF000000 jnz test.0040165C
    0040159D  |.  8BF8          mov edi,eax
    0040159F  |.  8B5424 18     mov edx,dword ptr ss:[esp+0x18]
    004015A3  |.  0FAF7C24 10   imul edi,dword ptr ss:[esp+0x10]
    004015A8  |.  0FAFFA        imul edi,edx
    004015AB  |.  3BCF          cmp ecx,edi
    004015AD  |.  0F85 A9000000 jnz test.0040165C
    004015B3  |.  0FAFF2        imul esi,edx
    004015B6  |.  C1E6 04       shl esi,0x4
    004015B9  |.  C1E0 09       shl eax,0x9
    004015BC  |.  3BC6          cmp eax,esi
    004015BE  |.  75 3E         jnz short test.004015FE
    
    

    上面的整理后就是这样子
    (N12+N11*0xA-0x210)*(N8+N7*0xA-0x210)*0x10== (N6+N5*0xA-0x210)*(N4+N3*0xA-0x210)*0x20

    (N18+N17*0xA-0x210)*(N16+N15*0xA-0x210)*(N14+N13*0xA-0x210)==(N12+N11*0xA-0x210)*(N8+N7*0xA-0x210)*0x10

    (N16+N15*0xA-0x210)*(N4+N3*0xA-0x210)*0x10== (N14+N13*0xA-0x210)*(N8+N7*0xA-0x210)*0x20

    (N18+N17*0xA-0x210)*(N12+N11*0xA-0x210)*(N6+N5*0xA-0x210)==(N16+N15*0xA-0x210)*(N4+N3*0xA-0x210)*0x10

    (N6+N5*0xA-0x210)*(N14+N13*0xA-0x210)*0x10==(N18+N17*0xA-0x210)*0x200

    这5部分类似这个图

    解释:N1N2  就类似表中的12,N1为十位数,N2为个位数,组成一个两位整数.........N17,N18就是表中的17,18,N17为十位数,N18为个位数,组成一个两位整数,  表中相同颜色的线中的三个数字相乘要相等。
    最后可以凑出合法的注册码,如图





                               感谢GG老师及一起玩游戏小组全体成员!!



    来自群组: 一起玩游戏

    本帖子中包含更多资源

    您需要 登录 才可以下载或查看,没有账号?加入我们

    x

    评分

    参与人数 1威望 +2 收起 理由
    hoy0a1d + 2 赞一个,这个帖子很给力!

    查看全部评分

    PYG19周年生日快乐!
  • TA的每日心情
    无聊
    2023-3-14 13:51
  • 签到天数: 31 天

    [LV.5]常住居民I

    发表于 2018-11-28 13:30:21 | 显示全部楼层
    膜拜楼主,这个算法设计也是在看书的过程中突然想到的  就实现了一下  

    点评

    666 羡慕会编程的表哥,自己的想法可以用程序实现出来,赞  详情 回复 发表于 2018-11-28 17:48
    PYG19周年生日快乐!
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    无聊
    2023-3-14 13:51
  • 签到天数: 31 天

    [LV.5]常住居民I

    发表于 2018-11-28 13:34:21 | 显示全部楼层
    本帖最后由 hoy0a1d 于 2018-12-5 14:50 编辑

    借楼发一下源码吧

    [C++] 纯文本查看 复制代码
    #include <iostream>
    #include <string.h>
    using namespace std;
    
    int main()
    {
            char RegKey[200];
            int tip[21] = {80, 108, 101, 97, 115, 101, 0, 105, 110, 112, 117, 116, 0,
                    82, 101, 103, 75, 101, 121, 58, 0};
            // Please input RegKey: 
            int ok[32] = {86, 101, 114, 121, 0, 103, 111, 111, 100, 33, 0, 89, 111, 117, 114, 0,
                    82, 101, 103, 75, 101, 121, 0, 105, 115, 0, 82, 105, 103, 104, 116, 33};
            // Very good! Your RegKey is Right!
            int no[28] = {83, 111, 114, 114, 121, 33, 0, 89, 111, 117, 114, 0,
                    82, 101, 103, 75, 101, 121, 0, 105, 115, 0, 87, 114, 111, 110, 103, 33};
            // Sorry! Your RegKey is Wrong!
            int TestLen[25] = {82, 101, 103, 75, 101, 121, 0, 108, 101, 110, 103, 116, 104, 0,
                    109, 117, 115, 116, 0, 98, 101, 0, 49, 56, 46};
            // RegKey length must be 18.
            
            for(int i = 0; i < 21; i++)
                    cout << (char)tip[i];
            cin >> RegKey;
            
            int key1 = 32, key2, key3, key4, key5 = 16, key6, key7, key8, key9;
            
            // 判断输入位数是否为 18  若不等于 18 输出提示
            if(strlen(RegKey) != 18)
            {
                    for(int i = 0; i < 25; i++)
                            cout << (char)TestLen[i];
                    cout << endl;
            }
            else
            {
                    /* 
                            ————————————————
                            | 32 | xx | xx |
                            |    |    |    |
                            | xx | 16 | xx |
                            |    |    |    |
                            | xx | xx | xx |
                            ————————————————
                    */
                    // 判断左上角是否为 32   且中心是否为 16
                    if((RegKey[0] - '0') * 10 + (RegKey[1] - '0') == key1
                            && (RegKey[8] - '0') * 10 + (RegKey[9] - '0') == key5)
                    {
                            key2 = (RegKey[2] - '0') * 10 + (RegKey[3] - '0');
                            key3 = (RegKey[4] - '0') * 10 + (RegKey[5] - '0');
                            key4 = (RegKey[6] - '0') * 10 + (RegKey[7] - '0');
                            key6 = (RegKey[10] - '0') * 10 + (RegKey[11] - '0');
                            key7 = (RegKey[12] - '0') * 10 + (RegKey[13] - '0');
                            key8 = (RegKey[14] - '0') * 10 + (RegKey[15] - '0');
                            key9 = (RegKey[16] - '0') * 10 + (RegKey[17] - '0');
                            
                            // 这里判断一下右下角是否为 0  因为右下角为 0 则除了已给出的 32 和 16
                            // 其他部位全部填 0 则可正确注册
                            if(key9 != 0)
                            {
                                    // 判断横排三组数相乘是否相等
                                    if(key1 * key2 * key3 == key4 * key5 * key6
                                            && key4 * key5 * key6 == key7 * key8 * key9)
                                    {
                                            // 判断竖排三组数相乘是否相等
                                            if(key1 * key4 * key7 == key2 * key5 * key8
                                                    && key2 * key5 * key8 == key3 * key6 * key9)
                                            {
                                                    // 判断对角两组数相乘是否相等
                                                    if(key1 * key5 * key9 == key3 * key5 * key7)
                                                    {
                                                            for(int i = 0; i < 32; i++)
                                                                    cout << (char)ok[i];
                                                            cout << endl;
                                                    }
                                                    else
                                                    {
                                                            for(int i = 0; i < 28; i++)
                                                                    cout << (char)no[i];
                                                            cout << endl;
                                                    }
                                            }
                                            else
                                            {
                                                    for(int i = 0; i < 28; i++)
                                                            cout << (char)no[i];
                                                    cout << endl;
                                            }
                                    }
                                    else
                                    {
                                            for(int i = 0; i < 28; i++)
                                                    cout << (char)no[i];
                                            cout << endl;
                                    }
                            }
                            else
                            {
                                    for(int i = 0; i < 28; i++)
                                            cout << (char)no[i];
                                    cout << endl;
                            }
                    }
                    else
                    {
                            for(int i = 0; i < 28; i++)
                                    cout << (char)no[i];
                            cout << endl;
                    }
            }
            return 0;
    }
    

    评分

    参与人数 1威望 +2 飘云币 +2 收起 理由
    wgz001 + 2 + 2 开源666

    查看全部评分

    PYG19周年生日快乐!
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    2019-2-26 11:14
  • 签到天数: 459 天

    [LV.9]以坛为家II

     楼主| 发表于 2018-11-28 17:48:37 | 显示全部楼层
    hoy0a1d 发表于 2018-11-28 13:30
    膜拜楼主,这个算法设计也是在看书的过程中突然想到的  就实现了一下

    666
    羡慕会编程的表哥,自己的想法可以用程序实现出来,赞
    PYG19周年生日快乐!
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 登录 | 加入我们

    本版积分规则

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