當前位置:
首頁 > 新聞 > 安卓APP破解利器Frida之破解實戰

安卓APP破解利器Frida之破解實戰

在第一篇博文中,我對Frida做了一些簡單的介紹,現在,我們就使用 Frida 來進行一個安卓APP的破解實戰吧。通過之前我們對Frida用法的了解和掌握,破解一個簡單的crackme 就變得非常簡單了。如果你想跟著我一起操作,你需要下載下面幾個文件:


1. OWASP Crackme Level 1 (APK)


2. Bytecode Viewer


3. dex2jar


當然,我假設你已經成功的安裝了Frida 9.1.16或更高的版本,並且在你的已經ROOT過的安卓設備中安裝了相應的server 二進位文件。我在本次教程中使用的是安卓7.1.1 的ARM版本的模擬器。

可以使用如下命令在你的安卓設備上安裝 OWASP Crackme Level 1 app:


等待APP安裝完畢,然後在模擬器的菜單中啟動這個APP。如下圖(右下角的橘黃色圖標):

安卓APP破解利器Frida之破解實戰



當你啟動了這個APP後,你會發現它會提示你「不能運行在已ROOT的安卓設備中」。如下圖所示:

安卓APP破解利器Frida之破解實戰



點擊「OK」後,APP會立馬退出。嗯……看起來,我們無法繼續破解這個APP了。真的么?讓我們來看看到底發生了什麼事情以及這個APP的內部到底有些什麼。


使用dex2jar把這個apk文件轉換成一個jar包。


michael@sixtyseven:/opt/dex2jar/dex2jar-2.0$ ./d2j-dex2jar.sh -o /home/michael/UnCrackable-Level1.jar /home/michael/UnCrackable-Level1.apkdex2jar /home/michael/UnCrackable-Level1.apk -> /home/michael/UnCrackable-Level1.jar

之後將這個jar包載入到BytecodeViewer中,或者你也可以選擇使用其他的支持Java的反彙編工具。你也可以選擇直接將APK文件載入到 BytecodeViewer中,但是我操作的時候遇到了問題,所以我就使用dex2jar先把APK轉成jar然後再導入到 BytecodeViewer中。

安卓APP破解利器Frida之破解實戰



下面是CFR反編譯器反編譯這個APP的MainActivity的輸出內容:


package sg.vantagepoint.uncrackable1;import android.app.Activity;import android.app.AlertDialog;import android.content.Context;import android.content.DialogInterface;import android.os.Bundle;import android.text.Editable;import android.view.View;import android.widget.EditText;import sg.vantagepoint.uncrackable1.a;import sg.vantagepoint.uncrackable1.b;import sg.vantagepoint.uncrackable1.c;public class MainActivityextends Activity { private void a(String string) { AlertDialog alertDialog = new AlertDialog.Builder((Context)this).create(); alertDialog.setTitle((CharSequence)string); alertDialog.setMessage((CharSequence)"This in unacceptable. The app is now going to exit."); alertDialog.setButton(-3, (CharSequence)"OK", (DialogInterface.OnClickListener)new b(this)); alertDialog.show(); } protected void onCreate(Bundle bundle) { if (sg.vantagepoint.a.c.a() || sg.vantagepoint.a.c.b() || sg.vantagepoint.a.c.c()) { this.a("Root detected!"); //This is the message we are looking for } if (sg.vantagepoint.a.b.a((Context)this.getApplicationContext())) { this.a("App is debuggable!"); } super.onCreate(bundle); this.setContentView(2130903040); } public void verify(View object) { object = ((EditText)this.findViewById(2131230720)).getText().toString(); AlertDialog alertDialog = new AlertDialog.Builder((Context)this).create(); if (a.a((String)object)) { alertDialog.setTitle((CharSequence)"Success!"); alertDialog.setMessage((CharSequence)"This is the correct secret."); } else { alertDialog.setTitle((CharSequence)"Nope..."); alertDialog.setMessage((CharSequence)"That s not it. Try again."); } alertDialog.setButton(-3, (CharSequence)"OK", (DialogInterface.OnClickListener)new c(this)); alertDialog.show(); }}


通過查看其他的被反編譯的class文件後,我們發現這是一個很小的APP,所以,我們完全可以搞定這個crackme的解密演算法的逆向和一般的字元串的修改。然而,我們有了Frida這款破解利器,操作起來會更加方便簡單。讓我們來看看這個APP在哪裡進行了設備是否已經ROOT的檢查。根據上面提示的消息內容「Root detected」,我們找到了下面的代碼:


public static boolean a() { String[] a = System.getenv("PATH").split(":"); int i = a.length; int i0 = 0; while(true) { boolean b = false; if (i0 >= i) { b = false; } else { if (!new java.io.File(a[i0], "su").exists()) { i0 = i0 + 1; continue; } b = true; } return b; } } public static boolean b() { String s = android.os.Build.TAGS; if (s != null && s.contains((CharSequence)(Object)"test-keys")) { return true; } return false; } public static boolean c() { String[] a = new String[7]; a[0] = "/system/app/Superuser.apk"; a[1] = "/system/xbin/daemonsu"; a[2] = "/system/etc/init.d/99SuperSUDaemon"; a[3] = "/system/bin/.ext/.su"; a[4] = "/system/etc/.has_su_daemon"; a[5] = "/system/etc/.installed_su_daemon"; a[6] = "/dev/com.koushikdutta.superuser.daemon/"; int i = a.length; int i0 = 0; while(i0 < i) { if (new java.io.File(a[i0]).exists()) { return true; } i0 = i0 + 1; } return false; }


利用Frida 我們可以通過重寫這些方法讓它們都返回false,重寫方法的方式我們在本系列教程的第一部分中有講解到。但是,當有一個方法返回了true時,到底發生了什麼?難道就是因為發現設備已經root了么?我們在MainActivity的函數a中看到,它打開一個窗體。並且設置了一個onClickListener,這在我們點擊「OK」按鈕時會被觸發。


alertDialog.setButton(-3, (CharSequence)"OK", (DialogInterface.OnClickListener)new b(this));


onClickListener這個監聽器的實現代碼並不是很多。

package sg.vantagepoint.uncrackable1;class b implements android.content.DialogInterface$OnClickListener { final sg.vantagepoint.uncrackable1.MainActivity a; b(sg.vantagepoint.uncrackable1.MainActivity a0) { this.a = a0; super(); } public void onClick(android.content.DialogInterface a0, int i) { System.exit(0); }}


上述代碼僅僅使用了System.exit(0)退出了APP。因此,我們要做的就是阻止APP的退出。讓我們使用Frida重寫一下onClick這個方法。


創建一個名為uncrackable1.js的文件,並把下面的代碼寫入這個文件中。


setImmediate(function() { //prevent timeout console.log("[*] Starting script"); Java.perform(function() { bClass = Java.use("sg.vantagepoint.uncrackable1.b"); bClass.onClick.implementation = function(v) { console.log("[*] onClick called"); } console.log("[*] onClick handler modified") })})


如果你閱讀過本系列教程的第一部分,那麼你應該能明白這些代碼:我們將代碼封裝在了setImmediate這個函數中以阻止超時(你或許不需要關注這個),之後調用了Java.perform 通過Java使用Frida內置的一些方法。真正起作用的代碼為:我們檢索這個類的包裝器,實現OnClickListener介面並覆蓋其onClick方法。 在我們的版本中,這個函數只是在控制台輸出一些內容。 而不是原來那樣會退出APP。 由於原來的onClickHandler被我們的Frida注入函數所取代,並且永遠不會被調用,所以當我們點擊對話框的OK按鈕時,APP不會退出。讓我們試試吧 打開APP(讓它顯示「Root detected」對話框)。

安卓APP破解利器Frida之破解實戰



並且在這個時候注入腳本:


Frida注入代碼會等待幾秒鐘,直到你看到「onClickHandler」的消息(這個時候你可能會得到一個shell,因為我們把代碼放在了一個setImmediate包裝器中,所以Frida會在後台執行它)。

安卓APP破解利器Frida之破解實戰


然後點擊APP中的「OK」按鈕。如果一切順利,APP應該不再退出。

安卓APP破解利器Frida之破解實戰



很好:對話框消失了,現在我們可以輸入密碼。 我們輸入一些內容,按「驗證」按鈕看看會發生什麼:

安卓APP破解利器Frida之破解實戰



正如預期的那樣,APP提示了錯誤的代碼。 但是我們有一個我們正在尋找的想法:某種對輸入的內容進行加密/解密的演算法以及將結果和你輸入的內容進行比較。


再次檢查MainActivity,我們在函數中看到如下代碼:


public void verify(View object) {

if (a.a((String)object)) {


package sg.vantagepoint.uncrackable1;import android.util.Base64;import android.util.Log;/* * Exception performing whole class analysis ignored. */public class a { public static boolean a(String string) { byte[] arrby = Base64.decode((String)"5UJiFctbmgbDoLXmpL12mkno8HT4Lv8dlat8FxR2GOc=", (int)0); byte[] arrby2 = new byte[]{}; try { arrby2 = arrby = sg.vantagepoint.a.a.a((byte[])a.b((String)"8d127684cbc37c17616d806cf50473cc"), (byte[])arrby); } catch (Exception var2_2) { Log.d((String)"CodeCheck", (String)("AES error:" + var2_2.getMessage())); } if (!string.equals(new String(arrby2))) return false; return true; } public static byte[] b(String string) { int n = string.length(); byte[] arrby = new byte[n / 2]; int n2 = 0; while (n2 < n) { arrby[n2 / 2] = (byte)((Character.digit(string.charAt(n2), 16)


我們現在可以開始對字元串操作和解密功能進行逆向分析,並對原始的加密字元串進行處理,這些字元串也包含在上面的代碼中。或者我們讓APP執行我們並不在乎的所有加密處理過程,我們只需要HOOK sg.vantagepoint.a.a.a這個函數來捕獲它的返回值就行。 返回值是解密後字元串(以位元組數組的形式)並與我們的輸入進行比較。 下面是要注入的腳本的作用:


aaClass = Java.use("sg.vantagepoint.a.a"); aaClass.a.implementation = function(arg1, arg2) { retval = this.a(arg1, arg2); password = for(i = 0; i < retval.length; i++) { password += String.fromCharCode(retval[i]); } console.log("[*] Decrypted: " + password); return retval; } console.log("[*] sg.vantagepoint.a.a.a modified");


把這些代碼片段放在一起,這裡是完整的腳本:


setImmediate(function() { console.log("[*] Starting script"); Java.perform(function() { bClass = Java.use("sg.vantagepoint.uncrackable1.b"); bClass.onClick.implementation = function(v) { console.log("[*] onClick called."); } console.log("[*] onClick handler modified") aaClass = Java.use("sg.vantagepoint.a.a"); aaClass.a.implementation = function(arg1, arg2) { retval = this.a(arg1, arg2); password = for(i = 0; i < retval.length; i++) { password += String.fromCharCode(retval[i]); } console.log("[*] Decrypted: " + password); return retval; } console.log("[*] sg.vantagepoint.a.a.a modified"); });});


我們來運行這個腳本。 像以前一樣,將其保存為uncrackable1.js並執行(如果Frida沒有自動重新運行的話)。


不過請注意Frida的輸出:


michael@sixtyseven:~/Development/frida$ frida -U -l uncrackable1.js sg.vantagepoint.uncrackable1 ____ / _ | Frida 9.1.16 - A world-class dynamic instrumentation framework | (_| | > _ | Commands: /_/ |_| help -> Displays the help system . . . . object? -> Display information about object . . . . exit/quit -> Exit . . . . . . . . More info at http://www.frida.re/docs/home/[*] Starting script[USB::Android Emulator 5554::sg.vantagepoint.uncrackable1]-> [*] onClick handler modified[*] sg.vantagepoint.a.a.a modified[*] onClick called.[*] Decrypted: I want to believe


很好,實際上我們已經得到了解密的字元串:「I want to believe」。 沒錯,就是它。我們來看看它是否有效:

安卓APP破解利器Frida之破解實戰



到目前為止,我希望你至少對Frida可以做些什麼有了一些深刻的印象了——它是一個動態的二進位插樁工具。


喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 嘶吼RoarTalk 的精彩文章:

外媒:朝鮮導彈發射失敗或因美國網路攻擊所致
絕密追蹤:利用像素圖片收集攻擊目標信息
比特幣錢包遭暴力破解的真相竟是為了挖寶
如何使用Unicode域名進行網路釣魚攻擊?

TAG:嘶吼RoarTalk |

您可能感興趣

Android APP破解利器Frida之反調試對抗
Python強勢破解WiFi密碼!
Android逆向之旅-Android中鎖屏密碼演算法解析以及破解方案
Wifi密碼破解實戰
Flying Robot Police Hero Battle破解版 飛行機器人警察英雄解鎖破解版
Splash Cars破解版 Splash Cars無限鑽石破解版
Primer Premier 6安裝、破解、引物設計實操攻略
BotHeads破解版 BotHeads去廣告破解版
破解密碼「AlphaGo」誕生,訓練GAN破解27%LinkedIn測試集密碼
iPhone 6s的NFC功能 遭越獄高手破解
FBI介入Cellebrite 又破解了台iPhone
Steel Skies破解版 Steel Skies無限鑽石破解版
FBI介入Cellebrite,又幫忙破解了台蘋果iPhone
工具推薦:逆向破解利器OllyDbg
手機安全受挑戰?iPhone 5s疑似被破解
「Science」破解密碼「AlphaGo」誕生,訓練Gan破解27%LinkedIn測試集密碼
破解Dress Code——五招教你玩轉Party季!
破解Dress Code——五招教你玩轉Party季!
DEFCON精彩破解:Apple Pay被攻破、機器人解鎖保險箱、用聲音攻擊智能設備(含PPT)