在iOS應用程式中使用Frida繞過越獄檢測,iosfrida
阿里聚安全在之前的三篇部落格中介紹了利用Frida攻擊Android應用程式,整個過程彷彿讓開發人員開啟上帝視角,在本篇部落格中,我們將會介紹在iOS應用程式中使用Frida繞過越獄檢測。即使你從來沒有使用過Frida,這篇文章也將會作為進入Mobile Security開發和分析的入門指南。
相關文章內容:
利用FRIDA攻擊Android應用程式(一)
利用FRIDA攻擊Android應用程式(二)
利用FRIDA攻擊Android應用程式(三)
一、Frida介紹
Frida是一個可以hook App的動態代碼工具包,可以向Windows、macOS、Linux、iOS、Android和QNX的本機應用程式中注入JavaScript或自己的庫代碼。最開始的時候,它是基於Google的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/
更多Mobile Security類知識乾貨,請持續關注阿里聚安全的部落格