修改二进制程序并运行
叶孤城原创
小白:叶城主,你知道有些iOS程序是没人性的吗?老是不按我的意愿来运行!
叶孤城:我怎么知道你的意愿就是有人性的?
小白:……
本文解决一个问题:修改别人的二进制程序并运行起来。
让别人的程序按你的意愿来运行,文明一点的做法就是拿到源码后加上自己的修改再生成新的程序并安装。
小白:哇,这句话好长,你能一口气说完吗?
叶孤城:闭口,否则让你见识天外飞仙!
陆小凤:叶兄,冷静!
小白:……
很多情况下我们是没有源码的,那怎么办?
一个办法是把程序的指令或者数据改掉;另一个办法是让程序执行到自已的代码上,再把流程或内存值给改掉。
小白:还能让程序执行到自己的代码?这不就是乾坤大挪移吗?
叶孤城:这叫注入!
小白:那赶紧讲注入吧。
叶孤城:不!我先讲硬改。
如何改掉程序的指令?
举一个例子来说明。
(一)一个会过期的程序
这是一个demo,程序显示主页面时是这样的:
-(void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
UIAlertController* alertvc = nil;
int expire = 1;
if (expire) {
alertvc = [UIAlertController alertControllerWithTitle:nil message:@"过期了!" preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* cancel = [UIAlertAction actionWithTitle:@"算了" style:UIAlertActionStyleCancel handler:nil];
[alertvc addAction:cancel];
}
else {
alertvc = [UIAlertController alertControllerWithTitle:nil message:@"欢迎回来" preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* ok = [UIAlertAction actionWithTitle:@"太客气了" style:UIAlertActionStyleDefault handler:nil];
[alertvc addAction:ok];
}
[self presentViewController:alertvc animated:YES completion:nil];
}
为了真实模拟,先把这个demo弄出一个ipa包,再来安装(而不是直接用xcode安装到手机),这个ipa包就是修改目标。
如果是从itunes下载的app,则可以这样拿到ipa包:
这时,要对ipa做重签名才能通过第三方工具安装到越狱手机。
小白:叶城主,什么是重签名?
叶孤城:简单来说,签名就是允许这个app以什么方式安装。上传到aapstore的app都是以发布证书来签名,允许通过itunes或appstore来安装,但不允许用第三方的工具比pp助手、itools之类的工具来安装。而这里的重签名,指的是用开发证书来签名,允许通过第三方工具来安装。
小白:咦?我为什么要通过第三方工具来安装?用appstore不是好好的吗?
叶孤城:但是,如果想修改代码再运行,就只能通过第三方工具,难道你修改代码后还上传给aapstore吗?!
小白:那就是说,只有通过appstore下载的ipa才需要重签名了?如果原本就是第三方工具安装的ipa就不需要重签名了?
叶孤城:是的。而且,很多第三方工具都提供自已的app库,这些app都是重签名了的。找时间我单独讲如何重签名。
小白:那重签名后,又修改过的app要不要重签名?
叶孤城:
这个ipa安装到越狱手机后,跑起来是这样的:
小白:这么可恶!
叶孤城:不顺你的意愿就是可恶?难道什么都要给你免费用才是人性的体现?
小白:快别扯远了,说重点!
要去掉这个框,先要分析一下代码。
把ipa包解压,再进到xx.app内,找到执行文件,分析这个文件,这里用hopper来分析。
小白:hopper是什么东东?
叶孤城:是分析二进制代码的倚天剑!
小白:有屠龙刀吗?
叶孤城:有,ida是也!
小白:好可怕,亮剑吧!
启动hopper,小编的版本是这样的:
可以看到,弹框的代码是:
去掉弹框,办法有得选,比如把调用alertview的代码改成nop,比如把比较的值改掉不让它进过期的分支,比如把跳转指令“取反”地改一下......
小白:nop是什么?
叶孤城:nooperation,空指令,什么都不做的,但占指令执行时间。
小白:我也想什么都nop!
叶孤城:那会给swr的。
小白:啥?
这里演示把跳转指令改掉的办法。
先确定跳转的地方:
cbz,表示为0就跳转,而且是跳转到非过期的分支。也就是说,现在不是0,没有跳转。所以,修改的办法就是改为“不为0就跳转”。
把光标放在cbz命令行上,再切换至十六进制的表示页面:
可以看到cbz对应的十六进制是这样的(两个字节):
cbz即是:62 06 00 34
而cbnz(不是0就跳转)是:62 06 00 35
所以,修改为cbnz,就是这样:
保存为另一个执行文件:
把修改后执行文件覆盖掉原文件,再把Payload目录打包,重命名为.ipa文件,再用第三方工具安装到手机(不需要重签名)。
于是,过期的提示消失了:
小白:Oh Yeah!