主要内容:

010Editor介绍

16进制编辑器:16进制修改、文本修改、模板解析各种文件格式、对比文件

010暴力破解分析

1、找到注册的窗口

2、测试注册窗口的反应

3、根据反应做出下一步分析

猜测API,API下断点动态调试

敏感字符串,程序中搜索

4、动态分析,定位关键跳转,修改代码

5、动态分析,定位关键CALL,修改代码

010算法分析

关键函数

一步步分析,找到访问用户名和密码的代码

边分析边重写C语言

测试

1样本概况

1.1 应用程序信息

应用程序名称:010Editor 8.0.1

MD5值:7D5D95F0E3DC24AC30133A596D9904AD

SHA1值:4D7089541DB5BFF56CB87F41ECAC2AC3844B2BCA

简单功能介绍:16进制修改、解析各种文件、对比文件

1.2 分析环境及工具

系统环境:win7 32位

工具:Ollydbg、IDA、010Editor、PEiD、Exeinfo、Vistual Studio

1.3 分析目标

1、010Editor暴力破解分析

2、010Editor算法分析

3、010Editor网络验证分析

2.具体分析过程

2.1 分析过程

2.1.1 010Editor暴力破解分析

使用Exeinfo先看一下程序信息,发现该程序是Qt框架下写的,连接器版本是12.0,对应的编译器是VS2013

该程序是收费的,运行之后需要填写用户名和密码,当我们点击Check License时会弹出一个窗口:

因此我们有两种思路进行分析,第一种是搜索创建窗口的函数,第二种是搜索弹出窗口中的字符串,这里第一种进行分析。

使用OD进行分析,在主模块中右键,查找当前模块的名称,发现很多Qt5的函数,输入Create查找,也没有定位到API

使用IDA对程序进行分析,查看其导入表,使用的是Qt的库,对Qt不熟悉,也没有发现创建窗口的函数,因此继续使用OD进行分析。

在模块窗口中找到user32.dll这个模块,这个模块和窗口API有关,进入该模块后,按:Ctrl+n,然后搜索和创建窗口有关的API,如:CreateWindowExA/W、MessageBox、DialogBox、CreateDialog等,Qt程序底层调用的创建窗口的API是CreateWindowA/W,我们搜索该API下断点,然后运行测试:

发现其在CreateWindowExW处断了下来,我们在K窗口中看栈回溯,对主模块进行分析,找到下面几个调用函数:

每个都点进去往上追踪,看有没有关键信息,其中018CB29点进去之后,发现了有用的字符串信息:

其中一个是无效的用户和密码,就是我们输入时弹出的字符串,我们点击该行,会提示我们是从哪个地方跳过来的,我们右键转到该地址:

我们对上面两个对EDI判断的地方下断点运行分析,发现语句执行了,说明如果EBX不等于0x93,EDI不等于0xED、0x20C,就会跳转到刚才提示失败的地方

继续向上追踪,看EBX和EDI分别表示什么意思:

追踪上去发现,如果EDI不等于0xDB就跳转到刚才的地方,对上面的代码下断点运行之后,发现没有断下来,说明上面这一段代码没有执行,EDI的值是上面跳转过来的。

CMP语句的跳转来自两个地方,是两个相邻的地方,我们追踪过去:

发现是判断EBX的值,如果EBX等于0xE7就跳转到刚才的位置,而EBX又是EAX赋值得到的,所以就是判断EAX是否等于0xE7。而又已经知道程序是VS2013的程序,则ECX是函数的返回值,所以我们找到了关键函数。就是当CALL1函数执行后,返回值如果等于0xE7,下面就会跳转到判断EDI的地方。如果EDI不等于0xDB,就会跳转提示错误。继续往下找,看能不能找到提示正确的地方。

在这里发现了提示正确的字符串,又发现其在关键跳转的下面。说明EDI等于0xDB才能继续往下执行提示正确,而EDI又来自上面的EAX,当CALL2函数执行后,返回值EAX等于0xDB,才能继续往下执行提示正确。进入该函数进行分析,发现里面又调用了一次CALL1函数:

分析之后发现当CALL1函数返回值是0x2D的时候会跳转到EAX等于0xDB,说明要想CALL2的返回值等于0xDB,CALL1的返回值必须是0x2D。

暴力破解的话,我们只需要将EDI是否等于0xDB下面的跳转nop掉,然后保存就行,再打开输入就可以通过验证了。

如果想要运行程序之后,直接进入而不需要我们再点Check License,我们要让CALL2的返回值是0xDB,进入函数进行修改,修改后之直接返回:

修改后保存,再打开就是直接进入了。

也可以用弹出窗口中的字符串,来进行搜索。右键查找字符串,右键输入查找的文本也能找到关键位置:

2.1.2 010Editor算法分析

破解完程序之后,我们需要对关键函数进行分析,来写一个注册机,自动生成序列号。进入关键函数:0040A826。因为是C++程序,需ECX传递this指针,我们需要关注ECX的值,数据窗口中跟随

每个都右键跟随进去看看,数据窗口跟随:0x05153DF0,发现了我们输入的用户名:

数据窗口跟随:0x05129678,发现了我们输入的密码:

发现了带有isEmpty、String的字符串,猜测是判断用户名和密码是否为空的函数:

进去函数进行分析,确定是判断用户名和密码是否为空的函数:

继续往下分析,EAX被赋值为:0x0012D08C,数据窗口跟随:0x05010C3F0,再数据窗口跟随:

发现了输入的密码:

继续向下分析,跟随ECX,ECX+4上保存的是用户名的信息:

下一个函数将带有密码信息的EAX传进去了,不知道其具体目的,进去之后发现过程很长。先数据窗口跟随EAX,然后运行程序,看其数据是怎么变化:

运行前:

运行后:

根据结果显示,上面函数的作用应该是将密码字符串转为了16进制的字节数据。继续向下分析,下面函数传入了一个ASCII是999的值,根据名字猜测是字符串操作,但是具体作用还不知道:

运行之后,返回值是0,没有发现其他变化,先不管其作用,继续往下分析:

发现ESI指向了0123456789ABCDEF,然后是循环。这一块是将999传入进行了操作,没有涉及到用户名和密码,先不去分析其作用,继续向下分析:

从这里开始应该是算法的地方,一步步对算法进行分析:

K[3]如果不等于9C、FC、AC,就会跳转到EAX=0xE7,返回时就会出错。所以K[3]应该是9C、FC、AC的其中一个。如果密码是个数组,初步判断K[0]和K[6]有联系,K[1]和K[7]、K[2]和K[5]有联系。其中K[0]^K[6]后传入了函数,进入函数进行分析:

该函数对K[0]和K[6]进行了一系列的操作,然后返回EAX,再继续分析下一个函数:

经过分析得知:ECX不能为0,即:((K[0]^K[6])^0x18+0x3D)^0xA7不等于0,EAX也不能为0,且小于等于0x3E8。而EAX的值又取决于上面函数的返回值,函数中分析后可知,EAX的值取决于函数中EAX除以ECX的余数,如果余数EDX不为0,则EAX被清空为0,因此,要想EAX不为0,EAX处于ECX的余数要为0。由上面的分析可以得出密码数组中一些元素的关系,可以根据上面的算法编写代码进行测试。

继续向下分析:

运行到这里之后向下跳转到:013BDD88

有一个函数由toUtf8String的字样,应该是和字符串有关的操作,跟随push进去的EAX,看数据的变化,运行前:

该函数运行后:

所以该函数作用是将用户名字符串转化为ASCII。下面又有一个函数,看名字应该是和数组有关的,运行之后看返回值:

运行之后发现其返回值是用户名,继续向下分析,有一个函数传入了四个参数,具体作用不知道,先运行看数据变化:

运行之后,EAX不确定是什么值,可能是哈希值。继续向下分析:

当0x00407644函数的返回值即:((K[0]^K[6])^0x18+0x3D)^0xA7大于等于9的时候才会跳转到成功的地方。经过分析得知:0x00402E50这个函数对ASCII码版的用户名字符串进行了一个计算,计算后返回的结果,分别与密码的K[4]、K[5]、K[6]、K[7]进行了比较,都相等的话,才能成功。

至于函数对用户名计算的这个函数,可以一步步进行分析,也可以Ctrl+X复制函数的地址,然后再IDA中按G键找到该地址:

按F5进行分析:

OD中将0x2E64148上的数据复制下来,放到代码中:

再将IDA中的代码复制下来,放到VS代码中,将参数进行修改

运行之后,得到密码:

2.1.3 010Editor网络验证分析

生成的序列号过一段时间后,再次注册会将序列号发给官网进行验证,如果官网没有保存这个序列号就会失效,我们需要让其通过网络验证。

使用OD继续分析:

运行之后,发现函数返回了0x113,进入0x00409C9B处的函数分析:

发现里面有判断,如果[ESI+0x2C]上的值不为0,就会返回0x113,我们可以将跳转改为无条件跳转:JMP short 0x013BE4F6,然后保存,继续往下运行观察:

此时,没有跳转,继续向下执行,进行网络验证,修改代码,让其一直返回1:

保存之后,就成功绕过了网络验证。

2.2 测试代码(如有代码验证贴出关键代码

用户名加密函数:

参数1:用户名、参数2:BL等于FC, 就是0,不等就是1、参数3:1、参数4:0x40083C8的返回值,<=0x3E8

int __cdecl EncodeUsername(const char* pUsername, 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 = pUsername;

v16 = 0;

v5 = strlen(pUsername);

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_EcodeArray[v8];

if (a2)

{

v10 = g_EcodeArray[v7]

+ g_EcodeArray[v15]

+ g_EcodeArray[(unsigned __int8)(v8 + 47)] * (g_EcodeArray[(unsigned __int8)(v8 + 13)] ^ v9);

result = g_EcodeArray[v14] + v10;

v16 = g_EcodeArray[v14] + v10;

}

else

{

v12 = g_EcodeArray[v7]

+ g_EcodeArray[v15]

+ g_EcodeArray[(unsigned __int8)(v8 + 23)] * (g_EcodeArray[(unsigned __int8)(v8 + 63)] ^ v9);

result = g_EcodeArray[v13] + v12;

v16 = g_EcodeArray[v13] + v12;

}

v14 += 19;

++v6;

v15 += 9;

v7 += 13;

v13 += 7;

v4 = pUsername;

} while (v6 < v5);

}

return result;

}

主函数:

int main()

{

srand(time(NULL));

//0、初始化

int dwRet = rand() % 0x3E8;

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

//1、用户名,经过函数加密,由返回值确定K[4]、K[5]、K[6]、K[7]

char szName[100] = { 0 };

printf("please input name: ");

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

DWORD dwKey = EncodeUsername(szName, 1, 0, dwRet);

K[4] = dwKey & 0xFF;

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

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

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

//2、穷举

while (true)

{

byte K0 = rand() % 0xFF;

byte K6 = K[6];

//AL=((K[0]^K[6])^0x18+0x3D)^0xA7

//ECX=(((K[0]^K[6])^0x18+0x3D)^0xA7)&0xFF

byte al = ((K0 ^ K6) ^ 0x18 + 0x3D) ^ 0xA7;

if (al >= 9)

{

K[0] = K0;

break;

}

}

while (true)

{

byte K1 = rand() % 0xFF;

byte K2 = rand() % 0xFF;

byte K5 = K[5];

byte K7 = K[7];

//ESI=(((K[1]^K[7])&0xFF)*0x100+((K[2]^K[5])&0xFF))&0xFFFF

//EAX=(((ESI^0x7892+0x4D30)^0x3421)&0xFFFF)

//余数为0,返回商;且返回的商小于等于0x3E8

DWORD ESI = (((K1 ^ K7) & 0xFF) * 0x100 + ((K2 ^ K5) & 0xFF)) & 0xFFFF;

DWORD EAX = (((ESI ^ 0x7892) + 0x4D30) ^ 0x3421) & 0xFFFF;

int a = EAX % 0xB;

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

{

K[1] = K1;

K[2] = K2;

K[5] = K5;

K[7] = K7;

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;

}

3.总结

在对010Editor分析过程中,发现其先对用户名和密码判断是否为空,然后对密码字符串转成16进制字节数据,对数据进行验证。再将用户名转成ASCII字符串,通过一个函数返回一个值,这个值会和密码的K[4]、K[5]、K[6]、K[7]有关系。编写注册机代码思路是:先指定用户名,用加密函数算出一个值,然后根据这个值确定K[4]、K[5]、K[6]、K[7],再用分析出来的的算法将剩下不确定的计算出来。

在对算法进行逆向分析的过程,要一步步跟踪解析算法,需要有耐心,并且要多写注释,便于思路的梳理。另外也可以配合IDA的使用,自动分析一些函数。

010Editor逆向分析相关推荐

  1. [系统安全] 二十四.逆向分析之OllyDbg调试INT3断点、反调试、硬件断点与内存断点

    您可能之前看到过我写的类似文章,为什么还要重复撰写呢?只是想更好地帮助初学者了解病毒逆向分析和系统安全,更加成体系且不破坏之前的系列.因此,我重新开设了这个专栏,准备系统整理和深入学习系统安全.逆向分 ...

  2. [系统安全] 二十三.逆向分析之OllyDbg动态调试复习及TraceMe案例分析

    您可能之前看到过我写的类似文章,为什么还要重复撰写呢?只是想更好地帮助初学者了解病毒逆向分析和系统安全,更加成体系且不破坏之前的系列.因此,我重新开设了这个专栏,准备系统整理和深入学习系统安全.逆向分 ...

  3. [安全攻防进阶篇] 二.如何学好逆向分析、逆向路线推荐及吕布传游戏逆向案例

    从2019年7月开始,我来到了一个陌生的专业--网络空间安全.初入安全领域,是非常痛苦和难受的,要学的东西太多.涉及面太广,但好在自己通过分享100篇"网络安全自学"系列文章,艰难 ...

  4. 某K字头运动软件逆向分析-登录时非法的请求

    ​最近重新燃起了运动的热情,经常使用到一款软件,里面有些内容需要付费观看,所以决定给它一些特殊的关爱. 重新打包是避不开的,现在大多app都会做防护,所以决定什么都不做只是反编译重打包试下,果然重打包 ...

  5. asp.net webform 复制窗体代码_逆向分析流氓软件自我复制以及防御思路

    一.前言 好长时间没有投稿了,之前被发布的稿件,也收到了Freebuf的现金奖励,同时陆陆续续收到好多圈类人士的夸奖,备受鼓舞,觉得自己应该坚持投稿,为安全事业略尽绵薄之力!最近任务不重,正好有时间投 ...

  6. android逆向分析概述_Android存储概述

    android逆向分析概述 Storage is this thing we are all aware of, but always take for granted. Not long ago, ...

  7. Android逆向分析工具ded的使用

    今天使用了ded做逆向分析,瞬间比Apktool高大上了,功能太强大了,不过还有升级版,明天研究.吼吼~ 详细内容可以参考这篇论文:A Study of Android Application Sec ...

  8. 技术分享:逆向分析ATM分离器

    文章内容仅供技术交流,请勿模仿操作! 背景(作者) 每一次外出时, Elizabeth和我总是格外的小心,同时把我们身上的钱藏在特殊的皮带上面,这样还不够,我们还采取了"狡兔三窟" ...

  9. NSA释出逆向工程工具GHIDRA针对恶意软件逆向分析

    2019独角兽企业重金招聘Python工程师标准>>> 美国国安局(National Security Agency,NSA)准备在今年3月举行的RSA安全会议上免费释出名为GHID ...

  10. 【世界上最优秀的逆向分析工具】IDA Pro6.1绿色版

    [世界上最优秀的逆向分析工具]IDA Pro6.1绿色版 让编程改变世界 Change the world by program 世界上最优秀的静态逆向工具没有之一 [caption id=" ...

最新文章

  1. linux机器启动pg数据库命令,Linux下创建Postgresql数据库的方法步骤
  2. 【深度学习】CNN在大规模图像数据集上的应用(基于keras和MNIST)
  3. 两对光纤收发器用网线连接_光纤那么快,路由器和电脑之间为何不用光纤连接,反而用普通网线...
  4. c#-----让richtextbox或者TextBox不可编辑
  5. macos -bash: yarn: command not found/-bash: cnpm: command not found
  6. 学了阿里中台,却依然做不好系统? 聊聊阿里的项目管理
  7. 8086简单的指令流水线_在8086微处理器中执行流水线的指令和概念的步骤
  8. [SQL SERVER] 优化SQL Server 2000的设置
  9. matlab中主程序如何调用其它子程序,主程序怎样调用子程序
  10. 程序员软考真题__专项:数据结构与算法 02
  11. android高德hud导航,教你一招,手机导航秒变HUD抬头显示
  12. 直播预告| ICML专场四~
  13. 【SQL面试】WHERE 1=1 到底是啥意思?
  14. 如何使用phpdoc生成PHP文档
  15. 汽车信息安全要求(5)——Secure Boot(安全启动)
  16. 多旋翼飞行器设计与控制(二)—— 基本组成
  17. cudnn 版本查看
  18. 信用卡,今天你办了吗?
  19. 2022-2028全球与中国化学机械抛光(CMP金刚石衬垫调节器市场现状及未来发展趋势
  20. mybatis中association的用法

热门文章

  1. openjtag openocd libftd2xx
  2. Oxygen XML Editor Professional文档的强大工具
  3. 计划超越苹果!诺基亚在印度推出笔记本电脑
  4. SPSS中如何进行快速聚类分析
  5. 恢复威金病毒感染的EXE文件小方法(转)
  6. 医院管理系统(Java)
  7. U盘量产U盘扩容和U盘芯片检测
  8. Power BI数据网关
  9. 用云服务器储存文件空间,用云服务器储存文件空间
  10. Windows10安装JDK配置环境变量