Hopper Disassembler是个非常好用的逆向工具,在其官网上还提供了Demo版,不过有半小时的限制。这次我们要逆向的对象就是Hopper Disassembler v2.8.1,目的有三:
- 取消半小时时间限制
- 导出程序
- 在Hopper内使用GDB
- 仅供逆向研究,不放出任何已破解的程序,Hopper绝对是物超所值的。
- Shut up and take my money!
这个版本的Hopper还没有做太多防范,我们甚至可以直接class-dump出它的头文件。
$ class-dump -H -o Hopper /Applications/Hopper Disassembler.app/Contents/MacOS/Hopper Disassembler
话不多说,先以register做为关键字搜索吧。
根据文件名,至少能看出HopperAppDelegate应该是比较关键的。打开一看,这一串函数立刻就暴露了:
- (BOOL)checkSavedRegistration;
- (id)registrationOrderID;
- (id)registrationName;
- (id)registrationData;
- (id)registrationOrderID:(id)arg1;
- (id)registrationName:(id)arg1;
- (BOOL)checkRegistrationLicense:(id)arg1;
那么这些利用Objective-C的runtime就能搞定。
搞定后启动Hopper,没有了原来的"Try the demo",可是半小时后还是会弹出试用结束的Alert。这一次我们以expire为关键字搜索。
看来是HopperDocument呢。果然:
- (id)expired:(id)arg1;
那么这个继续用runtime搞定。再次打开Hopper,半小时后,没有了试用到期的alert了。不过,这还不完美,因为我们还不能保存修改后的可执行文件,也不能在Hopper内使用GDB。
可是我们明明已经把能Hook的都给Hook了啊,还能想到的,那就是在执行「保存」和「GDB」时,还有别的函数在检查,而且很有可能不是Objective-C写的。
这一次就让我们用Hopper来反编译Hopper吧!以子之矛,攻子之盾!
在Hopper的搜索框里输入gdb,可以看到很多相关的函数
不过这其中有一个和刚才的expired处于同一个类中,也就是toggleGDBWindow. 从字面上来看,切换GDB窗口,应该就是我们想要找的了。
跳到这个方法的汇编中,可以看见它调用了一个C函数,getApplicationStatus。
这个C函数返回的值保存在eax中,随后的
test eax, eax
je 0x10001ed4d
即 if (eax == 0) { goto loc_0x10001ed4d;}
函数返回0则跳转到0x10001ed4d处,那么0x1000ed4d是什么呢?
已经很明显了呢,那么我们的目标就是这个getApplicationStatus函数了。
可是Hook C函数,在iOS上我们有CydiaSubstrate的MSFindSymbol帮我们,可是Mac上呢?对于私有C函数,我们似乎是无能为力。
不管怎么说,先看看这个C函数的汇编码吧。
很简单的调用,就是返回了currentStatus的值。再看一下这个函数的Cross References呢。
很多地方都用到了啊,那么我们只要小小的修改一下函数返回值不就全搞定了吗?
不过不能用runtime搞定的话,我们就来简单粗暴的方法吧!直接修改机器码!
如果我们能把
mov eax, dword [ds:___currentStatus_1004bec90]
改为我们想要的
mov eax, 0x1
就大功告成了。
在这一句汇编的左边,我们可以看见它的机器码:8B051AC74B00
于是借助Hex编辑器,搜索8B051AC74B00
仅仅拿到这些还不够,我们还需要知道mov eax, 0x1的机器码,这又得靠Hopper了,虽然不能直接保存。
于是我们就得到了机器码B801000000,不过这比原来的差一个字节,没关系,用nop补上吧~(nop的机器码和刚才一样的方法得到)
于是我们把8B051AC74B00替换为B80100000090
保存之后再打开Hopper,点击GDB
再试试保存功能、
嗯,没问题了呢!
你好 最近看了这个网站的一个教程 http://adr.horse/?p=753 可是程式的版本变了 用hopper分析出的代码有些不一样 最后不知道要怎么修改 还有最后一步的应用程序签名 不知道要怎么完成 博主能帮帮我么 谢谢啦
其实博主操作还是有些麻烦了。
今天看到了博主的文章(一直关注你呦~),于是来自己动手操作一下,毕竟自己用的是老版2.7.12版的破解版。
之前objc动态操作的话,是不是性能会有点点欠缺。。手动改汇编码,不是更酸爽吗。。
前提是找到破解版的ida,hopper啥的
以下方法我都没实践过不会告诉你用旧版Hopper破解以后直接覆盖新版就免注册了
按博主思路分析,第一步class dump出一大堆
垃圾头文件,搜索到了有关registration的方法。基于博主找出的几个方法,可以猜测除了返回值为BOOL的方法,其余都是提供许可信息的方法,并无太大价值。(一看id就想到NSString,我这是怎么了= =)那就从checkSavedRegistration入手吧。
通过Hopper分析发现,这个方法中有一个跳转,在0x100005396这个位置。
如果test rax,rax失败了 那么就不跳转,继续往下执行,而之后的代码段里引向了checkRegistrationLicense这个方法 两个红包一手抓。那就要走另一条路了,就是0x1000053ad,这个分支就是简单无脑的一条指令 xor al,al 把al复位了。
所以就直接把je改成jmp好了。
接着是-(id)expired:(id)arg1的修改
直接用流程图理解,它是通过调用getApplicationStatus来验证许可是否有效的
hopper你直接把第三条拽出来了,说好的第二条呢?!
强迫症善后,继续je改成jmp。
最后getApplicationStatus的修改照博主做就行了。。
如果有错误的地方还请博主
么么哒指出= =啊啦,最近没怎么上博客~
正如你所说的,第一步的确是class dump出了一大堆垃圾头文件(我顺便hook了其中几个,改成了自己的信息,其实就是为了调戏一下Hopper)。
一开始想用objc动态操作,其实就是图个方便,不太想直接上汇编码。性能上,和全靠改汇编码比起来,可能会慢一小点,但是基本也察觉不到就是啦:)
博主看了Hopper v3没有? 貌似免疫了class-dump
万恶的Hopper v3,下载下来研究一下
看过了 基本上所有函数的签名 甚至字符串 都加密了 懒得研究了
v3的加密丧心病狂,所以才选了v2来玩。
当然要是真的有人想去破解v3的话,肯定也能做出来,只是太耗费时间和精力了。从技术上来说,破解v3应该会很(jing)有(jin)意(ren)思(wang);从其他方面来讲,Hopper已经很便宜了,直接买买买吧!
虽然我也是这么想的 不过买完之后就没钱买minecraft了= =
我的购物车里还有一堆CD。。
于是生活变得更有意义了= =
博主为何在最后卖萌。。
嘛,毕竟涉及到破解软件,虽然没有给出修改后的文件,但是还是得明确一下购买正版的思想,我又不想说的太正经,只好卖个萌顺便还能缓和一下气氛 :P
niconiconi~~