吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 5560|回复: 19
收起左侧

[原创] 010Editor算法分析模拟注册机实现

  [复制链接]
Nattevak 发表于 2021-12-5 19:32
本帖最后由 Nattevak 于 2021-12-6 19:13 编辑

        此处接上一篇帖子 爆破过010Editor注册 ,接下来分析010Editor的序列号算法,实现注册机
上一篇链接:

[url=爆破过010Editor注册 https://www.52pojie.cn/thread-1555732-1-1.html (出处: 吾爱破解论坛)]爆破过010Editor注册[/url]

1.算法分析步骤记录一
①继续来到我们之前找到的关键函数的位置,从这里开始分析,由于这里赋值了ECX,所以我们数据窗口跟随一下看看其中的数据。

1.1

1.1

1.2

1.2


②通过数据窗口跟随,找到我们输入的用户名及密码
·05254910数据窗口跟随后找到我们输入的用户名

2.1

2.1


·05251C80数据窗口跟随后找到我们输入的密码

2.2

2.2

③分析CALL里面的反汇编代码,因为在主函数的位置我们大致了解到需要关注ECX的值,所以我们进入CALL以后同样寻找关于ECX的操作,此处将ECX赋值给了EDI,即将this指针传递给EDI,再向下分析找到了用户名的部分

3

3
  
④判断用户名密码是否为空

4

4

⑤在这个CALL的位置,我们输入的密码转为了16进制字节数据

5

5

⑥用户名部分反汇编代码的分析

6

6

⑦对比密码在数组中的位置关系

7

7

⑧获得密码数组下标为5的数据

8

8

⑨更换了密码为0011-2233-4455-6677-8899,正好对应数组下标,便于后面数据的对比,密码操作仍同上,只是更改了值

9

9

⑩密码分析

10.1

10.1

10.2

10.2

10.3

10.3

10.4

10.4

10.5

10.5


结合上述分析的反汇编代码,编写测试代码:
[C] 纯文本查看 复制代码
//        K[3] = 9C、AC、FC
//        此处K[3]应该等于9C,以便于我们得到后面想要的结果
int main()
{
        srand(time(NULL));
        byte K[10] = { 0x00,0x11,0x22,0x9C,0x44,0x55,0x66,0x77,0x88,0x99 };
        //         CALL 010Edito.00407644 的返回值:AL = {{(K[0]^K[6])^0x18}+0x3D}^0xA7 != 0
        //         满足条件的值:K[0] 和 K[6]
        while (true)
        {
                byte k0 = rand() % 0xff;
                byte k6 = rand() % 0xff;

                byte AL = (k0 ^ k6 ^ 0x18 + 0x3D) ^ 0xA7;
                if (AL != 0)
                {
                        K[0] = k0;        //        将满足条件的值存到对应的下标中
                        K[6] = k6;
                        break;
                }
        }

        //  CALL 010Edito.004083C8 的返回值:
        //  EAX = (0x100 * (K[1] ^ K[7] & 0xff) + K[2] ^ K[5] & 0xff) & 0xFFFF
        //  EAX = (((EAX ^0x7892) + 0x4D30)^0x3421) & 0xFFFF / 0xB <= 0x3E8
        //  注意:判断余数,是否为0,为0返回商,余数不为0返回0
        //  满足条件的值:K[1]、K[2]、K[5]、K[7]
        while (true)
        {
                byte k1 = rand() % 0xff;
                byte k7 = rand() % 0xff;
                byte k2 = rand() % 0xff;
                byte k5 = rand() % 0xff;

                DWORD EAX = (0x100 * (k1 ^ k7 & 0xff) + k2 ^ k5 & 0xff) & 0xffff;
                EAX = (((EAX ^ 0x7892) + 0x4D30) ^ 0x3421) & 0xffff;
                if (EAX % 0xB == 0 && EAX / 0xB <= 0x3E8)
                {
                        K[1] = k1;        //        将满足条件的值存到对应的下标中
                        K[7] = k7;
                        K[2] = k2;
                        K[5] = k5;
                        break;
                }
        }
        printf("%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X", K[0], K[1], K[2], K[3], K[4], K[5], K[6], K[7], K[8], K[9]);
        getchar();
        return 0;
}


2.算法分析步骤记录
①接上面的分析步骤从013BDCD3位置的JMP跳下去

-1

-1

②随着JMP跳下来后分析此处的反汇编代码

-2

-2

③进入CALL 010Edito.00402E50;  String Encode

-3.1

-3.1

-3.2

-3.2

④在IDA中分析上段代码(便于使用IDA中的还原伪代码功能)

-4.1

-4.1


-4.2

-4.2

⑤F5将反汇编代码转为伪代码便于我们分析

-5

-5

⑥找到需要的数组地址,在OD中将拷贝

-6.1

-6.1

-6.2

-6.2

⑦将复制的数据转换为C++ DWORD(我们在IDA中分析时可以发现数据是DWORD型的)

-7

-7

根据反汇编代码写出C语言代码
[C] 纯文本查看 复制代码
DWORD g_EncodeArray[] = { };//此处篇幅冗杂,详情见末尾会贴出最后完成的完整代码
int __cdecl EncodeUsername(const char* pszUserName, int a2, char a3, unsigned __int16 a4)
{
        const char* v4; // edx@1
        signed int v5; // esi@1
        signed int v6; // edi@1
        unsigned __int8 v7; // bl@2
        int v8; // eax@3
        int v9; // ecx@3
        int v10; // ecx@4
        int result; // eax@4
        int v12; // ecx@5
        unsigned __int8 v13; // [sp+8h] [bp-10h]@2
        unsigned __int8 v14; // [sp+Ch] [bp-Ch]@2
        unsigned __int8 v15; // [sp+10h] [bp-8h]@2
        int v16; // [sp+14h] [bp-4h]@1

        v4 = pszUserName;
        v16 = 0;
        v5 = strlen(pszUserName);
        v6 = 0;
        if (v5 <= 0)
        {
                result = 0;
        }
        else
        {
                v13 = 0;
                v14 = 0;
                v7 = 15 * a4;
                v15 = 17 * a3;
                do
                {
                        v8 = toupper(v4[v6]);
                        v9 = v16 + g_EncodeArray[v8];
                        if (a2)
                        {
                                v10 = g_EncodeArray[v7]
                                        + g_EncodeArray[v15]
                                        + g_EncodeArray[(unsigned __int8)(v8 + 47)] * (g_EncodeArray[(unsigned __int8)(v8 + 13)] ^ v9);
                                result = g_EncodeArray[v14] + v10;
                                v16 = g_EncodeArray[v14] + v10;
                        }
                        else
                        {
                                v12 = g_EncodeArray[v7]
                                        + g_EncodeArray[v15]
                                        + g_EncodeArray[(unsigned __int8)(v8 + 23)] * (g_EncodeArray[(unsigned __int8)(v8 + 63)] ^ v9);
                                result = g_EncodeArray[v13] + v12;
                                v16 = g_EncodeArray[v13] + v12;
                        }
                        v14 += 19;
                        ++v6;
                        v15 += 9;
                        v7 += 13;
                        v13 += 7;
                        v4 = pszUserName;
                } while (v6 < v5);
        }
        return result;
}

//        K[3] = 9C、AC、FC
//        1.K[3] = 9C时。
int main()
{
        srand(time(NULL));
        //  0.初始化
        int dwRet = rand() % 0x3E8;
        byte K[10] = { 0x00,0x11,0x22,0x9C,0x44,0x55,0x66,0x77,0x88,0x99 };
        char szName[100] = { 0 };//"LUK"
        printf("please input name:");
        scanf_s("%s", szName, 100);
        //  1.用户名,加密,将返回值赋给密码数组
        DWORD dwKey = EncodeUsername(szName,1,0, dwRet);
        //CMP K[4],retValue & 0xFF;
        //CMP K[5],retValue >> 0x8 & 0xFF;
        //CMP K[6],retValue >> 0x10 & 0xFF;
        //CMP K[7],retValue >> 0x18 & 0xFF;
        //if (K[4])
        K[4] = dwKey & 0xFF;
        K[5] = dwKey >> 0x8 & 0xFF;
        K[6] = dwKey >> 0x10 & 0xFF;
        K[7] = dwKey >> 0x18 & 0xFF;

        //  2.穷举剩余的字节
        //         返回值:AL = (K[0] ^ K[6] ^ 0x18 + 0x3D) ^ 0xA7 != 0
        //         满足条件的值:K[0] 和 K[6]
        while (true)
        {
                byte k0 = rand() % 0xff;
                byte k6 = K[6];

                byte AL = (k0 ^ k6 ^ 0x18 + 0x3D) ^ 0xA7;
                if (AL >= 9)
                {
                        K[0] = k0;        //        将满足条件的值存到对应的下标中
                        K[6] = k6;
                        break;
                }
        }

        //  返回值:
        //  EAX = (0x100 * (K[1] ^ K[7] & 0xff) + K[2] ^ K[5] & 0xff) & 0xffff
        //  EAX = (((EAX ^ 0x7892) + 0x4D30) ^ 0x3421) & 0xffff / 0xB <= 0x3E8
        //  注意:判断余数,是否为0,为0返回商,余数不为0返回0
        //  商 <= 0x3E8
        //  满足条件的值:K[1]、K[2]、K[5]、K[7]
        while (true)
        {
                byte k1 = rand() % 0xFF;
                byte k7 = K[7];
                byte k2 = rand() % 0xFF;
                byte k5 = K[5];

                DWORD EAX = (0x100 * (k1 ^ k7 & 0xff) + k2 ^ k5 & 0xff) & 0xFFFF;
                EAX = (((EAX ^ 0x7892) + 0x4D30) ^ 0x3421) & 0xFFFF;
                if (EAX % 0xB == 0 && EAX / 0xB == dwRet)
                {
                        K[1] = k1;        //        将满足条件的值存到对应的下标中
                        K[7] = k7;
                        K[2] = k2;
                        K[5] = k5;
                        break;
                }
        }
        //  3.打印计算出的密码
        printf("%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X", K[0], K[1], K[2], K[3], K[4], K[5], K[6], K[7], K[8], K[9]);
        
        getchar();
        return 0;
}

⑨验证代码运行结果(发现还需要过网络验证才行)

-9.1

-9.1

-9.2

-9.2


⑩过网络验证
网络验证到服务器有一个标志位的判断
1)简单快捷,直接JMP

-10.1

-10.1


2)修改数据

-10.2

-10.2

-10.4

-10.4


3)修改标志位
将网络验证函数返回值修改为1

-10.3

-10.3

-11

-11

网络二次验证,修改为JMP

-10.5

-10.5

-10.6

-10.6


3.算法比较
010 8.0.1与010 9.0算法比较
①验证算法—致,验证函数参数不一致

8.0-9.0

8.0-9.0

②push 0x9 ~ push 0xA
③push 0x4389 ~ push 0x4596
相近的版本改动较小,故也可尝试别的版本。

4.完整代码
[C] 纯文本查看 复制代码
#include<windows.h>
#include <time.h>
#include <stdio.h>
#include<stdlib.h>

DWORD g_EncodeArray[] = {
0x39cb44b8, 0x23754f67, 0x5f017211, 0x3ebb24da, 0x351707c6, 0x63f9774b, 0x17827288, 0x0fe74821, 0x5b5f670f, 0x48315ae8, 0x785b7769, 0x2b7a1547, 0x38d11292, 0x42a11b32, 0x35332244, 0x77437b60,
0x1eab3b10, 0x53810000, 0x1d0212ae, 0x6f0377a8, 0x43c03092, 0x2d3c0a8e, 0x62950cbf, 0x30f06ffa, 0x34f710e0, 0x28f417fb, 0x350d2f95, 0x5a361d5a, 0x15cc060b, 0x0afd13cc, 0x28603bcf, 0x3371066b,
0x30cd14e4, 0x175d3a67, 0x6dd66a13, 0x2d3409f9, 0x581e7b82, 0x76526b99, 0x5c8d5188, 0x2c857971, 0x15f51fc0, 0x68cc0d11, 0x49f55e5c, 0x275e4364, 0x2d1e0dbc, 0x4cee7ce3, 0x32555840, 0x112e2e08,
0x6978065a, 0x72921406, 0x314578e7, 0x175621b7, 0x40771dbf, 0x3fc238d6, 0x4a31128a, 0x2dad036e, 0x41a069d6, 0x25400192, 0x00dd4667, 0x6afc1f4f, 0x571040ce, 0x62fe66df, 0x41db4b3e, 0x3582231f,
0x55f6079a, 0x1ca70644, 0x1b1643d2, 0x3f7228c9, 0x5f141070, 0x3e1474ab, 0x444b256e, 0x537050d9, 0x0f42094b, 0x2fd820e6, 0x778b2e5e, 0x71176d02, 0x7fea7a69, 0x5bb54628, 0x19ba6c71, 0x39763a99,
0x178d54cd, 0x01246e88, 0x3313537e, 0x2b8e2d17, 0x2a3d10be, 0x59d10582, 0x37a163db, 0x30d6489a, 0x6a215c46, 0x0e1c7a76, 0x1fc760e7, 0x79b80c65, 0x27f459b4, 0x799a7326, 0x50ba1782, 0x2a116d5c,
0x63866e1b, 0x3f920e3c, 0x55023490, 0x55b56089, 0x2c391fd1, 0x2f8035c2, 0x64fd2b7a, 0x4ce8759a, 0x518504f0, 0x799501a8, 0x3f5b2cad, 0x38e60160, 0x637641d8, 0x33352a42, 0x51a22c19, 0x085c5851,
0x032917ab, 0x2b770ac7, 0x30ac77b3, 0x2bec1907, 0x035202d0, 0x0fa933d3, 0x61255df3, 0x22ad06bf, 0x58b86971, 0x5fca0de5, 0x700d6456, 0x56a973db, 0x5ab759fd, 0x330e0be2, 0x5b3c0ddd, 0x495d3c60,
0x53bd59a6, 0x4c5e6d91, 0x49d9318d, 0x103d5079, 0x61ce42e3, 0x7ed5121d, 0x14e160ed, 0x212d4ef2, 0x270133f0, 0x62435a96, 0x1fa75e8b, 0x6f092fbe, 0x4a000d49, 0x57ae1c70, 0x004e2477, 0x561e7e72,
0x468c0033, 0x5dcc2402, 0x78507ac6, 0x58af24c7, 0x0df62d34, 0x358a4708, 0x3cfb1e11, 0x2b71451c, 0x77a75295, 0x56890721, 0x0fef75f3, 0x120f24f1, 0x01990ae7, 0x339c4452, 0x27a15b8e, 0x0ba7276d,
0x60dc1b7b, 0x4f4b7f82, 0x67db7007, 0x4f4a57d9, 0x621252e8, 0x20532cfc, 0x6a390306, 0x18800423, 0x19f3778a, 0x462316f0, 0x56ae0937, 0x43c2675c, 0x65ca45fd, 0x0d604ff2, 0x0bfd22cb, 0x3afe643b,
0x3bf67fa6, 0x44623579, 0x184031f8, 0x32174f97, 0x4c6a092a, 0x5fb50261, 0x01650174, 0x33634af1, 0x712d18f4, 0x6e997169, 0x5dab7afe, 0x7c2b2ee8, 0x6edb75b4, 0x5f836fb6, 0x3c2a6dd6, 0x292d05c2,
0x052244db, 0x149a5f4f, 0x5d486540, 0x331d15ea, 0x4f456920, 0x483a699f, 0x3b450f05, 0x3b207c6c, 0x749d70fe, 0x417461f6, 0x62b031f1, 0x2750577b, 0x29131533, 0x588c3808, 0x1aef3456, 0x0f3c00ec,
0x7da74742, 0x4b797a6c, 0x5ebb3287, 0x786558b8, 0x00ed4ff2, 0x6269691e, 0x24a2255f, 0x62c11f7e, 0x2f8a7dcd, 0x643b17fe, 0x778318b8, 0x253b60fe, 0x34bb63a3, 0x5b03214f, 0x5f1571f4, 0x1a316e9f,
0x7acf2704, 0x28896838, 0x18614677, 0x1bf569eb, 0x0ba85ec9, 0x6aca6b46, 0x1e43422a, 0x514d5f0e, 0x413e018c, 0x307626e9, 0x01ed1dfa, 0x49f46f5a, 0x461b642b, 0x7d7007f2, 0x13652657, 0x6b160bc5,
0x65e04849, 0x1f526e1c, 0x5a0251b6, 0x2bd73f69, 0x2dbf7acd, 0x51e63e80, 0x5cf2670f, 0x21cd0a03, 0x5cff0261, 0x33ae061e, 0x3bb6345f, 0x5d814a75, 0x257b5df4, 0x0a5c2c5b, 0x16a45527, 0x16f23945};

int __cdecl EncodeUsername(const char* pszUserName, int a2, char a3, unsigned __int16 a4)
{
        const char* v4; // edx@1
        signed int v5; // esi@1
        signed int v6; // edi@1
        unsigned __int8 v7; // bl@2
        int v8; // eax@3
        int v9; // ecx@3
        int v10; // ecx@4
        int result; // eax@4
        int v12; // ecx@5
        unsigned __int8 v13; // [sp+8h] [bp-10h]@2
        unsigned __int8 v14; // [sp+Ch] [bp-Ch]@2
        unsigned __int8 v15; // [sp+10h] [bp-8h]@2
        int v16; // [sp+14h] [bp-4h]@1

        v4 = pszUserName;
        v16 = 0;
        v5 = strlen(pszUserName);
        v6 = 0;
        if (v5 <= 0)
        {
                result = 0;
        }
        else
        {
                v13 = 0;
                v14 = 0;
                v7 = 15 * a4;
                v15 = 17 * a3;
                do
                {
                        v8 = toupper(v4[v6]);
                        v9 = v16 + g_EncodeArray[v8];
                        if (a2)
                        {
                                v10 = g_EncodeArray[v7]
                                        + g_EncodeArray[v15]
                                        + g_EncodeArray[(unsigned __int8)(v8 + 47)] * (g_EncodeArray[(unsigned __int8)(v8 + 13)] ^ v9);
                                result = g_EncodeArray[v14] + v10;
                                v16 = g_EncodeArray[v14] + v10;
                        }
                        else
                        {
                                v12 = g_EncodeArray[v7]
                                        + g_EncodeArray[v15]
                                        + g_EncodeArray[(unsigned __int8)(v8 + 23)] * (g_EncodeArray[(unsigned __int8)(v8 + 63)] ^ v9);
                                result = g_EncodeArray[v13] + v12;
                                v16 = g_EncodeArray[v13] + v12;
                        }
                        v14 += 19;
                        ++v6;
                        v15 += 9;
                        v7 += 13;
                        v13 += 7;
                        v4 = pszUserName;
                } while (v6 < v5);
        }
        return result;
}

//        K[3] = 9C、AC、FC
//        1.K[3] = 9C时。
int main()
{
        srand(time(NULL));
        //  0.初始化
        int dwRet = rand() % 0x3E8;
        byte K[10] = { 0x00,0x11,0x22,0x9C,0x44,0x55,0x66,0x77,0x88,0x99 };
        char szName[100] = { 0 };//"LUK"
        printf("please input name:");
        scanf_s("%s", szName, 100);
        //  1.用户名,加密,将返回值赋给密码数组
        DWORD dwKey = EncodeUsername(szName,1,0, dwRet);
        //CMP K[4],retValue & 0xFF;
        //CMP K[5],retValue >> 0x8 & 0xFF;
        //CMP K[6],retValue >> 0x10 & 0xFF;
        //CMP K[7],retValue >> 0x18 & 0xFF;
        //if (K[4])
        K[4] = dwKey & 0xFF;
        K[5] = dwKey >> 0x8 & 0xFF;
        K[6] = dwKey >> 0x10 & 0xFF;
        K[7] = dwKey >> 0x18 & 0xFF;

        //  2.穷举剩余的字节
        //         返回值:AL = (K[0] ^ K[6] ^ 0x18 + 0x3D) ^ 0xA7 != 0
        //         满足条件的值:K[0] 和 K[6]
        while (true)
        {
                byte k0 = rand() % 0xff;
                byte k6 = K[6];

                byte AL = (k0 ^ k6 ^ 0x18 + 0x3D) ^ 0xA7;
                if (AL >= 9)
                {
                        K[0] = k0;        //        将满足条件的值存到对应的下标中
                        K[6] = k6;
                        break;
                }
        }

        //  返回值:
        //  EAX = (0x100 * (K[1] ^ K[7] & 0xff) + K[2] ^ K[5] & 0xff) & 0xffff
        //  EAX = (((EAX ^ 0x7892) + 0x4D30) ^ 0x3421) & 0xffff / 0xB <= 0x3E8
        //  注意:判断余数,是否为0,为0返回商,余数不为0返回0
        //  商 <= 0x3E8
        //  满足条件的值:K[1]、K[2]、K[5]、K[7]
        while (true)
        {
                byte k1 = rand() % 0xFF;
                byte k7 = K[7];
                byte k2 = rand() % 0xFF;
                byte k5 = K[5];

                DWORD EAX = (0x100 * (k1 ^ k7 & 0xff) + k2 ^ k5 & 0xff) & 0xFFFF;
                EAX = (((EAX ^ 0x7892) + 0x4D30) ^ 0x3421) & 0xFFFF;
                if (EAX % 0xB == 0 && EAX / 0xB == dwRet)
                {
                        K[1] = k1;        //        将满足条件的值存到对应的下标中
                        K[7] = k7;
                        K[2] = k2;
                        K[5] = k5;
                        break;
                }
        }
        //  3.打印计算出的密码
        printf("%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X", K[0], K[1], K[2], K[3], K[4], K[5], K[6], K[7], K[8], K[9]);
        
        getchar();
        return 0;
}

免费评分

参与人数 8威望 +1 吾爱币 +29 热心值 +8 收起 理由
156608225 + 1 + 1 谢谢@Thanks!
phithon + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
Hmily + 1 + 20 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
小朋友呢 + 2 + 1 热心回复!
tail88 + 1 + 1 用心讨论,共获提升!
asdfghjk_0001 + 1 + 1 谢谢@Thanks!
wkxq + 2 + 1 用心讨论,共获提升!
pentium450 + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!

查看全部评分

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

guoxiaofei029 发表于 2022-9-24 21:25
  这个注册机打开后  输入错误密码不弹出无反应,麻烦大佬指点
:https://wwn.lanzoul.com/idhFX0caihha 密码:52pj
狂野兔斯基 发表于 2021-12-6 11:50
yasenhacker 发表于 2021-12-6 13:09
shallies 发表于 2021-12-6 13:32
厉害了,我的哥
kuagnkuangkuang 发表于 2021-12-6 23:06
感谢分享好教程
limit496 发表于 2021-12-7 03:25
不懂 但感觉很厉害
asts 发表于 2021-12-7 08:44
感谢分享技术
yyb414 发表于 2021-12-7 09:07
崇拜啊!大佬!
qe13323 发表于 2021-12-7 09:59
感谢分享好教程,另外楼主好强
风千叶 发表于 2022-3-23 16:55
感谢大佬讲的这么详细,膜拜
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

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

GMT+8, 2024-11-24 13:34

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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