CydiaSubstrate与SSL Pinning绕过

0x00 上文

前一篇文章Xposed Framework使用方法以及SSL pinning绕过介绍了安卓上的hook框架Xposed Framework的使用方法,本篇将介绍iOS上的hook框架CydiaSubstrate以及SSL pinning绕过方法。

0x01 准备:不使用Developer账号制作ipa文件

1.进入/Application文件夹,右键Xcode.app点击"Show Package Contents"

2.进入Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS9.3.sdk/目录,修改SDKSettings.plist文件,把DefaultProperties下的CODE_SIGNING_REQUIRED从YES改为NO,把AD_HOC_CODE_SIGNING_ALLOWED从NO改为YES,保存。记得改之前备份该文件。如果显示没有权限修改该文件,则先把该文件拷贝到桌面,修改完再复制回去。

3.重启Xcode,在Navigator->Project Navigator里,找到Code Signing Identity,把所有Debug和Release模式全部设置为Don't Code Sign。

4.点击Product->Archive。


5.第4步会构建Archive,当第4步完成后,会出现Organize - Archive窗口。右键你的archive->Show in Finder。

6.在Finder里右键*.xcarchive文件->Show Package Contents,在Products/Applications下找到.app文件。

7.打开iTunes,调到Apps模式,把上一步的.app文件拖入iTunes。

8.右键app->Show in Finder,你就能看到一个.ipa文件了,这是未签名的ipa文件。

9.回到Xcode,打开Preference,追加一个Apple ID,然后点击View Details,点击iOS Development和Mac Development之后的Create键,就会在KeyChain里创建署名用的证书。

10.下载iResign,打开iReSign,第一行是未签名ipa文件的路径,最后一行填证书的名字。证书的名字在KeyChain里可以找到,打开KeyChain,点击My Certificates,找到对应的证书,证书名字形如(iPhone Developer: YourMailAddress (XXXXXXXX))。填完这两个信息,点击ReSign即可签名。

5.第4步会构建Archive,当第4步完成后,会出现Organize - Archive窗口。在右侧选择Export。在弹出的窗口中选择Development,然后Next,选择你的Personal Team Apple账号,然后一路Next,最后选择保存的路径即可。

6.打开刚刚保存的文件夹,可以发现IPA文件在那里了。可以在Xcode里选择Window->Devices and Simulators,然后选择你的设备,点击右侧画面最下方的加号,即可安装。

7.如果出现A valid provisioning profile for this executable was not found.这个错误,说明你没有把provision profile安装到你的iPhone上,这时你有两个选择,一个是在Xcode中直接"Build and run the current scheme"把App直接编译运行装到你的iPhone上,这样provision profile也会被自动装到你的iPhone上。另一种方法是在~/Library/MobileDevice/Provisioning Profiles目录下找到xxxxxxxx.mobileprovision文件,通过Window->Devices and Simulators手动把它安装到iPhone上:

8.如果你是越狱的机器,在iPhone上安装AppSync Unified即可。如果不是越狱的机器,在iPhone的一般->プロファイルとデバイス管理里找到自己的デベロッパAPP、検証一下就好了。

关于导出IPA文件可以参考这篇文章:
https://medium.com/m%CE%BBgn%CE%BEt%CE%BBr/how-to-export-a-ipa-file-from-xcode-without-a-dev-account-bac8b2645ad3
关于provisioning profile可以参考这篇文章:
https://medium.com/@abhimuralidharan/what-is-a-provisioning-profile-in-ios-77987a7c54c2

0x02 准备:修复SSL pinning项目

这次我们使用的SSL pinning是这个ios-ssl-pinning,但是它的证书同样过期了,我们去github上导出一张github的最新的证书,导出格式为Der,命名为github.com.cer,保存到SSL pinning iOS/Resouces/文件夹下,覆盖掉原来过期的证书,然后编译,按照上一节的步骤制作ipa文件。

编译前需要安装AFNetworking这个库,按照README安装即可。

0x03 ssl-kill-switch2

下载并安装ssl-kill-switch2。我安装完了之后并没有成功bypass SSL Pinning,在Xcode中查看log发现ssl-kill-switch2显示警告Preference file not found.Subtrate hook disabled.查看源代码才发现ssl-kill-switch2试图读取该文件:/private/var/mobile/Library/Preferences/com.nablac0d3.SSLKillSwitchSettings.plist,而iPhone中并没有该文件,于是我自己写了一个com.nablac0d3.SSLKillSwitchSettings.plist文件,里面只有一个域叫做shouldDisableCertificateValidation,bool型,值为YES,scp到该iPhone目录下,ReSpring后ssl-kill-switch2即正确运行了。 在iPhone的设置里找到ssl-kill-switch2,启用即可。

正确运行后可以发现app能够正常请求github.com,其他https网站诸如google.com也可以正确请求,在设置中将ssl-kill-switch2关闭后则只有github.com的请求能正常执行。

0x04 ssl-kill-switch2分析

待续。

0x05 substrate的坑

实际使用中,发现某函数hook后会导致app crash,上网查找后发现substrate不能hook小于12字节的函数。而我在debug 64位的binary时,发现substrate会用最少16字节来覆盖掉原函数,如果原函数少于16字节,则函数后面的部分就会被覆盖掉了。具体如下:
%e3%82%b9%e3%82%af%e3%83%aa%e3%83%bc%e3%83%b3%e3%82%b7%e3%83%a7%e3%83%83%e3%83%88-2016-10-06-16-40-04
解释以下substrate的hook原理:

首先,ldr x16, #8PC+8中储存的值赋值给x16。注意此时PC0x1000eb93c,所以PC+80x1000eb944,所以从0x1000eb944开始读出8字节的数值为0x0000000103b1bc80,将该地址赋值给x16

下一条指令br x16会调用x16指向的函数,也就是0x0000000103b1bc80处的函数。该函数如下:
%e3%82%b9%e3%82%af%e3%83%aa%e3%83%bc%e3%83%b3%e3%82%b7%e3%83%a7%e3%83%83%e3%83%88-2016-10-06-16-41-09
我们发现这个函数就是我们写的钩子函数。

以上就是substrate如何hook函数的原理,就是在函数原来的地址处写入了一些跳转命令,覆盖掉了原函数。而这些跳转命令至少要占16个字节,注意到我们的函数只有8字节,所以该函数和它之后的函数都被覆盖掉了,这就很可能会导致我们的app crash。付一张这两个函数被覆盖前的状态:
1475807519883