小白:小程,你知道有些iOS程序是没人性的吗?老是不按我的意愿来运行!
小程:我怎么知道你的意愿就是有人性的?

本文解决一个问题:修改别人的二进制程序并运行起来。

让别人的程序按你的意愿来运行,文明一点的做法就是拿到源码后加上自己的修改再生成新的程序并安装。

小白:哇,这句话好长,你能一口气说完吗?

但是,很多情况下我们是没有源码的,那怎么办呢?

一个办法是把执行程序的指令或者数据改掉;另一个办法是让程序执行到自已的代码上,再把流程或内存值给改掉。最终,让程序按自己的想法来运作。

小白:还能让程序执行到自己的代码?这不就是乾坤大挪移吗?
小程:这叫注入!
小白:那赶紧讲注入吧。
小程:不!我先讲硬改。

如何改掉程序的指令呢?

程序的源码你很可能拿不到,但是可执行文件却随手可得,如果能直接修改执行文件来解决问题,那就进到了破解的领空。这里从iOS上的程序入手,举一个例子来说明。

这是一个会“过期”的程序,显示主页面的代码是这样的:

-(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包就是修改目标。

ipa是一个压缩包,里面包括了执行程序、配置文件、图片等资源。

如果是从itunes下载的app,则可以这样拿到ipa包:

appstore上的APP可以直接安装到手机,但对于那些从appstore下载的ipa,要做重签名后,才能通过第三方工具安装到越狱手机。

小白:小程,什么是重签名?
小程:简单来说,签名就是允许这个app以什么方式安装。上传到aapstore的app都是以发布证书来签名,允许通过itunes或appstore来安装,但不允许用第三方的工具比pp助手、itools之类的工具来安装。而这里的重签名,指的是用开发证书来签名,允许通过第三方工具来安装。
小白:咦?我为什么要通过第三方工具来安装?用appstore不是好好的吗?
小程:但是,如果想修改代码再运行,就只能通过第三方工具,难道你修改代码后还上传给aapstore吗?
小白:也对。那就是说,只有通过appstore下载的ipa才需要重签名了?如果原本就是第三方工具安装的ipa就不需要重签名了?
小程:是的。而且,很多第三方工具都提供自已的app库,这些app都是重签名了的。
小白:那重签名后,再次修改过的app,要不要重签名?
小程:实践证明,这时不需要再签名。


为了清除“修改了程序却不能安装”的障碍,这里介绍一下重签名的操作。

(一)重签名的准备

(1)mobileprovision文件

重签名需要用到描述文件即provision文件,并保证keychain里面有对应的证书。

可以创建证书与provision,再安装到keychain。或者让别人发一个p12文件与对应的provision,再双击安装。

(2)plist文件

重签名时要使用一个entitlements.plist 文件,可以直接找一个这样的文件来修改,保证get-task-allow字段为true即可。

也可以plistbuddy工具来生成一个plist:

/usr/libexec/PlistBuddy -x -c "print :Entitlements " /dev/stdin <<< $(security cms -D -i xxx.app/embedded.mobileprovision) > entitlements.plist   

/usr/libexec/PlistBuddy -c 'Set :get-task-allow true' entitlements.plist  

xxx.app换成目标app,并且要cd到目标ipa的Payload目录再进行操作

(二)重签名

使用codesigh进行签名:

cp "xxx.mobileprovision" "Payload/xxx.app/embedded.mobileprovision"
--使用mobileprovision文件,覆盖app原有的(没有也照样拷贝过去)

/usr/bin/codesign -f -s "iPhone Developer: xxx (yyy)" --entitlements "Payload/entitlements.plist" "Payload/xxx.app"
--注意entitlements.plist要准备好

在codesign指定证书时,证书的名字(带括号、空格之类的),最好到keychain里面找到这个证书,然后右键在“简介”里面拷贝过去,避免“找不到”的提示。

把Payload压缩成ipa,注意不是Payload的上一级目录!


这个ipa安装到越狱手机后,跑起来是这样的:

小白:这么可恶!这个框太不友好了!

要去掉这个框,先要分析一下代码。

把ipa包解压,再进到xx.app内,找到执行文件,分析这个文件,这里用hopper来分析。

小白:hopper是什么东东?
小程:是分析二进制代码的倚天剑!
小白:有屠龙刀吗?
小程:有,ida是也!
小白:好可怕,亮剑吧!

启动hopper,小程的版本是这样的:

可以看到,弹框的代码是:

想要去掉弹框,可以选择不同的办法,比如把调用alertview的代码改成nop,比如把比较的值改掉不让它进过期的分支,比如把跳转指令“取反”地改一下......

小白:nop是什么?
小白:nooperation,空指令,什么都不做的,但占指令执行时间。
小白:我也想nop!

这里演示把跳转指令改掉的办法。

先确定跳转的地方:

cbz,表示为0就跳转,而且是跳转到非过期的分支。也就是说,现在不是0,没有跳转。所以,修改的办法就是改为“不为0就跳转”。

把光标放在cbz命令行上,再切换至十六进制的表示页面:

可以看到cbz对应的十六进制是这样的(两个字节):

cbz即是:62 06 00 34

而cbnz(不是0就跳转)是:62 06 00 35

所以,修改为cbnz,就是这样:

保存为另一个执行文件:

把修改后的执行文件覆盖掉原文件,再把Payload目录打包,重命名为.ipa文件,再用第三方工具安装到手机(不需要重签名)。

最终,过期的提示消失了,看到了另一个提示:

小白:Oh Yeah!

总结一下,关键流程是,用hopper定位到目标代码的位置,并通过hopper修改保存。同时,应该注意ipa的重签名等常规的知识。“硬改”的办法,对汇编技能的要求较高,相对而言,如果只是想在iOS平台控制目标程序的运作,hook会是一个更有想象力的选择。


iOS逆向开发(0):修改二进制代码与重签名 | hopper | codesigh的更多相关文章

  1. iOS逆向(五)-ipa包重签名

    为什么要重签名? 1.在没有源代码的情况下,你已经对某个应用进行了资源修改(比如修改了启动图或图标等).修改完成以后,如果想要让APP可以正常使用,该APP一定要重新签名然后压缩成IPA文件. 2.如 ...

  2. iOS逆向开发(5):微信强制升级的突破 | 多开 | 微信5.0

    接下来的几篇文章,小程以微信为例,实战地演示一下:如何注入iOS的APP.其中使用到的知识,基本在前面的文章中都有介绍到. 小白:小程,我想用回旧版本的微信! 小程:为什么要用旧版本微信呢? 小白:你 ...

  3. iOS逆向开发(3):锁定APP的目标类与函数 | reveal | lldb | debugserver | 远程调试

    之前介绍了怎么获取APP的所有类的结构信息,这个有什么用呢?用处大了,比如以这一步为基础,下一步通过注入来做更多研究工作. 注入的最小单位是函数,实际上,编译执行的程序在编译后,类就不复存在了,留下来 ...

  4. iOS逆向开发(1):基础工具 | ssh | scp | socat

    小白:小程,我一直想问,什么是逆向来着?是逆向行驶吗? 小程:理解为逆向行驶也没错.一般的项目是从无到有,而逆向是从已有的状态入手,分析出已有的流程与结构的手段. iOS上的逆向开发,是一件有趣的事情 ...

  5. iOS逆向开发(8):微信自动添加好友

    这一次,小程演示怎么让一个APP自动地运行,从而代替手工的操作.同样以"微信"以例,实现在一个微信群里面,对所有的成员,自动地一个一个地发出添加好友的请求. 知识点还是之前介绍的东 ...

  6. iOS逆向开发(4):注入目标函数 | fishhook | MobileSubstrate | MSHookFunction | iOSOpenDev

    从获得APP的所有类声明,到锁定目标类与函数,现在是时候注入函数了. 所谓"注入函数",小程的意思是让APP执行到小程写的代码中,跟"钩子"的概念一致.小程把个 ...

  7. iOS逆向开发(2):获取APP的类声明 | class-dump | dumpdecrypted

    之前介绍了怎么操作越狱的iOS设备(以下简称为手机),但简单操作手机并不是目标,小程的目标是手机上特定的APP,比如微信.淘宝.QQ音乐等等,因为小程可以从这些APP上拿到一些有用的信息或资源--比如 ...

  8. iOS逆向开发(7):微信伪装他人

    上一节小程介绍了微信在进入"附近的人"时修改位置信息的办法,这一次,小程来修改"自己"的信息,伪装成别人. 但是,这里的伪装只是"本地的伪装" ...

  9. iOS逆向开发(6):微信伪造位置

    仍然以微信为例,实战地练习一下使用Reveal.iOSOpenDev等工具注入APP的流程,积累经验.这一系列的文章都是学习过程的总结,不带任何商业目的. 本文解决一个问题:如何伪造一个经纬度,在微信 ...

随机推荐

  1. 爸爸在家庭中最应该扮演的角色,是爸爸本爸!zz

    不然呢?还是爸爸应该cosplay什么物种?细想下,爸爸这个角色很多人是不称职的,经常加班或完全不管孩子的隐形人.肆意把脾气撒在孩子身上的炸弹君.动不动就不耐烦的刺猬......孩子经常挂在嘴边的不是 ...

  2. abaqus重新划分网格

    首先建立了几何体: 装配并划分网格: 下面对单元操作: 删除单元: 单元中删除某条边: 单元 拆分边: 单元 交换对角线: 单元 拆分四边形到三角形: 单元 交换对角线: 单元 合并: 网格 网格 去 ...

  3. Ubuntu之sudo权限管理/etc/sudoers文件

    网易云音乐翻车记 系统安装的Ubuntu18.04桌面版,安装网易云客户端后,还没来得及夸奖,发现点击图标打不开后网上找到教程:Ubuntu网易云音乐无法打开 感觉挺靠谱的,照着最下边的教材修改了一波 ...

  4. 初学者必看的文章:在VM12中安装 RedHat RHEL7.2  系统的详细步骤:看我如何操纵RHEL系统

    一.开始安装 1)新建虚拟机 RHEL7.2 2)成功引导系统--开机出现此画面 Install Red Hat EnterpriseLinux 7.2  安装RHLE7.2 操作系统 Test th ...

  5. APIView源码简单分析图

    APIView源码简单分析 !声明:下面这个dispatch分发方法不在是父类View里的dispatch了,APIView重新封装了这个dispatch.(整个核心就是initialize_requ ...

  6. Servlet的创建二以及生命周期

    之前说Servlet可以通过实现Servlet接口来创建,但是我们看到了,需要重写该接口中的所有方法. 创建方式二:Servlet的创建还可以继承抽象类GenericServlet并重写其中的抽象方法 ...

  7. Exception.ToString()使用及其他方法比较

    在日常C#的编码过程中,我们常常会使用try...catch...来抓住代码异常,并且在异常的时候打印log, 如下 try { } catch (Exception e) { //输出Log信息等 ...

  8. 从git远程仓库Checkout项目到本地

    一.登录coding  并且项目已创建好  已经是项目的组员 二.打开idea 1.弹出如下页面  复制远程项目上的SSH(URL)到下框URL 并且Test测试 成功就Clone即可 2.Clone ...

  9. kubernets基础

    1.定义和功能. 1.1定义:kubernets解释为舵手或者飞行员,以Borg为主衍生出. 1.2功能:自动装箱,自我修复,水平扩展,服务发现和负载均衡,自动发布和回滚. 密钥和配置管理,存储编排, ...

  10. FPGA中带优先级的if else if与不带优先级的case的探讨

    我们知道在书本上都说让我们尽量使用不带优先级的的数据选择器,今天我们就来探讨一下二者的区别. 例子1:带优先级的的数据选择器,综合成功,且没有任何警告. module detection_prio # ...