【技术分享】如何在.ipa文件上进行iOS代码注入

http://p2.qhimg.com/t01b5eef9a0dc9cc367.png

翻译:骨哥_2015

预估稿费:200RMB

投稿方式:发送邮件至linwei#360.cn,或登陆网页版在线投稿


前言

代码注入是将外部代码注入至现有软件系统的过程。通过本文,我将分享在iOS APPs上执行代码注入所需的工具和技术。使用Xcode工具可以部署一个用以展示iOS代码注入行为的实验。总体思路是创建一组独立的代码,与最终的APP打包,并以某种方式执行新的代码。

[注意:代码的注入过程可在IOS9.3,10.0.2以及XCode v7.3和v8.0环境下正常运行,其他IOS系统或Xcode版本尚未测试]

我们可以使用Xcode,利用两种方式创建一个独立的二进制包:

动态链接库(Cocoa Touch Framework)

静态链接库(Cocoa Touch Static Library)

http://p2.qhimg.com/t01c8ee7ffa6ac6c464.png

动态链接库vs静态链接库:可通过选择创建包含了注入代码的外部二进制文件

静态链接库

编译时链接代码

为了执行代码,静态链接库需要在.ipa文件编译期间可用

静态链接库不支持Swift

没有已知的方法来指导.ipa文件加载静态链接库

我们不能直接使用静态链接库,你需要首先将其转换为动态链接库

动态链接库

运行时链接代码,Xcode在编译期间需要依赖动态链接库/框架,但不保证这些依赖包被打包进APP中,这就是为什么有时你可能会遇到加载动态链接库运行时报错:

dyld: Library not loaded: @rpath/libswift_stdlib_core.dylib

我们可以为动态链接库构建Swift代码

在启动APP之前将动态链接库加载到内存中,以便在.ipa文件中执行dylib命令

是的,我们可以使用这个 ?

选择dylib(动态链接库)作为我们的自定义代码包,让我们使用XCode来呈现代码注入的概念证明(Proof of concept,简称POC)

http://p3.qhimg.com/t01c74ee27712ee98f5.png

步骤如下:

1. 创建一个新的Xcode项目

2. 创建一个新的IOS应用程序目标

3. 创建一个新的“Coca Touch Framework”目标,为其命名为“PatchPGO”

4. 创建一个新的Objective-C Cocoa Touche类。为其命名为“PatchLoader”,在.m文件中添加以下方法。

@implementation PatchLoader 
static void __attribute __((constructor))initialize(void){ 
    NSLog(@“==== Code Injection in Action ====”); 
    / * 
      注入代码放在这里
    * / 
} 
@end

使用方法修饰符,这样在APP启动前会将类加载到内存中,这样就可以指定我们想要做的事情,你可以将其视为要插入IOS APP代码的“入口点”

"static void __attribute__((constructor))”initialize

5. 运行IOS应用程序目标,确保日志控制台的输出与代码注入之前所期望的一样

6. 将动态链接库框架文件与IOS APP进行链接,确保框架被嵌入

http://p7.qhimg.com/t01f2ba8fa593086752.png

http://p0.qhimg.com/t018d72dc93b8e4e844.png

iOS APP Target创建阶段: 确保“Destination”选择了“Frameworks”,并且在“Embed Freameworks”下方嵌入了你的framework

7. 现在你的IOS 应用程序目标已正确链接,运行它并观察日志控制平台

我们的NSLog信息已成功注入到IOS应用程序目标。

http://p9.qhimg.com/t01fa0889410f74ad0d.png

请注意,我们已观察到(新的日志记录)应用程序目标行为的改变,但应用程序目标的代码尚未被修改。Xcode在代码签名和安装修改后的应用程序之前,已悄悄的将库链接到了目标,在上面的注入实验中,开发人员拥有应用程序的源代码。接下来,让我们在没有源代码的情况下,尝试将代码注入到.ipa文件中。


在.ipa文件的代码注入POC(Proof of Concept)

步骤如下:

1. 根据选择下载.ipa文件,你也可以通过第三方(例如:www.iphonecake.com  )下载破解的.ipa文件

2. 下载optool(https://github.com/alexzielenski/optool  )或Clone我的repository

https://github.com/depoon/iOSDylibInjectionDemo  。

这个 repository 实现了在.ipa文件(通过optool)加载dylibs,它包含了optool和一个“patchapp.sh”脚本,详细信息可查看README文件

3. 在iOSDylibInjectionDemo目录中创建一个文件夹,以包含我们将注入到.ipa文件中的动态链接库的二进制文件,为其命名为‘Dylibs’

4. 进入Framework文件夹(你在上面利用Xcode创建的实验)检查Framework文件夹中的内容

http://p0.qhimg.com/t01b82c94a5f926b09a.png

如何在XCode中定位动态框架的文件夹位置:右键单击 – >选择“Show in Finder”

http://p8.qhimg.com/t01a3942a97b33036c5.png


动态框架目录,动态链接库的二进制文件以蓝色突出显示

找到与框架文件夹同名的文件,这个文件即是我们需要通过它来修改.ipa文件的动态链接库二进制文件,将这个二进制文件复制到第3步创建的文件夹中,此时你的文件夹应该像下面这样:

http://p8.qhimg.com/t01ec824fd24062b3be.png


Dylibs文件夹已包含了我们的自定义的动态链接库代码

如果你的动态链接库包含Swift代码,你需要将标准的Xcode Swift dylib库复制到“Dylibs”文件夹中,Swift dylibs也可在本地

/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift 路径下找到。

这时添加了标准Swift dylib文件后的文件夹目录应该看起来像下面这样:

http://p0.qhimg.com/t01f189ae7a22384196.png


为代码注入而准备的标准Swfit dylib

将.ipa修改的过程我们用术语称之为“Patching”。进入iOSDylibPatchingDemo文件夹,并在终端中运行“sh ./patchapp.sh cracked.ipa ./DYLIBS”命令,其中“cracked.ipa”为我们要“Patch”的ipa文件,“./DYLIBS”为要“Patch”的dylib文件夹,然后会输出一个经过“Patch”的名为“cracked-path.ipa”的.ipa文件,并完成代码注入过程,但是,在这一点上,我们不能安装或side load这个.ipa文件到任何非越狱设备上,因为即使“cracked-patch.ipa”有注入代码,在我们对它的内容进行了调整和修改之后,.ipa代码签名也是无效的。

http://www.cydiaimpactor.com   下载Cydia Imapctor,Cydia Impactor是一款允许我们安装任意.ipa文件到非越狱设备的工具,并允许我们通过重签名的.ipa文件使用与该设备相关连的有效配置文件和凭据。

http://p5.qhimg.com/t0124eef058ee7d5889.png


Cydia Impactor Mac App

您可以通过将“cracked-patch.ipa”拖放到Cydia Impactor Mac App中开始.ipa安装过程,随后它将提示你输入苹果开发者的用户名和密码。

http://p0.qhimg.com/t016e87277b826c80bf.png


Cydia Impactor在安装期间会请求输入你的苹果开发者用户名和密码

Cydia Impactor(CI)会尝试登录到你的苹果开发者中心并下载你的配置文件以及在本地keychain中检索你的iOS开发证书,CI将以深度优先的方式从最深的文件夹级别开始,尝试对.ipa文件内容进行签名,使其达到.ipa文件夹级别,在此之后,CI将.ipa文件安装并side load到指定的设备,在这个过程中,设备会将.ipa文件认为是由用户开发和签名的,因此允许修改应用并在设备上成功启动,如果你不喜欢Cydia Impactor,你也可以自动动手对.ipa文件进行重签名,然后使用Xcode将.ipa文件side load到设备。

http://p0.qhimg.com/t014005830966629ade.png

Patching .ipa文件过程

http://p6.qhimg.com/t0173ae51d9f1c156ad.png

签名和安装.ipa文件到非越狱设备的过程

观察日志控制台,并搜索我们之前插入到动态链接库中的NSLog消息:"==== Code Injection in Action====",如果能够找到这个日志消息,那么你可以开始庆祝了,因为你已经成功地在IOS.ipa文件上执行了代码注入,你可以针对任何ipa文件执行这个代码注入过程。

http://p5.qhimg.com/t016b3bf6e824b6dd9a.png

嗯…..。这似乎对我来说很邪恶。

我在11月份的IOS Dev Scout Meetup(新加坡)介绍了这个主题,并演示了我是如何使用代码注入打破PokemonGo APP游戏的,在Meetup期间,观众通过添加键盘记录功能,打破了其它游戏的规则,并提出了黑客的想法,对于使用代码来破解APPs并不是那么容易的,因为它需要大量的猜测工作以及数小时的试错以保证它的准确性。


一些邪恶的想法

Keylogging (https://gist.github.com/johndel/6df8aee01055ed21dd9a#file-keylogger-swift-L65  )

Method Swizzling (http://nshipster.com/method-swizzling/  )

Get classes, ivars, properties, methods information via Objective C runtimehttps://developer.apple.com/reference/objectivec/1657527-objective_c_runtime 

Get a list of registered classes https://developer.apple.com/reference/objectivec/1418579-objc_getclasslist  )

有了以上的这些想法,恶意的开发人员可以读取任何一个应用程序中的所有类和ivars、method,并利用这些信息为恶意攻击做准备,最重要的是,无需使用越狱设备。

如果你有兴趣阅读关于使用这种代码注入技术来破解一个真正的应用程序,这里是我的下一篇博客hacking PokemonGo App 

https://medium.com/@kennethpoon/hacking-the-pokemongo-ios-app-with-3-classes-4b81589a9f39#.kz2vey8ir 

那么,邪恶的是谁呢?


总结

经过本篇文章用以描述整个iOS代码注入过程后,我个人认为允许任何人对.ipa文件进行重签名的功能是一个严重的安全缺陷,一旦一个ipa被签名后,它应该是不可改变的,任何企图破坏其内容的行为都应被认为是被破坏的,IOS设备不应该允许这类.ipa文件启动。

我希望读者对这篇文章有更深刻的见解,随意评论或通过de_poon@hotmail.com联系我。

(完)