首页
社区
课程
招聘
[原创]IncrediBuild 4.5 注册算法分析
发表于: 2012-10-11 02:51 46894

[原创]IncrediBuild 4.5 注册算法分析

2012-10-11 02:51
46894
国庆时候折腾了一下IncrediBuild, 本打算把RSA跑出来做注册机的, 结果被yafu的bug坑了, 那就只好把替换公钥的版本先放出来了.
按照惯例, 先把目前折腾完的东西说一说, 安装包已经补丁过, 换了公钥了. 然后送个测试的2012PacketLite.ib_lic文件, 双击自动导入. 当然喽, 要用配套的安装程序安装, 不然RSA解密过程就会报错.
IncredibuildSetup.bt和IncredibuildLicense.bt分别是setup.pak和2012PacketLite.ib_raw的解析模版, 可以在010Editor中使用.

先说下ib_lic的结构. 头部16个字节是文件的描述信息, 余下的是注册封包的RSA密文.
struct LicenseFileHeader
{
  DWORD licensefileversion;
  DWORD licensefilelength;
  unsigned __int64 contentchecksum;
};

其中+0是授权文件版本, 目前需要设置为1. +4是授权文件大小, 是整个大小, 不是内容部分大小. 从+8开始是RSA密文的checksum, 算法是标准的sum, RSA加密部分的每个字节累加.
下面如果没有特意说明, 这些数据在文件中都是默认的LittleEndian, 低位在前的.
当然如果有官方的ib_lic文件, 解一把出来, 封包格式自然就知道了, 可惜我找那些大公司有授权文件的人, 都不肯给我做参考, 动态跟的话, 只能是随便填点字串, 哪儿崩了看看callstack, 再去找到读取的地方, 猜测子封包格式, 自然这个是不可行的, 效率太低. 这大概是06还是07年分析到的阶段, 就停留在搞清楚明文包开始的32字节意义, 其实严格说是只分析出来20个字节.

今年国庆时候, 偶然间听人说见过授权文件, 当然最后还是没搞到, 不过我已经下决心要把他静态分析出来了, 顺便熟悉下IDA的使用.
首先第一步做的当然是下载个最新版的IncrediBuild, 往虚拟机里面装一把了, 然后照例看了下ib_lic文件, 关联到了XLicProc.exe, 参数是/LicenseFile=””当年分析的是2.x还是3.0的都没记录下来, 笔记里面只有官方的公钥值, 于是就抱着百闻不如一见的心思, 打开XLicProc.exe搜了一把, 好好的还在! 然后IDA里面打开String窗口, 查找LicenseFile, 找到了加载的地方. 判断文件头和解密, 当年还有点印象, 直接顺着找下去, 然后就是解密后的封包分析… 就进到了VMT的调用里面. 正好前几天下了个IDR, 拿XLicProc.exe试了一把, 在一片摸黑的前两天, 给了很多有益的信息.
首先IDR能够通过层层调用的关系, 猜测一个方法的参数的类型名称, 而不去管这个类型他认不认识. 其次会根据初始表, 猜测类成员的类型.
一开始根据以前弹出错误对话框时候的记录 (当前版本改为了抛出异常), 确定可疑的类叫做TLicensePacket, 继而查看成员列表和继承关系, IDR中这里设计的有问题, 想查看成员列表, 需要切换到Branch, 然后手动输入完整的类名,  在完整的Tree方式只有VMT没有Field的. 根据IDR从TLicensePacket的成员初始化表猜测出的类型, 将其改名为str4, float8, boolc,double10这类临时名称, 这其中, 有两个byte分别在+18和+28处, IDR并没有猜出他的类型. 稍后在浏览TLicensePacket的每个VMT入口的时候, 发现有一个函数里, 使用了FillChar(&byte,  10, 0)来填充这两个地址, 那么这就不是byte, 可能是guid这类的东西. 其他每个成员都在这里得到了初始化, 遂把这个命名为mayInitLicensePacket
在接着浏览VMT的函数时候, 发现了一个很有意思的函数, 根据传入的整数值, 从一个字符串数组取出名称返回.



转去IDA Pro, 查看对应的地址如下


数一数前面IDR里面字段的数量, 也是21, 相当可疑啊.怀着大胆推测, 小心求证的原则构造了个完全不对的2007Packet.ib_raw文件, 好吧其实就是当时用的文件, 这些字串是为了方便OD里面看读到了哪里. 然后使用注册助手, 使用替换过的密钥, 加密为2012Packet.ib_lic文件, 运行… 消失了.

好吧, 打开尘封已久的OD, 载入IDR输出的map文件, 然后加上参数, 运行, 通过callstack, 定位到这里

这里挺明显的是调用VMT+24的地方, 倒回到IDR中, 粗略查看了下, 是从流里面逐个读数据.
在IDA Pro里面尝试反编译后, 确定21个字段就是跟名字一一对应的, 大概类型也跟IDR猜测的一致. 这里卖个关子, 其实IDR还是猜错了重要的东西.

其实这里还可以看出Hexrays插件的另外一个bug, 注释的颜色是设置中数值常量的颜色, 1.1版本是没有这个问题的.
而且在修改函数参数类型的过程中, 经常改好参数一点击确定, 当前窗口就自动刷新到几个固定的函数, 这bug其实最费时间了.
这段函数中, 正好第一个字段是读取字串, 然后摸清楚了这个字串的长度字段读取方式, 还是有点意思的. 他是先读一个字节, 判断是奇数就读满四个字节, 判断偶数就用当前字节, 然后除以2, 读取对应长度的字符串.
从Delphi中也有256长度的短字串和4G的长字串, 初步推测他是用了末尾的1bit, 充当7bit和31bit的长度开关. 也就是小于127的字符串长度字段用1个字节. 大于的用4个.
遂根据这些类型, 在010Editor里面构造了解析模版, 并且填入了看起来正确的数据. 两个PacakageList和BlockedAppList不知道做什么用的, 就直接填了00000000.
前面提到那几个类型是Double的Date, 就是VCL的TDateTime类型, 存储的数值在010Editor模版中有完全对应的OLETIME, 其实010Editor原本就是VCL的程序, 有这个并不奇怪.
至于两个GUID, 就保持以前填的ASCII, 想着等他报错再看.
运行, 还是消失了~~ 因为IDA里面名字改得差不多了, 于是这次换IDA来调试, 在IDA里面打上OD同样断点, 逐步跟踪, 发现读取到CustomCheckFailures后, 原本的字串长度被吞了, 直接把字串的第一个字当作长度读出来了.
再看看读取这个Byte的地方, 有点费解,

可以看出 我写的数据1被当作长度读出来了, 而属于字符串的位置被读到了CustomCheckFailures这个”Byte”里面. 这个不解之谜直到几天后彻底分析到TBlockedApp才揭开, 当时的我没多想, 就多加了一个byte.
运行以后, 哦哟, 没有异常, 而且继续调用了CoordMonitor.exe, 把LicenseFile=””参数传进去, 这个倒是类似3.0版的做法了, 那时候直接是CoordMonitor.exe来检查这些字段.
当然我是在没有安装Incredibuild的机器上跑得, 而且目录下也没有CoordMonitor, 也就没跑起来.
好吧启动虚拟机, 跑了一下, 小激动, 注册通过了也!

等等… 有什么奇怪的地方, 允许的客户端数量怎么那么大, 我记得填得是200啊, 打开010Editor一看, 哦哟, float的200强制Int显示就这个值.
这也是发现的IDR猜测成员过程一个必犯错误, 就是猜出的Single(float)多半是int, 而猜出的Double后面也会跟一个DWORD.

这个画面出来以后 我第一件事不是想的去改正那2个GUID和反思Workgroup是不是网络邻居的workgroup, 而是马上拽出yafu, 打算趁热分解出来.
因为国庆前看过看雪有个文章, 说他跑了一个月, 跑出来了, 再看下面是用的3G的奔四, 我心想老子是至强, 怎么也比他快吧, 然后就跑了一天, 又跑了一天, 我坐不住了, 因为我运行yafu时候加了-threads 8参数, 他却迟迟只跑满1个核心, 终于我开始分析安装包格式, 看了下overlay, 是个证书, 再看看资源, 有奇怪的三个RCDATA其中一个还是mz文件头, 还有个超大的数据.  当然用UniversalExtractor是解不开的, 那并不重要,  祭出IDR和IDA组合, 再次确定启动后, 原来是把资源里面这三个, 最小的那个做为是否压缩的标志位和长度字段, MZ文件头的做为lzma.exe, 超大的数据保存为setup.lzma, 运行lzma.exe –d setup.lzma setup.pak, 然后从setup.pak末尾取出刚才提到的长度字段的数据保存为setup.exe. 当然这些都是在临时目录完成的, 我省去没提. 没有压缩的情况就不调用lzma直接存成setup.pak, 这个也没提, 可以打开IDB, exe面前没有秘密.
对着这个setup.pak搜索官方密钥, 搜到很多, 看来不需要二次解压了, 直接替换后再压回去, 用这个冒牌安装包安装过的agent就不用每台机器补丁了.
Agent安装好以后, 会自动从连接到的Coordinator服务器拿到授权.


在等待yafu展开多项式的时候, 因为听说4核展开只要10个小时我8核跑了三天了, 单核也该完了吧, 怀着激动的心情开始要把SetupPacket和刚才略过的TPackagePacketList/TBlcokedApplicationList分析完, 遂再次打开IDR和IDA, 这次把CoordMonitor也拽进去了, 这下真是牵了葫芦带起瓢, 我都懒得描述枯燥的重命名, 修改参数, Hexrays跳到奇怪位置, 再返回 重新F5…这样的过程了, 好在搞清楚了那个明明一个byte却要有长度计数的原因了, 原来这个是专门用来读取标志位用的, 并不是bool, 而是800/1000800/400/400000这种的组合, 当然也可能是1/2/F/80这类的, 前面就是指定他的长度了. 估计是实现应用里面扩充了标志位, packet低位的标志位还有效的设计.List写了0000000也不是当作nil用, 而是根据这个数量再次读取对应个数的Packet.
Packet开头的32个字节也搞明白了28个, 其中那个GUID当然也不是检测固定的值, 而是每个类型的Packet在程序中都有自己的guid, 通过VMT返回这个guid来判断是否想要读取的packet跟读到的是否一致的.
至于那个做好事的返回字段名的功能, 是因为程序中实现了字段类型转换, 一些不能转换为int/double/string的字段通过这个获取名字来拼接异常消息.
从分析来看, 试用期间, 其实还是有额外的限制的, 例如一些命令行工具被限制使用或者工作在单机模式不能调用其他agent, 而在读入lb_lic文件中, 如果提供空白的黑名单, 这个名单会被清空.
对应黑名单还有一个白名单就是刚才提到的PackagePacketList, 应该是该授权文件允许的features列表.
这里说明一下加密时候的算法, 其实也就是LbRSA的文件加密padding方式, 首先明文数据会被识别为反转的大数, 其次, 没有节省位数(没有按照bit选择刚好比n小的分段), 而是直接使用53byte的地方开始padding, 最后一包从结束开始的字节padding. 第一个padding字节是00, 是为了将明文和padding分开, 这干扰意义就不强了, 余下到最后二个字节之前都是01~FF的随机数, 不会出现00. 倒数第二个字节是02, 是识别padding版本的. LbRSA有01和02两种padding, 使用01时候刚才填的随机数就是固定的00. 读取的库可以兼容这两种, 也可以拒绝01方式的padding. 最后一个字节固定为00.
运算完的大数同样是按照LittleEndian的方式存到流中的, 也就是低位在前. 做注册机的话要注意这几个非标准的做法.

附件里面包含了分析过的idb, 测试版的注册机, 不过idb和安装包貌似论坛传不下, 回头传到rs去.

当然注册机补丁安装文件功能没做, 这几天在分析itunes没空, 注册界面也只做了几项显示时候用的输入. 说是测试版注册机, 是因为带了一个加密010Editor里面写出的授权文件功能, 可以用这个作出各种授权文件来测试.

分析过程中, 也感觉到了Delphi分析的优势和劣势. 优势刚才描述的里面也说了, 很多RTTI的信息保留下来, 开发人员并没有去去除, 而且以前维护KOL补丁也挺久, 对Delphi还是比VC熟悉的.
劣势吗, 第一个就是IDA里面编译器选择为Delphi以后, 他还是Microsoft的fastcall, 第二个嘛, 虽然可以用usercall来模拟borland的fastcall, 但是… 很多时候IDA生成的usercall少了eax参数, 多了ebx和esi, 或者多了返回值参数, 或者usercall识别为userpurge, 导致堆栈配不平.
其中问题最多的是Exception::CreateFmt, 这个要在IDA里面配好, purge字节是8, 最后一个参数是数组, 而且紧接着的RaiseException, 函数开头是一堆push, IDA会在这里错认为是属于函数的入栈, 这里要把purge改为0, 因为调用前后堆栈是平衡的, 要注意的是包括可变参数的LStrCatN, 是通过传递了参数个数, 在返回前调整堆栈的, 这里也容易配不平, 而且这种多参数的函数, 虽然可以贴心 的按+-来调整实际调用时候Hexrays插件识别的参数数量, 如果你不小心减成最少的数量, 再按+是加不回来的, 有个办法就是, 给他多改个参数, 然后改回去, 这个参数就空出来了…
让我想想看...还有个问题, 分析过程中用到了VMT, 也就是定义这些Packet的父类TPacket的VMT为一个各种函数指针的struct然后在TLicensePacket的+0处定义为struct TPacketVMT* vmt的办法, 不过这个办法也是有缺陷, 虽然你在LocalType里写好了每个func的参数列表, 可是IDA分析到的时候, 还是照样丢ecx认stdcall 强加返回值等等转为另外类型的函数指针, 比如明明replacetext定义为__fastcall(char*a1, char* a2, int a3)IDA却坚持分析称这样
void(*__cdecl)(int arg1)obj->vmt->reaplcetext(arg1);

这时候有个办法就是在vmt成员名字上右键, 选择force call type, IDA就会放弃自己的分析, 变成按照你的定义了.
obj->vmt->reaplcetext(a1, a2, arg1);

这办法同样可以用在C++的类里面.

文字太多来张图说明吧:


可以结合着idb和010Editor的模版看, 就是IncredibuildLicense.bt中的字段定义.

后继更新:
接到报告, 看了下扩展包的管理界面.

这些扩展包一共23种, 其中关于VC的可能以前叫做VC 6.0和2003/2005, 后来统一合并到MSVC/C++里面了, 不过不确定, 所以把和VC相关的列出来了, 顺便放了其他几个比较有意思的扩展包.
Keygen测试程序已经更新.


补丁过的安装包地址, 刚才测试的XP里面agent截图就是这个安装包安装的:
http://www.rayfile.com/zh-cn/files/c9af351c-130c-11e2-8a5f-0015c55db73d/
分析时候用的idb和dbfix
http://www.rayfile.com/zh-cn/files/c691a84f-130d-11e2-b45e-0015c55db73d/

[课程]FART 脱壳王!加量不加价!FART作者讲授!

上传的附件:
收藏
免费 6
支持
分享
最新回复 (67)
雪    币: 93944
活跃值: (200219)
能力值: (RANK:10 )
在线值:
发帖
回帖
粉丝
2
Большое спасибо.
Thanks you.
上传的附件:
2012-10-11 02:55
0
雪    币: 93944
活跃值: (200219)
能力值: (RANK:10 )
在线值:
发帖
回帖
粉丝
3
excellent article.
上传的附件:
2012-10-11 02:58
0
雪    币: 3758
活跃值: (3282)
能力值: ( LV15,RANK:500 )
在线值:
发帖
回帖
粉丝
4
哈哈感谢光临 lin版半夜还在看坛子啊 莫非也和小弟一样失眠了
2012-10-11 03:03
0
雪    币: 93944
活跃值: (200219)
能力值: (RANK:10 )
在线值:
发帖
回帖
粉丝
5
等 kanxue 來  wait...
上传的附件:
2012-10-11 03:12
0
雪    币: 485
活跃值: (78)
能力值: ( LV4,RANK:40 )
在线值:
发帖
回帖
粉丝
6
那张图是用什么软件生成的,挺好看的
2012-10-11 08:40
0
雪    币: 1015
活跃值: (235)
能力值: ( LV12,RANK:440 )
在线值:
发帖
回帖
粉丝
7
坐等精华,前面的大大注意休息啊!
2012-10-11 10:37
0
雪    币: 3519
活跃值: (4047)
能力值: (RANK:215 )
在线值:
发帖
回帖
粉丝
8
很强大,功力深厚。
2012-10-11 10:58
0
雪    币: 73
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
又见半仙~坐顶
2012-10-11 11:24
0
雪    币: 458
活跃值: (306)
能力值: ( LV12,RANK:400 )
在线值:
发帖
回帖
粉丝
10
前来围观。。
2012-10-11 12:08
0
雪    币: 44229
活跃值: (19965)
能力值: (RANK:350 )
在线值:
发帖
回帖
粉丝
11
笔记很专业~
2012-10-15 20:01
0
雪    币: 201
活跃值: (16)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
功力深厚 表示需要加强学习才能懂
2012-10-15 22:26
0
雪    币: 1233
活跃值: (907)
能力值: ( LV12,RANK:750 )
在线值:
发帖
回帖
粉丝
13
这图怎么画的?真漂亮~~~膜拜大牛
IDR没听说过,一并记下来mark,还有yafu是这个吗?
http://sourceforge.net/projects/yafu/
2012-10-15 22:41
0
雪    币: 3758
活跃值: (3282)
能力值: ( LV15,RANK:500 )
在线值:
发帖
回帖
粉丝
14
回楼上的, 图当时找了几个画类图的不好使, 直接用SAI画了. 全称PainttoolSAI
IDR是个开源项目, 综合DeDe和Dcu2Int这些工具的功能的. 可以去官方一个一个下他的特征库, 也可以去资源下载版, 有人放了完整的包.
yafu就是你贴的那个地址, 他的readme里面给了一个弱大数, 估计是开方法能求出来的, 所以测试时候其他两个工具都没yafu快. 你看看评价里面居然投反对的多, 就知道不止我一个白高兴一场
2012-10-15 23:51
0
雪    币: 67
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
果然大仙,我等平民膜拜之
2012-10-16 00:09
0
雪    币: 1919
活跃值: (901)
能力值: ( LV9,RANK:490 )
在线值:
发帖
回帖
粉丝
16
稍不留神就晚了
PS:那个网盘下起动都没动,哎。。。
2012-10-16 00:15
0
雪    币: 235
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
17
谢谢。。。学习。。
2012-10-16 18:50
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
18
拉下来测试了一下,导入license后工作在单机模式。
2012-10-23 12:40
0
雪    币: 270
活跃值: (117)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
19
哈哈,半仙改名大仙吧,感谢分享精华文章
2012-10-23 15:44
0
雪    币: 130
活跃值: (61)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
20
膜拜膜拜,好文章,学习了
2012-10-24 10:09
0
雪    币: 8
活跃值: (21)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
21
下载不了啊
2012-10-29 09:27
0
雪    币: 3758
活跃值: (3282)
能力值: ( LV15,RANK:500 )
在线值:
发帖
回帖
粉丝
22
应该是Agent没有用这个定制安装包安装吧...更换私钥的疼处
2012-11-4 13:56
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
23
是在Coordinator Settings里面的Extension Packages下显示:
Microsoft Visual Studio C/C++ Build System 0 Agents

应该是license受限吧。其他Agent也都用修改包安装的。
2012-11-5 09:19
0
雪    币: 201
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
24
跟楼上同样的情况, 貌似用不了
2012-11-5 15:05
0
雪    币: 244
活跃值: (40)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
25
哎,曾半仙给我最大的感觉就是:从火星来的
智商应该远在人类之上
2012-11-5 15:13
0
游客
登录 | 注册 方可回帖
返回
//