wgz001 发表于 2018-11-27 20:18:21

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

本帖最后由 wgz001 于 2018-11-27 20:22 编辑

目标地址:类似九宫格算法Crackmehttps://www.chinapyg.com/thread-121565-1-1.html
(出处: 飘云阁(PYG官方论坛) )
简单分析:
一开始作者没有判断为0的情况,比较容易就搞定了,开始我还自己写程序爆破,因为也没看懂算法,现在想想有点好笑,算法的话不难,但是我觉得作者设计的比较好,上一下OD分析的记录,注册码分为18位,我记为N1......N18
004013B7|.83C4 08       add esp,0x8
004013BA|.F2:AE         repne scas byte ptr es:
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:
004013CF|.BF 19000000   mov edi,0x19


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



00401553|.3BC3          cmp eax,ebx                              ;新增加的判断17,18位是不是为0
00401555|.0F84 BD010000 je test.00401718


下面就是九宫格中,相乘后的比较,分了5部分
0040155B|.8B5424 10   mov edx,dword ptr ss:
0040155F|.0FAF6C24 14   imul ebp,dword ptr ss:
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:
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:
004015A3|.0FAF7C24 10   imul edi,dword ptr ss:
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老师及一起玩游戏小组全体成员!!



一起玩游戏

smallhorse 发表于 2018-11-28 01:34:18

已跪拜!

hoy0a1d 发表于 2018-11-28 13:30:21

膜拜楼主,这个算法设计也是在看书的过程中突然想到的就实现了一下

hoy0a1d 发表于 2018-11-28 13:34:21

本帖最后由 hoy0a1d 于 2018-12-5 14:50 编辑

借楼发一下源码吧

#include <iostream>
#include <string.h>
using namespace std;

int main()
{
      char RegKey;
      int tip = {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 = {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 = {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 = {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;
      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;
                cout << endl;
      }
      else
      {
                /*
                        ————————————————
                        | 32 | xx | xx |
                        |    |    |    |
                        | xx | 16 | xx |
                        |    |    |    |
                        | xx | xx | xx |
                        ————————————————
                */
                // 判断左上角是否为 32   且中心是否为 16
                if((RegKey - '0') * 10 + (RegKey - '0') == key1
                        && (RegKey - '0') * 10 + (RegKey - '0') == key5)
                {
                        key2 = (RegKey - '0') * 10 + (RegKey - '0');
                        key3 = (RegKey - '0') * 10 + (RegKey - '0');
                        key4 = (RegKey - '0') * 10 + (RegKey - '0');
                        key6 = (RegKey - '0') * 10 + (RegKey - '0');
                        key7 = (RegKey - '0') * 10 + (RegKey - '0');
                        key8 = (RegKey - '0') * 10 + (RegKey - '0');
                        key9 = (RegKey - '0') * 10 + (RegKey - '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;
                                                      cout << endl;
                                                }
                                                else
                                                {
                                                      for(int i = 0; i < 28; i++)
                                                                cout << (char)no;
                                                      cout << endl;
                                                }
                                        }
                                        else
                                        {
                                                for(int i = 0; i < 28; i++)
                                                      cout << (char)no;
                                                cout << endl;
                                        }
                              }
                              else
                              {
                                        for(int i = 0; i < 28; i++)
                                                cout << (char)no;
                                        cout << endl;
                              }
                        }
                        else
                        {
                              for(int i = 0; i < 28; i++)
                                        cout << (char)no;
                              cout << endl;
                        }
                }
                else
                {
                        for(int i = 0; i < 28; i++)
                              cout << (char)no;
                        cout << endl;
                }
      }
      return 0;
}

wgz001 发表于 2018-11-28 17:48:37

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

666
羡慕会编程的表哥,自己的想法可以用程序实现出来,赞
页: [1]
查看完整版本: 论坛九宫格CM的算法简单分析