欢迎来到 嗅灵易学

零基础也能上手的脚本技术课,一对一答疑带你入门

[原创]010Editor最新版9.0.1超详细分析&&暴力破解&&注册机源码分享

[原创]010Editor最新版9.0.1超详细分析&&暴力破解&&注册机源码分享

萌新第一次发帖, 瑟瑟发抖...

以下是对010Editor最新版本v9.0.1的破解过程,因为本人比较菜,所以分析的特别详细..感谢15pb的老师们

010Editor简单介绍

010 Editor是一款专业的文本编辑器和十六进制编辑器,它可以编辑文本文件,包括 Unicode 文件、批处理文件、C/C++、XML 等,功能全面且强大,可以说是目前最强大的十六进制编辑器了。

实现平台:

Win7

工具:

Exeinfo PE,OD

暴力破解部分:

首先对010Editor用Exeinfo PE工具进行扫描,发现语言是vs2013版本c++。

运行010Editor,只有30天的免费使用时间。

暴力破解分析思路:

1.     找到注册的窗口

2.     测试注册窗口的反应

3.     猜测API,API下断动态调试/敏感字符串搜索

4.     动态分析,查找关键跳转,修改代码

5.     查找关键call,修改代码

暴力破解具体实现

CreateWindowExW在user32.dll中被调用,所以模块锁定user32.dl,CTRL+N名称搜索CreateWindowExW进行下断。

运行程序,输入名字和密码,点击确定,OD中会断到CreateWindowExW函数。点击K进行栈回溯。

栈回溯,分析得知是Qt进行编写的,但调用CreateWindowExW的是在010Editor中,由于出现的函数较少,分别点击进入查看

根据特殊字符串,定位到函数(寻找此地址时,还可以使用字符串搜索Invalid name or password直接跳转到此处)。

跳转到之前的函数地址

根据跳转继续回溯,cmp edi,0xDB,不相等时,会一直跳转到执行”Invalid name or password...”,那么推测当edi=0xDB时,才会执行正确的语句。

继续回溯,找到关键函数,如果要密码正确,edi=0xDB。经分析1339D3B函数,当eax=0x2D时,edi=0xDB,所以修改函数133A92F,进入133A92F发现有需要重定位的地方,所以先取消重定位。

使用010Editor取消重定位

对133A92F函数直接进行赋值后即返回。

而在1339D3B函数中,当eax=2D时,返回值才会返回DB。中间算法有些长,截取关键的赋值部分。

序列号提交后会联网和官网中的序列号进行比较,如果官网中没有对应的序列号,就会失效。去掉网络验证

经测试,1339D3B函数内这里需要强制跳转,需要强制更改为jmp指令。

有时网络不稳定时,会出现错误,所以要修改网络验证函数的返回值为1。

选中更改区域,右键保存所有更改。

至此,已暴力破解成功。

运行程序,一切正常。

算法分析部分:

1.     判断用户名密码是否为空

2.     将密码字符串转为16进制字节数据

3.     验证密码十六进制数据

A. K[3]=0x9c或0xfc或0xax

B. 407644函数的返回值不能为0,即al=(K[0]^K[6]^0X18+0X3D)^0XA7

AL!=0

   C.004083C8函数的返回值不能为0且<=0x3e8

      esi=0x100*(K[1]^K[7])+K[2]^K[5]

        eax=((esi^0x7892+0x4d30)^0x3421)&0xffff

         if(eax%0xb==0且eax/0xb<=0x3e8)

4.     将用户名转为ascii字符串

5.     使用用户名计算出一个key,与K[4]~K[7]之间存在对应关系

a.     调用402e50函数,参数是用户名字符串,1,0,4083c8函数的返回值

b.     使用密码中的几个字节与402e50函数的返回值retValue进行比较

Cmp K[4],ret&0xff

Cmp K[5],ret>>8&0xff

Cmp K[6],ret>>16&0xff

Cmp K[7],ret>>24&0xff

6.     判断参数

Cmp arg,407644的返回值>=0xa

算法详细分析:

关键函数为40a92f,只要此函数返回值是0x2d就能保证程序跳转到正确的路线。

进入40a92f函数中,push的参数进行数据窗口跟随,发现是密码,观察运行完之后的结果

接着往下,对算法进一步分析

根据传参K[0]K[6],分析0x4074EB函数,得知此函数是处理K[0]K[6]。

通过传参”0x100*((K[1]^K[7])&0xff)+(K[2]^K[5])&0xff”,分析0x40831E,该函数是处理K[1]K[2]K[5]K[7]参数。

分析至此,我们已经知道密码之间有一定的对应算法的关系,若最后执行正确的语句,有以下的逻辑关系:ecx!=0,eax<=0x3e8且eax!=0

接着往下分析,会发现用户名以及密码之间有一定的对应关系。

加密函数402f86,传入ascii版的用户名字符串,经过运算,得到类似加密后的返回值

用户名与密码之间果真存在着对应关系

至此,算法逻辑部分已经很清晰,剩下的就是写代码了。

抠取代码步骤:

注册机实现代码:


#include <stdio.h>

#include <time.h>

#include "windows.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 *a1, int a2, char a3, signed __int16 a4)

{

       const char *v4; // edx@1

       signed int v5; // esi@1signed int v6; // edi@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 = a1;

       v16 = 0;

       v5 = strlen(a1);

       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 = a1;

              } while (v6 < v5);

       }

       return result;

}

int main()

{

       //0.初始化

       srand(time(NULL));

       int dwRet = rand()%0x3e8;

       byte K[10] = { 0x00, 0x11, 0x22, 0x9C, 0x44, 0x55, 0x66, 0x77, 0x88,  0xaa };

       //eax = (K[0]^K[6]^0x18 +0x3d)^0xa7

       char szUsername[100] = { 0 };

       printf("please input username: ");

       scanf_s("%s", szUsername,100 );

       //1.用户名加密,将返回值赋给密码数组

       DWORD dwKey = EncodeUserName(szUsername, 1, 0, dwRet);

       K[4] = dwKey & 0XFF;

       K[5] = dwKey >>8& 0XFF;

       K[6] = dwKey >>16& 0XFF;

       K[7] = dwKey >>24& 0XFF;

       while (TRUE)

       {

              byte k0 = rand() % 0XFF;

              byte k6 = K[6];

              byte al = ((k0 ^ k6) ^ 0x18 + 0x3D) ^ 0xA7;

              if (al>=0xA)

              {

                     K[0] = k0;

                     K[6] = k6;

                     break;

              }

       }

       //esi = 0x100*((K[1]^K[7])&0xff)+(K[2]^K[5])&0xff

       //eax = (((esi^0x7892+0x4d30)^0x3421)0xffff)/0xb

       while (TRUE)

       {

              byte k1 = rand() % 0XFF;

              byte k7 = K[7];

              byte k2 = rand() % 0XFF;

              byte k5 = K[5];

              DWORD esi = (0x100 * (k1 ^ k7 & 0xFF) + k2 ^ k5& 0xFF)& 0xFFFF;

              DWORD  eax = (((esi ^ 0x7892 )+ 0x4d30) ^ 0x3421)&0xffff ;

              //eax:余数为0 返回商  | 余数不为0返回余数

              //余数为0且商为0x3e8

              if (eax%0xB==0&&eax/0xB==dwRet)

              {

                     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;

}

注意:上传附件及图片大小不得大于30M。

⚠️ 版权声明:
本博客所有内容(含教程、源码、工具)仅供个人技术学习与研究交流使用,严禁商用、倒卖、二次分发及非法用途
未经作者书面授权,任何组织或个人不得转载、复制或用于其他平台,违者将追究相关责任。

0 0 0 举报
复制成功