iOS冰与火之歌番外篇 - 在非越狱手机上进行App Hook(转载)

作者简介:郑旻(花名蒸米),阿里巴巴移动安全部门资深安全工程师,香港中文大学移动安全(Android & iOS)方向博士,曾在腾讯、百度以及硅谷的FireEye实习。在博士期间发表了多篇移动安全方向的论文(BlackHat、AsiaCCS等),去过10多个不同的国家做论文演讲。 曾帮助Apple公司修复了多处iOS安全问题,并且Apple在官网表示感谢。同时也是蓝莲花战队和Insight-labs的成员,在业余时间多次参加信息安全竞赛(Defcon、AliCTF、GeekPwn等),并取得优异成绩。

感谢作者阿里巴巴移动安全部门资深安全工程师郑旻(花名蒸米)对本文的授权。

原文地址:http://geek.csdn.net/news/detail/56195

0x00 序

冰指的是用户态,火指的是内核态。如何突破像冰箱一样的用户态沙盒最终到达并控制如火焰一般燃烧的内核就是《iOS冰与火之歌》这一系列文章将要讲述的内容。但在讲主线剧情前,我们今天先聊一聊分支剧情 - 在非越狱的iOS上进行App Hook。利用这个技术,你可以在非越狱的iOS系统上实现各种hook功能(e.g., 微信自动抢红包,自动聊天机器人,游戏外挂等),但写这篇文章的目的并不是鼓励大家使用外挂,更不是鼓励大家去卖外挂,所以千万不要用这个技术去做一些违法的事情。

《iOS冰与火之歌》系列的目录如下:

  1. Objective-C Pwn and iOS arm64 ROP
  2. 在非越狱的iOS上进行App Hook(番外篇)
  3. █████████████
  4. █████████████
  5. █████████████

另外文中涉及代码可在我的Github下载,地址: 
https://github.com/zhengmin1989/iOS_ICE_AND_FIRE

0x01 Mach-O LC_LOAD_DYLIB Hook

要是看过我写的安卓动态调试七种武器之离别钩 – Hooking(上)http://drops.wooyun.org/tips/9300 和 安卓动态调试七种武器之离别钩 – Hooking(下)http://drops.wooyun.org/papers/10156 的同学应该知道在android进行hook的方法可以是五花八本的。其实在iOS上进行hook的方式也有很多,但是大多数都需要越狱后才能实现(比如大家最常用的Cydia Substrate),今天我就来介绍一种不需要越狱就能hook iOS app方法,也就是Mach-O LC_LOAD_DYLIB Hook。这种方法是通过修改binary本身来加载第三方dylib并实现hook,具体思路是:

提取ipa中的二进制文件 -> 修改二进制文件的Load Commands列表,加入要hook的dylib –> hook.dylib在函数constructor函数中完成对特定函数的hook->对修改后的ipa进行签名,打包和安装。

首先我们先来看一下我们将要进行注入的目标app,这个app非常简单,就是调用上一章讲过的talker这个类输出一句”Hello, iOS!”。

在Products文件夹中我们能够看到IceAndFire.app这个文件,也就是编译完后的App:

IceAndFire.app其实就是个文件夹,里面可以看到很多的资源文件(签名信息,图片等),但最重要的东西就是与文件夹同名的IceAndFire这个二进制文件了。我们可以用xxd命令来看一下里面的内容:

这个二进制文件里保存了IceAndFire这个app的所有逻辑,但是直接看二进制编码太辛苦了,这里我推荐一个叫做MachOView的软件(可以在我的github里下载),通过这个软件就可以看到整个MachO文件的结构了:

在Load Commands这个数据段里,我们可以看到IceAndFire这个二进制文件会在启动的时候自动加载Foundation, libobjc.A.dylib等动态库。如果我们对MachO这个文件的Load Commands结构体进行修改,是不是就可以让IceAndFire这个app在启动的时候加载我们自定义的用来hook的dylib呢?没错,这个想法是可行的。并且我们只要在dylib的构造函数里完成相应的hook逻辑,就可以在app启动的时候对指定函数进行hook操作了。

那么如何修改MachO的结构体呢?用010 editor等二进制编辑器的确是一种方法,但实在是麻烦了点。好消息是金正日小分队已经把自动注入dylib的工具帮我们写好了。这个叫yololib的工具可以帮我们直接进行dylib的注入:https://github.com/KJCracks/yololib。但作者只放出了源码没有放出binary,我帮大家编译了一份扔到了我的github上(https://github.com/zhengmin1989/iOS_ICE_AND_FIRE)。

编译好yololib后,我们只需要在Mac上执行:

./yololib [binary] [dylib file]
./yololib [被插入dylib的二进制文件] [要插入的dylib]

命令即可完成dylib的注入,如图所示:

现在我们再用MachOView看一下IceAndFire这个二进制文件就会看到hook1.dylib已经被我们成功注入进去了:

“@executable_path/hook1.dylib”的意思是二进制文件会在当前目录下对hook1.dylib进行加载,所以我们编译好的hook1.dylib要和二进制文件一起放到IceAndFire.app文件夹里,这样才能保证我们在运行app的时候hook1.dylib能够被正确的加载。

0x02 CaptainHook for Dylib

修改好了app二进制文件的Load Commands结构体后,我们再来看看如何构造进行hook的第三方dylib。因为app自己肯定不会主动调用第三方dylib中的函数,所以如果我们想要让第三方dylib进行hook操作就要把hook的逻辑写到构造函数里。实现构造函数很简单,只要在函数前声明 ”attribute((constructor)) static” 即可,我们先写个”Hello, Ice and Fire!”测试一下:

编译好dylib文件后,我们将这个dylib文件与App一起签名、打包、安装。然后我们运行一下程序就可以看到我们注入的dylib库已经在程序启动的时候成功加载并执行了。

下一步就是要实现对特定函数的hook。在这里我推荐使用CaptainHook这个framework。作者已经帮我们实现了hook所需要的各种宏,只要按照如下步骤就可以完成针对特定函数的hook:

  1. 使用 CHDeclareClass() 声明想要hook的class;
  2. 在构造函数中用 CHLoadClass() 或 CHLoadLateClass() 加载声明过的class;
  3. 使用CHMethod() hook相应的method;
  4. 在CHMethod()中可以使用CHSuper()来调用原函数;
  5. 在构造函数中使用CHClassHook()来注册将要hook的method。

比如我们想要hook Talker这个class里的say method,让app在调用say的时候修改method的参数,让say的话都变成”Hello, Android!”,我们只需要这样编写dylib的源码:

#import <CaptainHook/CaptainHook.h>
CHDeclareClass(Talker);
CHMethod(1, void, Talker, say, id, arg1)
{
    NSString* [email protected]"Hello, Android!";
    CHSuper(1, Talker, say, tmp);
}
__attribute__((constructor)) static void entry()
{
    NSLog(@"Hello, Ice And Fire!");
    CHLoadLateClass(Talker);
    CHClassHook(1, Talker,say);
}

CHMethod()这个宏的格式是:参数的个数,返回值的类型,类的名称,selector的名称,selector的类型,selector对应的参数的变量名。

CHClassHook()这个宏的格式是:参数的个数,返回值的类型,类的名称,selector的名称。

编写完代码后,我们对源码进行编译,将生成的dylib文件与app一起签名、打包、安装。然后我们运行一下程序就可以看到我们注入的dylib库已经成功的hook了say method了,原本应该输出”Hello, iOS!”,已经被我们成功的变成了”Hello, Android!”:

0x03 签名、打包和安装

我们知道越狱后的iPhone有一个很重要的特性就是可以关闭app的签名校验,关掉签名校验后,App Store上的app(无论是收费的还是免费的)就可以随意盗版并且免费安装了。但是在非越狱的iPhone上,系统要求app必须要有合法的签名,负责无法进行安装。其实除了AppStore上的app有合法的签名外,我们还可以使用开发者证书或者企业证书来让没有合法签名的app拥有合法的签名。

当我们拥有开发者帐号并且在机器上安装了证书的话,就可以在Keychain Access这个工具中看到我们的签名信息:

我们接下来要干的事情就是使用这个开发者证书来对我们修改后的IceAndFire .app进行签名。步骤如下:

1.首先先保证IceAndFire.app文件夹下有正确的embedded.mobileprovision文件:

如果没有的话,可以去苹果的开发者中心(developer.apple.com)生成。如果是个人开发者要注意将iOS设备的UDID加到开发者的设备列表中再生成embedded.mobileprovision文件,如果是企业证书则没有设备数量的限制。

2.正确的编写签名时使用的Entitlements.plist:

这里最需要注意的就是application-identifier要包含正确的Team ID (可以在开发者中心查看) 和对应的Bundle ID。

3.使用codesign对hook的dylib进行签名:

codesign -f -s "iPhone Developer: [email protected] (XXXXXXXXX)" IceAndFire.app/hook1.dylib

4.使用codesign对app进行签名:

codesign -f -s "iPhone Developer: [email protected] (XXXXXXXXX)" --entitlements Entitlements.plist IceAndFire.app

5.使用xcrun将IceAndFire.app打包成IceAndFire.ipa:

xcrun -sdk iphoneos PackageApplication -v IceAndFire.app  -o ~/iOSPwn/hook/github/IceAndFire.ipa

6.使用itunes或者mobiledevice进行安装。

成功的话会显示”OK”。然后就可以在非越狱的手机上使用我修改后的app了。

0x04 Class-dump 和 ida

通过上面几节的介绍,我们已经将非越狱app hook的流程走过一遍了,但这时候有人会问:”你hook的app是自己写的,你当然知道应该hook哪个函数了,我想hook的app都是App Store上的,并没有源码,我该怎么办?”其实这个问题也不难解决。只要用好class-dump和ida即可。

Class-dump是一款可以用来dump头文件工具:

比如我们想要dump XXX的头文件,只需要执行:

./class-dump -H -o header XXX

经过dump后,所有的头文件都会保存在“header”这个文件夹中:

每个头文件中都包含了类和方法的声明:

可以看到,利用class-dump能够很好的帮助我们了解App的内部结构。但是class-dump只能获取App的头文件,并不能知道每个方法具体的逻辑,这时候我们就需要用到ida了。

利用ida我们可以获取到一个方法具体的逻辑,不过这需要你对arm汇编有一定的了解:

比如上图所示的函数就是调用NSLog(@”%@\n”)来向控制台输出参数的内容。只有了解了某个函数具体是做什么的,我们能才知道如何hook这个函数。

0x05 微信自动抢红包的原理

至于微信自动抢红包的插件无非就是hook了接收微信消息的函数,然后判断消息中有没有红包,有的话就直接调用打开红包的函数即可。但因为这篇文章的主要目的是介绍非越狱手机的app hook,而不是鼓励大家使用外挂,所以具体实现的细节就不公布了,有兴趣的同学可以自己尝试写一个。虽然效果没有机械流那么酷炫,但的确省时省力啊。

0x06 总结

通过这篇文章我们可以看到,即使是在非越狱的iOS系统上依然可以玩出很多的花样,因此各大it厂商不要盲目的相信非越狱iOS系统的安全性。针对红包和支付等比较重要的逻辑一定要有混淆和加固,针对app本身一定要有完整性校验。不然好心的白帽子可能只是写个自动抢红包的外挂玩玩,但是黑客就可能利用这种技术开发各种外挂来牟取暴利或者让用户在无意当中安装上带有后门的app,随后会发生什么就只有天知道了。

最后感谢我的同事黑雪和耀刺对这篇文章的帮助和指导。

PS: 文中涉及代码可在我的Github下载,地址:https://github.com/zhengmin1989/iOS_ICE_AND_FIRE

时间: 2024-10-05 09:32:20

iOS冰与火之歌番外篇 - 在非越狱手机上进行App Hook(转载)的相关文章

iOS冰与火之歌

iOS冰与火之歌 – Objective-C Pwn and iOS arm64 ROP 蒸米 · 2016/01/26 10:29 0x00 序 冰指的是用户态,火指的是内核态.如何突破像冰箱一样的用户态沙盒最终到达并控制如火焰一般燃烧的内核就是<iOS冰与火之歌>这一系列文章将要讲述的内容.目录如下: Objective-C Pwn and iOS arm64 ROP █████████████ █████████████ █████████████ █████████████ 另外文中涉

编程珠玑番外篇

1.Plan 9 的八卦 在 Windows 下喜欢用 FTP 的同学抱怨 Linux 下面没有如 LeapFTP 那样的方便的工具. 在苹果下面用惯了 Cyberduck 的同学可能也会抱怨 Linux 下面使用 FTP 和 SFTP 是一件麻烦的事情. 其实一点都不麻烦, 因为在 LINUX 系统上压根就不需要用 FTP. 为什么呢? 因为一行简单的配置之后, 你就可以像使用本机文件一样使用远程的任何文件. 无论是想编辑, 查看还是删除重命名, 都和本机文件一样的用. 这么神奇的功能到底如何

(apache+tomcat集群+memcached番外篇)单台tomcat的session信息的2种持久化方式

为什么要实现搭建tomcat集群环境呢?主要因为单个tomcat无论从吞吐量和并发数上,会达到一定的极限.如果访问量超过单个tomcat的承受能力的话,tomcat一般要么拒绝提供服务,要么直接宕掉.所以,必须要依靠tomcat集群技术.举个最简单的例子,拿"送快件"比喻,如果一个人,5分钟送一件,一小时之内,送10个,一个人完全能胜任这项工作.假设现在到了双十一,要求1小时,送100个, 那怎么办?只能安排更多的人加入"送快件"这项工作中来.这其实和集群一个道理.

【喵&quot;的Android之路】【番外篇】有关于null的一些知识点

[喵"的Android之路][番外篇]有关于null的一些知识点 1.首先,到底什么是null? null是Java中的一个关键字,用于表示一个空对象引用,但其本身并不是任何类型也不是属于任何对象.因此,下面的做法是错误的: int a = null; 但: Object obj = null; 是可以的,因为null表示Object类型的一个空对象引用,符合其用意. [注1]引用类型使用null声明对象变量后,无法使用该变量访问对象的成员.例如上述obj对象如果使用obj.toString()

可视化(番外篇)

本篇主要介绍如何在SWT下构建一个应用,如何安装SWT Designer并破解已进行SWT的可视化编程,Display以及Shell为何物.有何用,SWT中的常用组件.面板容器以及事件模型等. 1.可视化环境搭建(SWT Designer): (1).首先下载SWT Designer插件包SWT Designer 6.9.5 for Eclipse.rar: (2).将解压好的插件包extplugins\swt\eclipse下的features和plugins导入Myeclipse的dropi

《Mycat学习笔记》 番外篇一.客户端使用latin1字符集,后端MySQL为UTF8字符集,MyCat日志分析。

其实这个番外篇比较无聊——即客户端为lantin字符集,后面MySQL为U8字符集,MyCat在中间到底会起什么作用. 再说下本次验证的环境: Mac OS 10.11.2 MySQL 5.6 MyCat 1.5 OK,开始我们的验证工作. 1) 由于数据库与操作系统已被默认设置为U8编码,计划通过修改Mysql  “character_set_client” 参数调整客户端字符集配置进行验证. 关于MYSQL字符集较全面的介绍,请参考 <mysql_query("set names gb

【喵&quot;的Android之路】【番外篇】关于==和equals

[喵"的Android之路][番外篇]关于==和equals 在实际的编程当中,经常会使用==和equals来判断变量是否相同.但是这两种比较方式也常常让人搞得云里雾里摸不着头脑.下面是我个人做的总结,希望能起到拨云见日的作用. [讲前普及] 请阅读 [喵"的Android之路][基础篇(一)][Java面向对象基础]数据类型与运算符 了解Java基本数据类型和引用数据类型 1."=="运算符 通俗点讲,==运算符比较的是两个变量在栈中的内容是否相同. 以a ==

cocos2dX 番外篇之CCSpriteBatchNode

嗯, 今天我们没事干, 闲的蛋疼, 干脆我们创建精灵玩玩吧, 我随手一打, 我去, 出了一万个精灵, 感觉我就是万能的上帝啊, 一万个( 旁白: 请不要放弃治疗好么), 嘿嘿, 看看一万个精灵是啥样: 看起来很不错啊( 旁白: 等等, 那个帧数怎么下降这么多啊), 额, 竟然被妹纸看出来了, 好吧, 我们进入今天的课程CCSpriteBatchNode 在游戏的某一时刻, 我们可能会大量的绘制某一个精灵( 比如发出的子弹, 搜集的星星之类), 我们都是使用同一张纹理图片创建的, 如果一张一张的进

Linux入门之内核管理番外篇(4)udev入门(1)

Linux入门之内核管理番外篇(4)udev入门(1) 前言 在上篇中的内核模块管理讲解中,最后或多或少会留下一些疑问,那么这些疑问就是内核模块的参数是怎么和对应的硬件所匹配上的,而硬件又是怎么被内核识别,并且一个个都映射成实际存在的文件,而这些文件之间的关系及作用.当然在最后了解到,这些硬件设备的探测信息是通过一个叫udev的工具来实现的,通过udev中配置的规则可以很有效的识别每一个硬件,并配合sysfs文件系统,将每个探测到的硬件信息导入到/sys目录中,那么与/proc目录对与内核系统信