商业软件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),点击右键,能够查看名称,可以查看导入导出的函数信息
另外一个方法是可以在反汇编主窗口中©使用快捷键ctrl+n
查看名称信息
发现其中名称中带有QT
的函数很多,说明这是QT界面库
写的,我们可以查看QT源码分析
或者使用windowsSdk
的思路分析
QT源码分析
1.下载源码库
;
2.找到库函数
;
WindowsSdk分析
网上查询资料,发现不管是何种高级语言,在底层中还是得调用诸如 CreateWindow
、MessageBox
以及一些 Dialog
相关的函数,这些函数位于 User32.dll
中!同样点击 OD
上方的小e
按钮,在里面找到 user32.dll
,双击进去,在这里要说一点就是,创建窗口的 API 函数
不止一个,而且也不存在 CreateWindow
、MessageBox
这类函数,其实它们只是个宏
,在深入一点都是调用Ex
的版本,那么问题又来了,是调用 A 版 还是调用 W 版
的,学过 windows 编程的都知道,A 版 的最终还是会去调用 W 版 的
, 所以我们不妨先对 CreateWindowExW
函数下断,按 Ctrl + G
,输入 CreateWindowExW
,如下:
点击OK,找到注册窗口位置
测试注册窗口的反应
F2打上断点,回到010Editor
程序界面,单击checkLicense
,发现程序可以断点
程序正常命中断点
根据反应做出下一步分析的打算(猜测 API、API
下断动态调试、挑出敏感字符串
,在程序中搜索)
断下来之后,我们接下来要想的是哪里调用了这个函数,我们可以上方的 k 小按钮
来查看,如下:
带有QT功能
属于QT函数
,这里我们看WindowsApi中提供的函
数,通过栈回溯分析,可以看出,在地址 001DCF6C上
的函数过程有个很显眼的字 show
,貌似跟显示窗口有关,我们双击进去看下里面有什么可以利用的信息,结果没发现有价值的东西,不要慌,我们继续点击上面这个地址的下一个地址,双击进行查看,结果也没有,再跟进去下一个地址,也就是 001DD044
处,双击进去,会发现如下这种情况:
通过上图可以看出,在这里面出现了大量可疑的字符串,其中 Invalid name or password......
这个字符串就是我们随意输入用户名和密码时弹出的信息提示,该处为一个 push 指令
动态分析,定位关键跳转,修改代码
找到 push 指令
,按下ctrl+A
分析程序,会出现跳转窗口
右键,点击转到JNZ来自01805A79
跳转到上面的判断中,重新触发断点之后发现跳转到下面的Cmp
,说明找到关键位置0x71!
程序底部的跳转位置总共有三组CMP指令
,首先来到第一组分析源程序
在 01805A58 地址处的 CMP 指令
,有一条源跳转,01805926
第二步的跳转如下
01805926位置上面
的比较有两个跳转
,分别是01805827,01805831
01805827处
,EBX
和DS值
需要做比较,如下:
不妨在上面处下个断,重新回到注册界面,点击 Check License
,会发现它会断在刚下的这个断点处,按 F8
下去,你会发现有两个关键的地方,一个是 EDI
的值,一个是 EBX
的值,前者需要和 0xDB
这个值作比较,后者则需要跟 0xE7
这个值作比较,如下:
这些值都是EAX中
的,EAX
存放的都是函数的返回值信息,我们找到了关键位置
,现在将值NOP
掉,如下:
最后保存
一下文件
文件保存成功之后我们测试一下
发现破解失败了!接着重新分析一下
这个问题是因为没有保存成功导致!选择所有修改,并且二进制为NOP!
保存后的效果如下:
每次打开软件都弹出Register
这个用户体验很差,怎么解决呢?
动态分析,定位关键 CALL,修改代码
捋一下思路
如果 EBX
为 0xE7
则跳,跳过之后,再对 EDI
比较,此时 EDI
为 0x177
,0x177
不等于 0xDB
又跳走,接着有两次对 EDI
进行比较,值分别为 0xED
和 0x20C
,我们知道,EDI 值
为 0x177
,所以两处的 JE 指令
不成立,最后对比 EBX 的值
,用它跟 0x93
对比,很明显 0xE7
不等于 0x93
,所以 JNZ 指令
成立,将跳过密码已被接受
过程。
所以为了一开始不跳,EBX 的值要不为 0xE7
,EDI 的值要为 0xDB
,在上面谈到的两个重要的 CALL
里,第二个 CALL
是根据第一个 CALL
的最终 EAX
的来进行对 EDI
进行赋值,所以,为了让 EDI 的值为 0xDB
,EBX 的值要为 0x2D
,也就是说第一个 CALL
的最终 EAX 值
要为 0x2D
,我们可以跟进第一个 CALL
内,在最开头部分写下:
最开头部分修改为2D
接下来我们需要返回值,如果有下划线代表重定位
,重定位会导致随机基质
,产生随机基质就会导致修改失败。我们打开010Editor
在OP头
里面修改它的随机基质后接着再来分析程序,如下图:
最后Ctrl+s
保存
回到OD
后,RET 8
发现怎么保存都达不到效果!于是我又开始重新分析!重新安装一个文件,拖到OD
中,注释标记过这里是关键位置
,但是这并不是唯一的位置,再次分析找一下
分析之后,发现第二个关键位置,我们修改后保存

保存测试成功打开,可以用010分析010了
!淦
注册机:
账户名统一使用:
www.15pb.com.cn
密码统一使用:
11 22 33 44 55 66 77 88 99 AA
算法基础分析
我们分析出来了第一个Call
,并且在Call
位置处添加了mov eax,0x2D ret 8
这两条指令,接下来我们沿着这个方向继续分析
第一步首先看下Call
有哪些参数
传的参数肯定和用户名密码
有关系,不妨跟进ECX所处的数据窗口
,ECX
的值为02D80F20
可以看到这个地址是一个数组
,接着我们找到用户名信息如下:
找到密码信息
如下:
这里的密码就是序列号
,我们找到关键信息
了,继续往下分析
获取到当前用户名
和密码
的信息,这里的密码也可以称为序列号
,后面分析
的时候可以用到它;
通过上图可以看到ECX
存放的是 this 指针
,而this 指针
指向的是一个字符串数组
,这个数组存放着用户名和密码字符串
,我已将说明标注在上图中。所以为什么说之前我们需要跟进 ECX
中的数据窗口去查看下这个地址里存放的是什么东西,那么在上图分析过程中起到一个辅助作用。
F8继续往下分析
,找到关键位置
在检测用户名和密码
是否为空后,紧接着将一个局部变量
的值压如栈中
,右键栈中
的地址数据窗口跟随,会发现这个数据是你输入的密码字符串
,而且为 16 进制
,所以说 PUSH 指令下的这个 CALL
,是将密码字符串转为 16 进制字节
的数据。如果你不放心,可以多测试几下,这里把密码换成 1122-3344-5566-7788-99AA
,如下:
继续分析,发现程序会循环把999
压入栈中,Call里面QT函数
处理了什么我们先不去管继续分析
下图中K
[0],K
[1] 对应的你输入的密码1122-3344-5566-7788-99AA
那么K
[0] 就是11
,K
[1]就是22
, k
[3]就是33
依次类推
这个地方一直跳不过去!
在上图中,有几个关键点地方,第一个圈起来的,它会拿你输入的密码的第 4 组数据去和 0x9C、0xAC、0xFC
这三个数进行比较,如果不是这三个数中的其中一个,那么程序会将 0xE7
赋值给 EAX
,而在前面一小节当中,EAX
的值不能为 0XE7
,否则失败,所以我们令 JNZ
下方这条指令为新的 EIP
,否则 JNZ
条件成立跳过去了,就不好分析了,最后我们可以肯定,密码有三个版本,这里只分析下 0x9C
这个版本。第二个关键点是第二个圈起来的地方,跟进这个 CALL
里,如下:
还好这个 CALL
里的代码并不是太复杂,主要处理的是 k
[0] 和 k
[6],也就是 11
和 77
这两个数。第三个关键点
是第三个圈起来
的地方,我们跟进这个 CALL
内,如下:
同样,代码也不复杂,主要是判断余数是否为 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]
进行处理,这里说这么一嘴,然后继续往下分析
写代码验证:
输出结果如下:
测试一下9C
和返回值
是否正确
由于是9C
所以长度发生变化
,断点分析
一下
跳出9C
,程序正常运行,说明生成的序列号代码
是对的,继续分析,看到返回值也不为0
以上代码只是让你遇到那两个 JE
和一个 JA 跳转指令
可以使它不成立,这个雏形
生成的密码并没有与用户名进行关联,在下一小节当中会分析密码与用户名的之间的联系。
算法深度分析
在上一小节当中,通过穷举法来找出符合要求的密码。下面将会为大家分析下用户名和密码之间的关系。
F7进去
之后发现,这一段主要是将用户名的字符串转为 ASCII 版
,在接下来的一个调用 CALL
后,EAX 中为用户名字符串地址
,如下:
将用户名字符串处理后的返回值传递给EDX
,然后与密码K[4],K[5],K[6],K[7]
发生关系
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
进行翻译,如下:
1. 使用OD->Ctrl+x
copy地址
2. 使用IDA
->Ctrl+G
找到地址->F5转换为C代码
3. 找到数组地址,copy数据
IDA分析花了两个小时,但是还没有分析完,继续使用OD查看思路
0X3734148
地址中存放的这些数据,我们复制一下
把刚刚复制过来的数据放到数组里面
完整的注册机代码:
接下来测试序列号是否正常!
首先 根据名称生成序列号:
接下来把序列号放到Register窗口
中测试,发现需要验证网络
测试不通过,由于网络验证无法正常绕过导致,我们继续分析
网络验证
出现这种情况是 010 Editor
会把该密码上传到它的服务器,如果发现不是通过正常渠道
获取得的密码,它会把这个密码拉黑
,出现上述这种情况你也不要慌,接下来我会为大家分析怎么来去除网络验证。
打开 OD
,把 010 Editor
拖进来,F9
运行起来,点击 Check License
,会断在如下地方:
F8
来到 0010D75819
处,如果按照正常来说,在调用完这两个 CALL
后,EAX
中的值要为 0xDB
,而此时变成了 0x113
,第一个 CALL
调用后,EAX
的值为 0x2D
,这个没问题,那么问题可能出现在第二个 CALL
内,这个 CALL
本应该把 EAX
的值修改为 0xDB
,而它去却把它修改成了 0x113
,我们不妨跟进这个 CALL
内,如下:
F8
运行到此处后,发现此处的 JE 指令
跳转不成功,接下来的 mov eax,0x113
代码将被执行并返回,所以需将 JE 指令改为 JMP
,改完之后,该 CALL 最后返回 0xDB
,而不是 0x113
,在后面你会发现即使修改了这处,它还是一样会验证失败,原因如下:
这个 JNS 指令
它会跳到失败处,也就是那个字符串提示
你的密码已被删除,注意图中的 EAX
的值,它为 -1
,同时,在运行 00E0824B 的 CALL 指令
会卡一下,如下:
整个注册界面会变灰,这时它在调用这个 CALL
进行网络验证
,需要等待一下,等它验证完后,EAX 的值变会变成 -1
,从而使得 JNS 指令
成立,所以解决的办法是进入到网络验证这个 CALL
内,把 EAX
的值修改成不是负数,在这我把它改成1
,如下:
MOV EAX,0X1
RET 0X4
NOP
NOP
ret
多少,可以向下滑,看它正常 ret
多少,你这里也 ret
多少,最后 Dump
出来覆盖原文件就可以了,注册机还是不变,只要你从官网下载 32 位版的 010 Editor
并安装在你计算机后,将下方的 Dump
文件覆盖安装目录下的原文件,运行注册机
后注册即可,以后就不用担心拉黑了。
去掉网络验证,接着测试 发现用户名密码验证不通过!检查下算法
,看下哪里出问题了
找到问题,是因为我这里的nRet
是固定的,所以不要写成 `<=``
正常进行网络验证
网络验证
绕过去->
测试一下,查看结果
任务完成!建议不要用破解版本,尊重知识产权!
本报告不发布到商业用途,只是用于提交作业!
总结
算法总结:
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函数,参数是用户名字符串、1、0、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