阿裡聚安全在之前的三篇博客中介紹了利用Frida攻擊Android應用程式,整個過程仿佛讓開發者開啟上帝視角,在本篇博客中,我們將會介紹在iOS應用程式中使用Frida繞過越獄檢測。即使你從來沒有使用過Frida,這篇文章也將會作為進入移動安全開發和分析的入門指南。 相關文章內容: 利用FRIDA攻 ...
阿裡聚安全在之前的三篇博客中介紹了利用Frida攻擊Android應用程式,整個過程仿佛讓開發者開啟上帝視角,在本篇博客中,我們將會介紹在iOS應用程式中使用Frida繞過越獄檢測。即使你從來沒有使用過Frida,這篇文章也將會作為進入移動安全開發和分析的入門指南。
相關文章內容:
一、Frida介紹
Frida是一個可以hook App的動態代碼工具包,可以向Windows、macOS、Linux、iOS、Android和QNX的本機應用程式中註入JavaScript或自己的庫代碼。最開始的時候,它是基於谷歌的V8 Javascript運行,但是從版本9開始,Frida已經開始使用其內部的Duktape運行。
列舉一些Frida的使用場景:
1、hooking特定函數並更改返回值
2、分析定製協議,同時其動態嗅探/解密
3、應用調試
4、在iOS應用上dump 類和方法信息
…
Firda眾多不同的使用場景,花樣繁多的啟動方式,包括各種強大的API和方法,讓它成為開發者建立自己安全分析的首選工具。它可以使用命令行界面或類似frida-trace的工具來跟蹤底層函數。同時還可以使用C、NodeJS或Python綁定完成更複雜的任務。但是在其內部,Frida使用Javascript的時候較多,可以通過JavaScript完成大部分的工作。
Frida之所以如此的能對安全檢測如此有用,就是因為它能夠在非越獄的設備上運行。 Frida提供了一個叫做“FridaGadget.dylib”的動態庫,可以用來在未越獄設備上為應用程式插入FridaGadget.dylib。開發者可以使用Swizzler2等工具來修改應用程式以在應用程式中添加FridaGadget.dylib。
iOS系統下,已有幾種基於Frida的安全分析工具,例如Needle和AppMon。
Needle是一個開源的模塊化框架,主要簡化iOS應用程式安全評估過程,並作為一個中心點。鑒於其模塊化方法,Needle很容易擴展新模塊,可以以Python腳本的形式加入。
地址:https://github.com/mwrlabs/needle
AppMon是監測和修改本地macOS、iOS、Android系統API的自動化框架,並能通過web介面顯示和操作
地址:https://github.com/dpnishant/appmon
二、在iOS上的設置Frida
設置步驟十分簡單,開發者同時在iOS設備和電腦上設置安裝Frida。
在iOS設備安裝步驟如下:
1、在iOS設備中打開Cydia APP
2、添加URL地址:https://build.frida.re
3、打開Source或搜索Frida,點擊Modify,然後安裝。
4、打開終端並輸入pip install frida來安裝Frida綁定, 當然你還可以使用python、C或NodeJS綁定來完成更複雜的任務
三、使用Frida連接iOS進程
完成Frida所有設置後,開始對iOS應用安全評估和利用之旅。
Damn Vulnerable iOS Application(DVIA)作為本次的測試方法,地址:http://damnvulnerableiosapp.com/
下文涉及的代碼,GitHub地址:https://github.com/interference-security/frida-scripts/tree/master/iOS
我們將從DVIA中分析越獄檢測操作,當前設備已顯示越獄。
首先查看目標設備的所有運行進程列表
frida-ps –U
從上面的截圖可以看到所有在iOS設備上運行的進程。
輸入frida –U process-name即可附加到任一進程,在Frida控制台獲取目標進程的屬性,記憶體和函數。
現在我們可以在Frida的shell中工作,它可以與我們的iOS進程進行交互,也可以編寫JavaScript來獲取我們想要的分析數據
四、Dump 類和方法信息
這個步驟是用於識別哪個ViewController和function負責驗證iOS設備是否越獄
ViewController是iOS應用程式中重要的部分,是應用程式數據和視圖之間的重要橋梁,ViewController管理應用中的眾多視圖。 iOS的SDK中提供很多原生ViewController,以支持標準的用戶界面,例如表視圖控制器(UITableViewController)、導航控制器(UINavigationController)、標簽欄控制器(UITabbarController)和iPad專有的UISplitViewController等。
先寫一個基礎的Frida腳本來dump目標應用程式中所有的class文件和method信息。開始尋找任何和越獄相關的內容,以便我們在Frida的幫助下繞過越獄檢測。
進程示意圖如下:
1、在DVIA中使用Frida尋找越獄檢測的類
先來看看應用程式中所有的class文件
for (var className in ObjC.classes)
{
if (ObjC.classes.hasOwnProperty(className))
{
console.log(className);
}
}
運行腳本,我們就會看到Frida附加到目標進程,一旦載入完成,它將在目標進程中顯示出許多class文件。
使用grep命令來找到相關的class文件是比較好的辦法。當我們運行grep Jailbreak的命令時,我們就會看到一個名為JailbreakDetectionVC的類,如下圖所示
在找到所有實例之後,會看到一個safe to ignore的錯誤聲明。因此首要任務就是尋找目標類,找出此類中任何相關的方法,這是一個有趣的過程。
2、在DVIA中使用Frida尋找越獄檢測的方法
使用ObjC.classes.class-name.$methods,此例中只需在我們的目標類-JailbreakDetectionVC,找到該方法。
console.log("[*] Started: Find All Methods of a Specific Class");
if (ObjC.available)
{
try
{
var className = "JailbreakDetectionVC";
var methods = eval('ObjC.classes.' + className + '.$methods');
for (var i = 0; i < methods.length; i++)
{
try
{
console.log("[-] "+methods[i]);
}
catch(err)
{
console.log("[!] Exception1: " + err.message);
}
}
}
catch(err)
{
console.log("[!] Exception2: " + err.message);
}
}
else
{
console.log("Objective-C Runtime is not available!");
}
console.log("[*] Completed: Find All Methods of a Specific Class");
繼續運行,運行grep檢索例如Jailbreak、Jailbroken、detection的字元串,如下圖所示
我們找到isJailbroken、jailbreakTest1Tapped:、jailbreakTest2Tapped:的3種字元串,符合上檢索目標。其中,isJailbroken看起來最像檢測設備是否越獄並返回值的函數。
3、在DVIA中使用Frida修改越獄檢測方法的返回值
查看isJailbroken發送的返回值
{
try
{
var className = "JailbreakDetectionVC";
var funcName = "- isJailbroken";
var hook = eval('ObjC.classes.' + className + '["' + funcName + '"]');
Interceptor.attach(hook.implementation, {
onLeave: function(retval) {
console.log("[*] Class Name: " + className);
console.log("[*] Method Name: " + funcName);
console.log("\t[-] Type of return value: " + typeof retval);
console.log("\t[-] Return Value: " + retval);
}
});
}
catch(err)
{
console.log("[!] Exception2: " + err.message);
}
}
else
{
console.log("Objective-C Runtime is not available!");
運行腳本,在iOS應用中按下Jailbreak Test 1按鈕,我們可以在Frida控制台看到返回值
因為設備已經越獄,顯示的返回值為0*1,意味著返回函數True。
接下來我們的任務是覆蓋返回值並修複方法,以便每當按下Jailbreak Test 1按鈕的時候,返回值為false或0*0。
我們添加另一行來改變這個特定函數的返回值。通過下麵的代碼來實現,並將其記錄到控制台。
newretval = ptr("0x0")
retval.replace(newretval)
console.log("\t[-] New Return Value: " + newretval)
最終腳本如下:
if (ObjC.available)
{
try
{
var className = "JailbreakDetectionVC";
var funcName = "- isJailbroken";
var hook = eval('ObjC.classes.' + className + '["' + funcName + '"]');
Interceptor.attach(hook.implementation, {
onLeave: function(retval) {
console.log("[*] Class Name: " + className);
console.log("[*] Method Name: " + funcName);
console.log("\t[-] Type of return value: " + typeof retval);
console.log("\t[-] Original Return Value: " + retval);
newretval = ptr("0x0")
retval.replace(newretval)
console.log("\t[-] New Return Value: " + newretval)
}
});
}
catch(err)
{
console.log("[!] Exception2: " + err.message);
}
}
else
{
console.log("Objective-C Runtime is not available!");
}
一旦運行腳本,我們看到返回值已經修改
查看iOS的APP,可以看到設備顯示未越獄
---------------------------------------------------------
本文由Douglas編譯自attify,原文地址:http://blog.attify.com/2017/05/06/bypass-jailbreak-detection-frida-ios-applications/
更多移動安全類知識乾貨,請持續關註阿裡聚安全的博客