今天拿 Thunder.app 来练手,目标是日了会员加速的功能 ~
找到 /Application 里的 Thunder.app 右键点击,选择 Show Package Contents,会发现进入了一个文件夹,这个是 OS X 可执行文件,目录结构如下所示:
Contents/MacOS 里的二进制文件 Thunder 则是 Thunder.app 真正的可执行文件,Mac 上可以使用 IDA 和 Hopper Disassembler 来分析可执行文件,我这里使用的是 Hopper,把 Thunder 拖进 Hopper。
左边点击函数进入可以看到对应的 x86 汇编代码,这里拿 isVip 来举例,点击进入函数 isVip 后如下图所示:
可以看到 isVip,具体的代码就是选中的几行。操作比较简单,就是获取并判断 UserController._loginSession 是否是 Vip,所以如果想让程序判断当前用户是 Vip 的话只需要修改这个函数永远返回 True 就行了。Hopper 提供了一种比较简答的修改汇编代码的方式 Alt + a。
这里只需要修改两行汇编代码,第一行改为 Mov eax, 0x1 第二行对应修改为 ret 即可,Hopper 比较方便可以直接输入汇编指令然后它会帮我们转化成对应的十六进制机器码,即: b8 01 00 00 00 c3。现在 isVip 函数的内容其实已经被替换掉了,变成一个只会返回 0x1(True) 的函数,可以通过 alt + Enter 查看。同样的 Patch 操作送给上面列出的了另外一些函数。
Patch 了所有上面提到的函数之后应该已经 Bypass 了所有的本地判断,现在客户端会认为我们是一个 Vip 白金用户了(吧?),结果迎接我的是 Thunder 直接闪退。。。一般情况需要检查一下是否修改汇编时出错,不过这里比较简单不大可能出错,所以应该是有检测 Thunder 可执行文件是否被篡改,从头开始看一下 _main 函数。
看到了么,这里有一个计算 “Contents/MacOS/Thunder” 可执行文件 MD5 的操作,然后检测 Content/BrowerserPlugins 文件夹里是否有这个 MD5 值为名字的文件夹,如果不存在的话就闪退,闪退前还会将 standardUserDefaults 里的 ForceQuit 值为 0x1。因此,只要存在一次检测失败的情况,以后每次 Thunder 都会闪退。
这个时候有几种情况 Bypass 这个检测:
1. 每次修改 Thunder 可执行文件之后自己计算 MD5,在对应位置生成目录。
2. 跳过这个检测,直接进入 NSApplicationMain。
综合考虑了一下,第二种检测比较方便,在 _main 函数里直接跳到 call imp___stubs__NSApplicationMain 这里就好。看了一下该汇编指令的对应偏移位置。
所以在 _main 初始化完成后直接 jmp 0x10000ba57 就好。那么现在,Patch 了所有上面提到的函数 + MD5 检测后,应该已经 Bypass 了所有的本地判断,现在客户端会认为我们是一个 Vip 白金用户了(吧?)
试了一下,然而还是不行。。。这说明之前 Patch 可能有所疏忽的地方 ~ 根据前人的提醒,发现了还需要 Patch 另外一个函数 [LocalTask isValidLixianTask],同样的操作,使这个函数永远返回 True。完成之后,已经可以免费使用 Thunder 的离线下载了。
不过此时其实只进行了一半,我还有更懒的想法:既不想登陆 Thunder,但却又享受它的加速下载功能。为什么会出现这个想法呢?因为之前出现了一个 isLogined 函数,还是跟之前一样的修改,isLogined 现在也变成了一个只会返回 0x1 的函数。效果图如下,可以看到不登陆 + 加速 done。
那么问题又来了,因为使用的是老版本的 Thunder.app 所以每次登陆都会提醒我要更新了,不仅在软件里会提示升级,而且还在推送里面提示,就很烦。
怎么办呢?同样掏出 Hopper 搜索 checkUpdate 函数,和上面类似的 Patch,全部直接 ret 不让他们执行就好了。现在,终于,得到了一个不烦人 + 免登录 + 高速通道的 Thunder.app 了。
* 这里用的是第二种方法绕过 MD5 检测,第一种方法的参考可以看这里,也同样很有意思。
** 2017 年更新后的 Thunder.app 3.x 版本已经不能利用上述 Patch 了,不过只需要下载功能的话 2.x 和 3.x 又有什么区别呢?