本帖最后由 ATree 于 2018-4-8 10:18 编辑
新人首发原创破解帖,感谢吾爱破解这个大平台提供的资源,感谢在15PB教我技术的老师们。
说明:今天发布的帖子中是包含我对010Editor 8.0.1最新版软件的一些逆向破解分析+注册机,虽然之前已经有一些帖子分析了010Editor 8.0这个软件,但没有人分享注册机,而且我会分享我的注册机源码,虽然对于大神来说比较简单,但大神也往往是从小白来的,所以我这篇分析主要是针对一些刚刚踏进信息安全圈的逆向分析新手,因为我也是新手,所以新手和新手之间的交流会比较容易懂,容易理解。
发帖前特意读了版规,按照版规,软件正常运行截图:
软件介绍:
SweetScape 010 Editor是一个全新的十六进位文件编辑器,它有别於传统的十六进位编辑器在于它可用模板来解析二进位文件, 从而让你读懂和编辑它. 它还可用来比较一切可视的二进位文件.总之在Windows平台下,这款十六进制编辑工具是相当的好用。
使用说明:
由于010Editor它提供一些模板,你可以使用它来解析PE文件,解析各种格式的文件,以及还可以用来对比二进制文件,逆向破解时这个软件非常有用。
逆向代码部分:0x00
图中我标注关键函数处,我是通过栈回溯(ctrl+k)找到的,我起初是利用OD插件中API下断插件,在所有对话框函数都下断点了,确定创建输入用户名和序列号的对话框是调用CreateWindowEx函数,这里需要提醒一点,在你找到创建输入序列号的窗口时,你此时断下来的位置是无法栈回溯到用户层代码的,这就需要你谨慎的单步跟了,注意观察是哪个用户层函数调用的。后面我同学提示我可以用字符串搜索,因为我最先也是使用字符串搜索的,没有搜索到,而后我就采用了此法,我猜测当时我两次搜索时程序都还未解密这些提示信息字符串,不过这也好,锻炼了使用栈回溯的方法寻找突破口的思维。
0x01
关键函数调用后,这一层中就可以看到各种提示信息字符串了,找到我们弹窗中的提示信息字符串,一步一步这么倒推上去,从而可以找到跳转指令处,这就需要我们转换下思维,不管是在CrackMe还是破解软件过程中,思维方式要灵活多变,因为软件设计及开发是灵活多变的。
0x02
找到跳转处,发现是在地址 0x01375A79跳转过去的,此时我们就要想了,那么是如何执行到这条指令的?顺着执行下来的吗?带着问题去思考,我们检查下该地址周围是否有跳转,会发现在地址 0x01375A58 CMP EDI,0xED这条指令处有一个跳转,我们继续向上寻找跳转处。
0x03
会发现这里是跳转处,对于这种常见的JCC系列的跳转指令,一定要熟悉,不熟悉就赶紧打开你的Intel指令手册,查看相应的指令含义以及是否受标志位影响,指令 JNZ 0x01375A58 含义是不等于0短跳转,那么就看它的上条指令是否相等,上条指令为 CMP EDI,0xDB,那么此时就可推理出如果EDI的值为 0xDB,那么就是弹出购买成功的窗口。我们就以此为线索寻找在何处EDI的值被赋为0xDB,注意在0x01375920地址处又是一个跳转跳过来的,继续向上找。我们也可以在此处进行暴力破解,就是将指令修改下,然后保存一份新文件,你再次打开运行时随意输入用户名和序列号,都可以注册成功。
0x04
我们可以从图中跳转处指令可知,先执行了 地址:0x01375821 CMP EBX,0xE7,然后 地址:0x01375827 JE 0x01375920,所以要想弹出正确的窗口,即EBX!=E7,EBX的值是来自于 0x01375800 地址处的函数返回值,而且我们也发现了EDI的值来自于EAX,也就是当 0x01375814 地址处函数执行完以后得到的返回值EAX又赋值给了EDI,此时一切都豁然开朗了,只要将这两个函数分析下,使之返回值分别不等于E7 和 等于DB即可。
0x05
0x009AA826 函数分析
还是一样的方法,向上寻找,不过我们的要求是最后的结果是不等于E7,所以向上找不会跳转过来将E7赋值给EAX的操作。最后经过几次分析之后会发现0x0195DE43处 MOV ESI,0x2D有跳转,并且只有将EAX赋值为0x2D时才是正确的操作。
此图中我已注释了部分操作,有对用户名字符串加密的操作,然后将用户名加密后得到的4字节数据与用户输入的序列号中某位进行比较,这是我在追码的过程得出的结论,只有当这一个个跳转条件不满足时才能执行到0x0195DDEF地址处,从而跳转到赋值为0x2D处。
这部分代码都是对序列号的判断,有异或操作,也有整除判断的操作,但凡是有条件不满足即跳出这里,将EAX赋值为0xE7。
代码易懂我就不细说了。
0x03404148地址中保存的是一个全局数组,它是010Editor中的密码表,循环次数为用户名称字符串的长度,每次循环都会从表中取出4字节数据,进行异或,有符号乘法,加法等操作,对字符串进行一定操作后得到的4字节数据便是真正序列号的后4个字节。
这是用户名字符串加密函数的主要部分了,因为这部分汇编代码你只要认真读下去,还是都能理解是什么意思,什么操作,这部分汇编代码看不太懂的,可以参考我的注册机中写的代码。
0x06
0x009A9C9B 函数分析
这个函数我们需要返回值为DB才是正确的弹窗。
进一步分析函数 0x009AA826,会发现这个函数和我们之前分析的是一个相同的函数。至此我们就可以顺着它对用户名字符串加密后得到的4字节数据与用户输入的序列号之间的操作来编写我们的注册机了。
0x07
[C] 纯文本查看 复制代码 int Original_Data_Array[1024] = {
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 };
全局变量数组,这个是从010Editor 内存中扣取出来的,也就是我上面提到的密码表。
[Asm] 纯文本查看 复制代码 DWORD GetEncryStr(char* Inputstr, DWORD Num)
{
int Tmp_Num = Num << 0x4;
Tmp_Num -= Num;
DWORD change_ch;
DWORD Local_data = 0,
Local_data1,
Local_data2_9 = 0,
Local_data3_13 = 0,
Local_data4_7 = 0;
int len = strlen(Inputstr);
for (int i = 0; i < len; i++)
{
Tmp_Num %= 0x100;
change_ch = toupper(Inputstr[i]);
Local_data1 = Original_Data_Array[change_ch];
Local_data1 += Local_data; //加上局部变量中保存的值
Local_data1 ^= Original_Data_Array[(change_ch + 0xD) & 0xFF];
Local_data1 *= Original_Data_Array[(change_ch + 0x2F) & 0xFF];
Local_data1 += Original_Data_Array[Local_data2_9];
Local_data1 += Original_Data_Array[Tmp_Num]; //这一步中ebx的值必须从之前的操作中获取
Local_data1 += Original_Data_Array[Local_data3_13];
Local_data = Local_data1;
Local_data3_13 += 0x13;
Local_data2_9 += 0x9;
Tmp_Num += 0xD;
Local_data4_7 += 0x7;
}
return Local_data;
}
通过传入用户名字符串的首地址与一个不大于3E8的随机数,就可以得到与010Editor计算相同的加密4字节数据。
[C] 纯文本查看 复制代码 DWORD GetRandNum(){
DWORD Result;
srand((unsigned)time(NULL));
return Result = rand() % 0x3E8; //这里的0x3E8说明下,是我想要随机的区间,区间是(0,3E8]
}
这是简单的获取不大于3E8的随机数函数
[C] 纯文本查看 复制代码 void CMFC_010Editor注册机Dlg::OnBnClickedOk()
{
UpdateData(TRUE);
DWORD Tmp_Num, Tmp_Val1, Tmp_Val2, Tmp_Val3;
char destbuf[100] = { 0 };
DWORD RandNum = GetRandNum();
Tmp_Num = (((RandNum * 0xB) ^ 0x3421) - 0x4D30) ^ 0x7892;
Tmp_Val1 = (Tmp_Num / 0x100) % 0x100; //随机数高字节(A9)
Tmp_Val2 = Tmp_Num % 0x100; //随机数低字节(3B)
USES_CONVERSION;
char *username = T2A(UserName);
DWORD num = GetEncryStr(username, RandNum);
short Res4 = num / 0x1000000; //3B
short Res1 = num % 0x100; //A6
short Res2 = (num % 0x10000) / 0x100; //46
short Res3 = (num / 0x10000) % 0x100; //9A
Tmp_Val1 ^= Res4; //随机数高字节与加密后字节异或 92
Tmp_Val2 ^= Res2; //随机数低字节与加密后字节异或 7D
Tmp_Val3 = Res3 ^ 0x72; //计算序列号第一个字节
sprintf_s(destbuf, "%X%X-%X9C-%X%X-%X%X", Tmp_Val3, Tmp_Val1, Tmp_Val2, Res1, Res2, Res3, Res4);
Serial_Number = A2T(destbuf);
UpdateData(FALSE);
}
这就是用户点击确定以后根据各个函数返回值来拼接计算出的真正的序列号。最后显示给用户……注册机是MFC编写。
注册机源码,这是根据读懂了之前我所说的那段汇编代码之后进行编写的,实际上就是它的序列号核心算法了,虽然起初很难搞,甚至没有思路,但是有了一点思路后再一点点深挖还是可以看见曙光的。最后忘了说一点,注册机得到的序列号在010Editor 7.0版本中也可以注册使用。
2018年了,又是新的一年,其实我这个是在2017年还有5分钟结束的时候推导出它的序列号算法的,可能间接的告诉我做所有的事情都应该有始有终吧。新的一年里,祝福吾爱破解越办越好,内容越来越精彩,同时也祝福教授我如此之多知识的15PB老师们,工作顺利,身体健康。祝每一位热爱逆向、热爱破解的小伙伴都能坚持到底,实现自己的大神梦~
X32_010Editor注册机 链接: https://pan.baidu.com/s/1i6iFXid 密码: f7d4(永久有效)
已更新X64注册机:
X64_010Editor注册机 链接: https://pan.baidu.com/s/1dGOL8OT 密码: wqhe
(永久有效 2017.1.9更新)
010Editor 8.0.1 64Bit 破解版(软件打包成压缩文件了),让各位久等了,之前有点忙,不好意思,现在将附上链接:https://pan.baidu.com/s/1B5f7ui087fCeLs67uoQWDQ 密码:zglh (永久有效 2018.4.8更新)
补丁文件下载链接:https://pan.baidu.com/s/1r2f67Se_2QXhZApVYv09Rw 密码:p0g7 (永久有效)(用这个替换你安装路径下的010Editor.exe文件后,再用注册机去计算序列号即可 2018.4.8更新)
对于那位鄙视我上传X64注册机失误的仁兄,多谢。昨晚整理帖子的排版较晚,望谅解。
1.9号更新,对于ID是Caitingting的朋友非常抱歉,因为我的失误,让你尝试多次未注册成功,现已修复bug。任何人在注册中产生问题,都可回帖,我会尽量帮助你们解决问题的。
解压密码是:www.52pojie.cn |