发布于 

商业软件010editor软件破解分析

样本名 商业软件010editor软件破解分析
平台 Win10 专业版64

1.样本概况

1.1 应用程序信息

应用程序名称:010editor

MD5值:94129C68103C03F7E77C17BCB87E5DCB

SHA1值:12D0A60D6018AE6A35FB20D5EEE81737E5ACE84D

简单功能介绍:

说明: 010 Editor 是一款非常强大的文本、十六进制编辑器,除了文本、十六进制编辑外,还包括文件解析、计算器、文件比较等功能,但它真正的强大之处还在于文件的解析功能。我们可以使用 010Editor 官方网站提供的解析脚本对 avi、bmp、png、exe ,apk等简单格式的文件进行解析,当然也可以根据需求来自己编写文件解析脚本。但是 010 Editor 是收费的,不过官方给出了 30 天的免费使用期限供用户体验。本文将为大家分析如何去除使用限制和编写注册机。目前最新版本为 v9.0.1,也是本文将分析的版本。010 Editor 官网:http://www.sweetscape.com/010editor/ 。

1.2 分析环境及工具

例如:系统环境:win732位虚拟机,win1064位专业版

工具: Ollydbg动态调试代码

CheatEngine 内存搜索

PEID/exeinfo 查壳,查编译环境

010Editor,十六进制编辑器

VisualStudio 开发程序

1.3 分析目标

1.暴力破解官方版本可以自己用

2.编写注册机可以正常破解程序

1. 具体分析过程

2. 在没有源代码的情况下,可以分析 和打补丁的结果就是破解。暴力破解的特点相对比较快!因为属于比较简单的破解方式,常用的破解方式有暴力破解,计算序列号,编写注册机

2.具体分析过程

暴力破解(暴破):
分析步骤

• 找到注册窗口

• 测试注册窗口的反应

• 根据反应做出下一步分析的打算(猜测 API、API 下断动态调试、挑出敏感字符串,在程序中搜索)

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

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

找到注册窗口

使用OD打开程序,打开主模板窗口(E),点击右键,能够查看名称,可以查看导入导出的函数信息

image.png

另外一个方法是可以在反汇编主窗口中©使用快捷键ctrl+n

image.png

查看名称信息

image.png

发现其中名称中带有QT的函数很多,说明这是QT界面库写的,我们可以查看QT源码分析或者使用windowsSdk的思路分析

QT源码分析

1.下载源码库

2.找到库函数

WindowsSdk分析

网上查询资料,发现不管是何种高级语言,在底层中还是得调用诸如 CreateWindowMessageBox 以及一些 Dialog 相关的函数,这些函数位于 User32.dll 中!同样点击 OD 上方的小e 按钮,在里面找到 user32.dll,双击进去,在这里要说一点就是,创建窗口的 API 函数不止一个,而且也不存在 CreateWindowMessageBox 这类函数,其实它们只是个,在深入一点都是调用Ex的版本,那么问题又来了,是调用 A 版 还是调用 W 版 的,学过 windows 编程的都知道,A 版 的最终还是会去调用 W 版 的, 所以我们不妨先对 CreateWindowExW 函数下断,按 Ctrl + G,输入 CreateWindowExW,如下:

image.png

点击OK,找到注册窗口位置
image.png

测试注册窗口的反应

F2打上断点,回到010Editor程序界面,单击checkLicense,发现程序可以断点
image.png

程序正常命中断点

image.png

根据反应做出下一步分析的打算(猜测 API、API 下断动态调试、挑出敏感字符串,在程序中搜索)

断下来之后,我们接下来要想的是哪里调用了这个函数,我们可以上方的 k 小按钮来查看,如下:

image.png

带有QT功能属于QT函数,这里我们看WindowsApi中提供的函数,通过栈回溯分析,可以看出,在地址 001DCF6C上的函数过程有个很显眼的字 show,貌似跟显示窗口有关,我们双击进去看下里面有什么可以利用的信息,结果没发现有价值的东西,不要慌,我们继续点击上面这个地址的下一个地址,双击进行查看,结果也没有,再跟进去下一个地址,也就是 001DD044处,双击进去,会发现如下这种情况:

image.png

通过上图可以看出,在这里面出现了大量可疑的字符串,其中 Invalid name or password...... 这个字符串就是我们随意输入用户名和密码时弹出的信息提示,该处为一个 push 指令

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

找到 push 指令,按下ctrl+A 分析程序,会出现跳转窗口

image.png

右键,点击转到JNZ来自01805A79

image.png

跳转到上面的判断中,重新触发断点之后发现跳转到下面的Cmp,说明找到关键位置0x71!

程序底部的跳转位置总共有三组CMP指令,首先来到第一组分析源程序

01805A58 地址处的 CMP 指令,有一条源跳转,01805926

第二步的跳转如下

01805926位置上面的比较有两个跳转,分别是01805827,01805831

01805827处EBXDS值需要做比较,如下:

image.png

不妨在上面处下个断,重新回到注册界面,点击 Check License,会发现它会断在刚下的这个断点处,按 F8 下去,你会发现有两个关键的地方,一个是 EDI 的值,一个是 EBX 的值,前者需要和 0xDB 这个值作比较,后者则需要跟 0xE7 这个值作比较,如下:

image.png

这些值都是EAX中的,EAX存放的都是函数的返回值信息,我们找到了关键位置,现在将值NOP掉,如下:

image.png

最后保存一下文件

image.png

image.png

文件保存成功之后我们测试一下

image.png

发现破解失败了!接着重新分析一下

image.png

这个问题是因为没有保存成功导致!选择所有修改,并且二进制为NOP!

保存后的效果如下:

image.png

每次打开软件都弹出Register这个用户体验很差,怎么解决呢?

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

捋一下思路

如果 EBX0xE7 则跳,跳过之后,再对 EDI 比较,此时 EDI 0x1770x177 不等于 0xDB又跳走,接着有两次对 EDI 进行比较,值分别为 0xED 0x20C,我们知道,EDI 值0x177,所以两处的 JE 指令不成立,最后对比 EBX 的值,用它跟 0x93 对比,很明显 0xE7 不等于 0x93,所以 JNZ 指令成立,将跳过密码已被接受过程。

所以为了一开始不跳,EBX 的值要不为 0xE7EDI 的值要为 0xDB,在上面谈到的两个重要的 CALL 里,第二个 CALL 是根据第一个 CALL 的最终 EAX 的来进行对 EDI 进行赋值,所以,为了让 EDI 的值为 0xDBEBX 的值要为 0x2D,也就是说第一个 CALL 的最终 EAX 值要为 0x2D,我们可以跟进第一个 CALL 内,在最开头部分写下:

image.png

最开头部分修改为2D

接下来我们需要返回值,如果有下划线代表重定位,重定位会导致随机基质,产生随机基质就会导致修改失败。我们打开010EditorOP头里面修改它的随机基质后接着再来分析程序,如下图:

image.png

image.png

最后Ctrl+s保存

回到OD后,RET 8 发现怎么保存都达不到效果!于是我又开始重新分析!重新安装一个文件,拖到OD中,注释标记过这里是关键位置,但是这并不是唯一的位置,再次分析找一下

image.png

分析之后,发现第二个关键位置,我们修改后保存

![](file:////private/var/folders/_p/q2v_2l_52t1cyd3sl8vz4n1r0000gn/T/com.kingsoft.wpsoffice.mac/wps-spider/ksohtml//wps28.jpg)

保存测试成功打开,可以用010分析010了

image.png

注册机:

账户名统一使用:

www.15pb.com.cn

密码统一使用:

11 22 33 44 55 66 77 88 99 AA

算法基础分析

我们分析出来了第一个Call,并且在Call位置处添加了mov eax,0x2D ret 8 这两条指令,接下来我们沿着这个方向继续分析

第一步首先看下Call有哪些参数

image.png

传的参数肯定和用户名密码有关系,不妨跟进ECX所处的数据窗口ECX的值为02D80F20

可以看到这个地址是一个数组,接着我们找到用户名信息如下:

image.png

找到密码信息如下:

image.png

这里的密码就是序列号,我们找到关键信息了,继续往下分析
image.png

获取到当前用户名密码的信息,这里的密码也可以称为序列号,后面分析的时候可以用到它;

image.png

通过上图可以看到ECX 存放的是 this 指针,而this 指针指向的是一个字符串数组,这个数组存放着用户名和密码字符串,我已将说明标注在上图中。所以为什么说之前我们需要跟进 ECX 中的数据窗口去查看下这个地址里存放的是什么东西,那么在上图分析过程中起到一个辅助作用。

F8继续往下分析,找到关键位置

image.png

在检测用户名和密码是否为空后,紧接着将一个局部变量的值压如栈中,右键栈中的地址数据窗口跟随,会发现这个数据是你输入的密码字符串,而且为 16 进制,所以说 PUSH 指令下的这个 CALL,是将密码字符串转为 16 进制字节的数据。如果你不放心,可以多测试几下,这里把密码换成 1122-3344-5566-7788-99AA,如下:
image.png

继续分析,发现程序会循环把999压入栈中,Call里面QT函数处理了什么我们先不去管继续分析

image.png

下图中K[0],K[1] 对应的你输入的密码1122-3344-5566-7788-99AA 那么K[0] 就是11K[1]就是22, k[3]就是33 依次类推

image.png

这个地方一直跳不过去!

在上图中,有几个关键点地方,第一个圈起来的,它会拿你输入的密码的第 4 组数据去和 0x9C、0xAC、0xFC 这三个数进行比较,如果不是这三个数中的其中一个,那么程序会将 0xE7 赋值给 EAX,而在前面一小节当中,EAX 的值不能为 0XE7,否则失败,所以我们令 JNZ 下方这条指令为新的 EIP,否则 JNZ 条件成立跳过去了,就不好分析了,最后我们可以肯定,密码有三个版本,这里只分析下 0x9C 这个版本。第二个关键点是第二个圈起来的地方,跟进这个 CALL 里,如下:

image.png

还好这个 CALL 里的代码并不是太复杂,主要处理的是 k[0] 和 k[6],也就是 1177 这两个数。第三个关键点是第三个圈起来的地方,我们跟进这个 CALL 内,如下:

image.png

同样,代码也不复杂,主要是判断余数是否为 0,如果为 0,那么就返回商,如果不为 0,那么就返回 0。所以这么一整段下来,在对 k[0]、k[1]、k[2]、k[3]、k[4]、k[5]、k[6]、k[7] 在进行操作,而我们输入的密码有 10 组,OD 中并没看到对 k[8]、k[9] 进行处理,这里说这么一嘴,然后继续往下分析

image.png

写代码验证:

输出结果如下:

image.png

测试一下9C返回值是否正确

image.png

由于是9C所以长度发生变化断点分析一下

image.png

跳出9C,程序正常运行,说明生成的序列号代码是对的,继续分析,看到返回值也不为0

image.png

以上代码只是让你遇到那两个 JE 和一个 JA 跳转指令可以使它不成立,这个雏形生成的密码并没有与用户名进行关联,在下一小节当中会分析密码与用户名的之间的联系。

算法深度分析

在上一小节当中,通过穷举法来找出符合要求的密码。下面将会为大家分析下用户名和密码之间的关系。

image.png

F7进去之后发现,这一段主要是将用户名的字符串转为 ASCII 版,在接下来的一个调用 CALL 后,EAX 中为用户名字符串地址,如下:
image.png

将用户名字符串处理后的返回值传递给EDX,然后与密码K[4],K[5],K[6],K[7]发生关系

image.png

ss:[ebp+0x8]此处为本Call智商传入来的参数0XA

在上图中的 ds:[edi+0x1C] 处其实是前面处理 k[0] 和 k[6] 那个 CALL 后的返回值(即 AL 的值),所以我们需要将代码中的

if (AL > 0)
{
    k[0] = k0;
    k[6] = k6;
    break;
}

改为如下:

if (AL >= 9)
{
    k[0] = k0;
    k[6] = k6;
    break;
}

接下来就是要做的就是那个对用户名处理的 CALL,通过分析知道,这个 CALL 的返回值类似于哈希值,我们需要得到这个值,回为这个值需要和k[4]、k[5]、k[6]、k[7] 发生关系,我们不妨声明这样一个函数,用来处理 ASCII 码版的用户名字符串,这里有个取巧的办法,那就是利用 IDA,将 010 Editor 载入 IDA 中,我们需要先获取处理这个用户名字符串的 CALL 的地址,这个地址可以通过 OD 找到,找到之后,切换到 IDA,按 g 输入地址回车,再按下F5进行翻译,如下:

image.png

1. 使用OD->Ctrl+x copy地址

2. 使用IDA->Ctrl+G找到地址->F5转换为C代码

3. 找到数组地址,copy数据

IDA分析花了两个小时,但是还没有分析完,继续使用OD查看思路

0X3734148地址中存放的这些数据,我们复制一下

image.png

image.png

把刚刚复制过来的数据放到数组里面
image.png

完整的注册机代码:

接下来测试序列号是否正常!

首先 根据名称生成序列号:

image.png

接下来把序列号放到Register窗口中测试,发现需要验证网络

image.png

测试不通过,由于网络验证无法正常绕过导致,我们继续分析

网络验证

出现这种情况是 010 Editor 会把该密码上传到它的服务器,如果发现不是通过正常渠道获取得的密码,它会把这个密码拉黑,出现上述这种情况你也不要慌,接下来我会为大家分析怎么来去除网络验证。

打开 OD,把 010 Editor 拖进来,F9 运行起来,点击 Check License,会断在如下地方:

image.png

F8 来到 0010D75819 处,如果按照正常来说,在调用完这两个 CALL 后,EAX 中的值要为 0xDB,而此时变成了 0x113,第一个 CALL 调用后,EAX 的值为 0x2D,这个没问题,那么问题可能出现在第二个 CALL 内,这个 CALL 本应该把 EAX 的值修改为 0xDB,而它去却把它修改成了 0x113,我们不妨跟进这个 CALL 内,如下:

image.png

image.png

F8 运行到此处后,发现此处的 JE 指令跳转不成功,接下来的 mov eax,0x113 代码将被执行并返回,所以需将 JE 指令改为 JMP,改完之后,该 CALL 最后返回 0xDB,而不是 0x113,在后面你会发现即使修改了这处,它还是一样会验证失败,原因如下:

image.png

这个 JNS 指令它会跳到失败处,也就是那个字符串提示你的密码已被删除,注意图中的 EAX 的值,它为 -1,同时,在运行 00E0824B 的 CALL 指令会卡一下,如下:

image.png

整个注册界面会变灰,这时它在调用这个 CALL 进行网络验证,需要等待一下,等它验证完后,EAX 的值变会变成 -1,从而使得 JNS 指令成立,所以解决的办法是进入到网络验证这个 CALL 内,把 EAX 的值修改成不是负数,在这我把它改成1,如下:

MOV EAX,0X1
RET 0X4
NOP
NOP

ret 多少,可以向下滑,看它正常 ret 多少,你这里也 ret 多少,最后 Dump 出来覆盖原文件就可以了,注册机还是不变,只要你从官网下载 32 位版的 010 Editor 并安装在你计算机后,将下方的 Dump 文件覆盖安装目录下的原文件,运行注册机后注册即可,以后就不用担心拉黑了。

去掉网络验证,接着测试 发现用户名密码验证不通过!检查下算法,看下哪里出问题了

image.png

找到问题,是因为我这里的nRet 是固定的,所以不要写成 `<=``

image.png

正常进行网络验证

image.png

网络验证绕过去->

image.png

image.png

image.png

测试一下,查看结果

image.png

任务完成!建议不要用破解版本,尊重知识产权! 本报告不发布到商业用途,只是用于提交作业!

总结

算法总结:

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

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

3. 验证密码16进制数据

1. K[3] = 0x9c 或者 0xFc 或者 0xAc,Fc和Ac待分析

2. Sub_00407644 函数的返回值不能为0

1. 即AL = (K[0] ^ K[6] ^ 0x18 + 0x3D) ^ 0x47

2. AL!=0

3. Sub_004084C8 函数的返回值不能为0,且小于等于0x3E8

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

2. Eax = ((esi^0x7892+0x4D30)^0x3421) & 0xffff

3. If(eax%oxb == 0 且 eax/0xb <= 0x3e8)

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

5. 使用用户名计算出了一个key,与密码K[4]~K[7]相等

2. 调用sub_402e50函数,参数是用户名字符串、10、sub_4083C8函数的返回值;

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

4. Cmp K[4],retValue&0XFF

5. Cmp K[5],retValue>>8&0Xff

6. Cmp K[6],retValue>>16&0Xff

7. Cmp K[7],retValue>>24&0xFF

6. 判断参数

8. Cmp arg,sub_00407644’s retValue >= 9
注册机总结:

版本1-> 随机字节,穷举找出符合条件的值;

版本2-> 指定用户名,调用加密函数求出key

将Key拆分,指定到密码字节数组

穷举剩下的字节

个人总结:

本次编写010Editor花费了接近4天时间,包括讲的最新的课也落下了!让我更加焦虑了!但是通过自己的努力分析了一遍010Editor,算是有了很大的收获!不难,耐心很重要!

不难,耐心很重要!

不难,耐心很重要!

不难,耐心很重要!

世上无难事只怕有心人!

参考文献

[1] 看雪,https://bbs.pediy.com/thread-255625-1.htm,2019

[3] 看雪,https://bbs.pediy.com/thread-270569.htm#msg_header_h3_3,2021