日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > Android >内容正文

Android

Android APP破解利器Frida之反调试对抗

發(fā)布時間:2025/4/5 Android 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android APP破解利器Frida之反调试对抗 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
本文講的是Android APP破解利器Frida之反調(diào)試對抗,在我發(fā)表了關(guān)于Frida的第二個博文后不久,@muellerberndt決定發(fā)布另外一個新的OWASP Android?破解APP,我很想知道我是否可以再次使用Frida解決這個CrackMe。如果你想跟隨我一起操作,你需要做以下準(zhǔn)備:

·?OWASP Level2的CrackMe APK

·?Android SDK和模擬器(我使用的是Android 7.1 x64映像)

·?Frida安裝(以及frida-server二進(jìn)制文件

·?ByteCode viewer

·?radare2(或你喜歡使用的其他一些反匯編程序)

·?apktool

如果你需要知道如何安裝Frida,請查看Frida的相關(guān)?文檔。對于Frida的使用,你還可以查看本教程系列的第I部分。我想你在繼續(xù)本文的操作之前已經(jīng)擁有所有需要的東西,并且基本上熟悉了Frida的使用。另外,確保Frida可以連接到你的設(shè)備或模擬器(例如使用frida -ps -U 命令)。

警告:本教程不僅僅是一個快速破解Crackme的練習(xí)。相反,我將向你展示各種方法來克服所遇到的具體問題。如果你只是尋找一個快速的破解方案,請在本教程末尾查看相關(guān)的Frida腳本。

注意:如果你遇到了下面這個錯誤:

Error:?access?violation?accessing?0xebad8082

或者使用Frida時會出現(xiàn)了類似的錯誤,再模擬器中擦除用戶數(shù)據(jù),重新啟動并重新安裝該apk可能有助于解決此類錯誤問題。

做好多次嘗試的準(zhǔn)備。該應(yīng)用程序可能會崩潰,模擬器也可能會重新啟動,一切也可能會搞砸,但是,它依舊可以正常工作。

先把APP跑起來

在開始時,我們做的事情和之前破解UnCrackable1是一樣的,先運行應(yīng)用程序:接下來,當(dāng)你在模擬器中運行它時,它會檢測到它是在有root權(quán)限的設(shè)備上運行的。

我們可能會嘗試像之前破解UnCrackable 1一樣Hook OnClickListener。但首先我們來看看我們是否可以連接到Frida來進(jìn)行篡改:

michael@sixtyseven:~/Development$?frida?-U?sg.vantagepoint.uncrackable2____/?_??|???Frida?9.1.27?-?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/ Failed?to?attach:?ambiguous?name;?it?matches:?sg.vantagepoint.uncrackable2?(pid:?5184),?sg.vantagepoint.uncrackable2?(pid:?5201)

這是什么東西?有兩個名稱相同的進(jìn)程?我們可以使用frida -ps -U命令來驗證一下:

5184??sg.vantagepoint.uncrackable2 5201??sg.vantagepoint.uncrackable2

奇怪。我們試著將Frida注入到父進(jìn)程:

michael@sixtyseven:~/Development$?frida?-U?5184____/?_??|???Frida?9.1.27?-?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/ Failed?to?attach:?unable?to?access?process?with?pid?5184?due?to?system?restrictions;?try?`sudo?sysctl?kernel.yama.ptrace_scope=0`,?or?run?Frida?as?root

看起來它并不起作用,因為當(dāng)我們使用root權(quán)限運行Frida時,我們得到了相同的結(jié)果,所以提出的解決方案并沒有什么幫助。這里到底發(fā)生了什么?我們來看看應(yīng)用程序吧。解壓縮apk并使用ByteCodeViewer 查看classes.dex并進(jìn)行反編譯(例如CFR-Decompiler):

package?sg.vantagepoint.uncrackable2; import?android.app.AlertDialog; import?android.content.Context; import?android.content.DialogInterface; import?android.os.AsyncTask; import?android.os.Bundle; import?android.support.v7.app.c; import?android.text.Editable; import?android.view.View; import?android.widget.EditText; import?sg.vantagepoint.a.a; import?sg.vantagepoint.a.b; import?sg.vantagepoint.uncrackable2.CodeCheck; import?sg.vantagepoint.uncrackable2.MainActivity; public?class?MainActivity extends?c?{private?CodeCheck?m;static?{System.loadLibrary("foo");?//[1]}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?/*?Unavailable?Anonymous?Inner?Class!!?*/);alertDialog.setCancelable(false);alertDialog.show();}static?/*?synthetic?*/?void?a(MainActivity?mainActivity,?String?string)?{mainActivity.a(string);}private?native?void?init();?//[2]protected?void?onCreate(Bundle?bundle)?{this.init();?//[3]if?(b.a()?||?b.b()?||?b.c())?{this.a("Root?detected!");}if?(a.a((Context)this.getApplicationContext()))?{this.a("App?is?debuggable!");}new?/*?Unavailable?Anonymous?Inner?Class!!?*/.execute((Object[])new?Void[]{null,?null,?null});this.m?=?new?CodeCheck();super.onCreate(bundle);this.setContentView(2130968603);}public?void?verify(View?view)?{String?string?=?((EditText)this.findViewById(2131427422)).getText().toString();AlertDialog?alertDialog?=?new?AlertDialog.Builder((Context)this).create();if?(this.m.a(string))?{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?/*?Unavailable?Anonymous?Inner?Class!!?*/);alertDialog.show();} }

我們注意到一個調(diào)用static的靜態(tài)調(diào)用System.load加載了foo庫(參見[1])。該應(yīng)用程序還在其onCreate方法的第一行調(diào)用了this.init()(參見[3]),該方法被聲明為一種native方法(參見[2]),因此它可能是foo的一部分。

現(xiàn)在讓我們來看看foo庫。在radare2中,打開這個庫文件(你可以在lib文件夾中找到各種架構(gòu)的多個庫文件,我在這里使用的是lib/x86_64),分析并列出其導(dǎo)出函數(shù):

michael@sixtyseven:~/Development/UnCrackable2/lib/x86_64$?r2?libfoo.so--?Don't?look?at?the?code.?Don't?look. [0x000007a0]>?aaa [x]?Analyze?all?flags?starting?with?sym.?and?entry0?(aa) [x]?Analyze?len?bytes?of?instructions?for?references?(aar) [x]?Analyze?function?calls?(aac) [?]?[*]?Use?-AA?or?aaaa?to?perform?additional?experimental?analysis. [x]?Constructing?a?function?name?for?fcn.*?and?sym.func.*?functions?(aan)) [0x000007a0]>?iE [Exports] vaddr=0x00001060?paddr=0x00001060?ord=004?fwd=NONE?sz=183?bind=GLOBAL?type=FUNC?name=Java_sg_vantagepoint_uncrackable2_CodeCheck_bar vaddr=0x00001050?paddr=0x00001050?ord=006?fwd=NONE?sz=15?bind=GLOBAL?type=FUNC?name=Java_sg_vantagepoint_uncrackable2_MainActivity_init vaddr=0x00004008?paddr=0x00003008?ord=014?fwd=NONE?sz=0?bind=GLOBAL?type=NOTYPE?name=__bss_start vaddr=0x00004008?paddr=0x00003008?ord=015?fwd=NONE?sz=0?bind=GLOBAL?type=NOTYPE?name=__bss_start vaddr=0x0000400d?paddr=0x0000400d?ord=016?fwd=NONE?sz=0?bind=GLOBAL?type=NOTYPE?name=_end 5?exports [0x000007a0]>

我們注意到,該庫出口2個有趣的導(dǎo)出函數(shù):

Java_sg_vantagepoint_uncrackable2_MainActivity_init和Java_sg_vantagepoint_uncrackable2_CodeCheck_bar

(對這些方法的具體命名可以查看Java接口NATIV JNI)。

我們來看看Java_sg_vantagepoint_uncrackable2_MainActivity_init:

[0x000007a0]>?s?0x00001050 [0x00001050]>?V

這是一個相當(dāng)短的函數(shù):

[0x00001050?29%?848?libfoo.so]>?pd?$r?@ sym.Java_sg_vantagepoint_uncrackable2_MainActivity_init???????????????????????????????????????????????????????????????????????????????????????????????????? /?(fcn)?sym.Java_sg_vantagepoint_uncrackable2_MainActivity_init?15?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? |???sym.Java_sg_vantagepoint_uncrackable2_MainActivity_init?();????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? |???????????0x00001050??????50?????????????push?rax???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? |???????????0x00001051??????e8caf7ffff?????call?sub.fork_820???????????;[1]???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? |???????????0x00001056??????c605af2f0000.??mov?byte?[0x0000400c],?1????;?[0x400c:1]=58?;?":?(GNU)?4.9.x?20150123?(prerelease)"????????????????????????????????????????????????????????????????????? |???????????0x0000105d??????58?????????????pop?rax??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????0x0000105e??????c3?????????????ret?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????0x0000105f??????90?????????????nop

它調(diào)用了另一個函數(shù)sub.fork_820,在這個函數(shù)中還有更多的函數(shù)調(diào)用:

[0x00000820?14%?265?libfoo.so]>?pd?$r?@?sub.fork_820???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? /?(fcn)?sub.fork_820?242??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? |???sub.fork_820?();??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? |???????????;?var?int?local_8h?@?rsp+0x8???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? |???????????;?var?int?local_10h?@?rsp+0x10????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? |??????????????;?CALL?XREF?from?0x00001051?(sym.Java_sg_vantagepoint_uncrackable2_MainActivity_init)??????????????????????????????????????????????????????????????????????????????????????????????? |???????????0x00000820??????4156???????????push?r14????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? |???????????0x00000822??????53?????????????push?rbx????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? |???????????0x00000823??????4883ec18???????sub?rsp,?0x18??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? |???????????0x00000827??????64488b042528.??mov?rax,?qword?fs:[0x28]????;?[0x28:8]=0x3180?;?'('????????????????????????????????????????????????????????????????????????????????????????????????????? |???????????0x00000830??????4889442410?????mov?qword?[local_10h],?rax??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? |???????????0x00000835??????e806ffffff?????call?sym.imp.fork???????????;[1]????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? |???????????0x0000083a??????8905c8370000???mov?dword?loc.__bss_start,?eax?;?[0x4008:4]=0x43434700?;?loc.__bss_start???????????????????????????????????????????????????????????????????????????????? |???????????0x00000840??????85c0???????????test?eax,?eax??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? |???????,=<?0x00000842??????741a???????????je?0x85e????????????????????;[2]????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? |???????|???0x00000844??????488d15a5ffff.??lea?rdx,?0x000007f0?????????;?0x7f0????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? |???????|???0x0000084b??????488d7c2408?????lea?rdi,?[local_8h]?????????;?0x8??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? |???????|???0x00000850??????31f6???????????xor?esi,?esi????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? |???????|???0x00000852??????31c9???????????xor?ecx,?ecx????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? |???????|???0x00000854??????e8f7feffff?????call?sym.imp.pthread_create?;[3];?ssize_t?read(int?fildes,?void?*buf,?size_t?nbyte)????????????????????????????????????????????????????????????????????? |??????,==<?0x00000859??????e990000000?????jmp?0x8ee???????????????????;[4]???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? |??????||??????;?JMP?XREF?from?0x00000842?(sub.fork_820)???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? |??????|`->?0x0000085e??????e8fdfeffff?????call?sym.imp.getppid????????;[5]????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? |??????|????0x00000863??????89c3???????????mov?ebx,?eax???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? |??????|????0x00000865??????bf10000000?????mov?edi,?0x10??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? |??????|????0x0000086a??????31d2???????????xor?edx,?edx????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? |??????|????0x0000086c??????31c9???????????xor?ecx,?ecx????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? |??????|????0x0000086e??????31c0???????????xor?eax,?eax???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? |??????|????0x00000870??????89de???????????mov?esi,?ebx???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? |??????|????0x00000872??????e8f9feffff?????call?sym.imp.ptrace?????????;[6]???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? |??????|????0x00000877??????4885c0?????????test?rax,?rax???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? |??????|,=<?0x0000087a??????7572???????????jne?0x8ee???????????????????;[4]????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? |??????||???0x0000087c??????4c8d742408?????lea?r14,?[local_8h]?????????;?0x8??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? |??????||???0x00000881??????31d2???????????xor?edx,?edx???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? |??????||???0x00000883??????89df???????????mov?edi,?ebx????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? |??????||???0x00000885??????4c89f6?????????mov?rsi,?r14????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? |??????||???0x00000888??????e883feffff?????call?sym.imp.waitpid????????;[7]

我們看到有調(diào)用fork,pthread_create,getppid,ptrace和waitpid。不需要花費太多的時間來進(jìn)行反匯編,我們就可以猜測出,主進(jìn)程使用ptrace作為調(diào)試器來fork了一個附加到它的子進(jìn)程。這是一個基本的常見的反調(diào)試技術(shù),你可以在這里閱讀到更多信息。

由于Frida 使用?ptrace用于初始的注入操作,所以這就解釋了為什么我們沒有成果連接到父進(jìn)程:附加調(diào)試進(jìn)程被阻止,因為已經(jīng)有其他的進(jìn)程作為調(diào)試器進(jìn)行了連接。

繞過反調(diào)試解決方案1:Frida

Frida來解決問題的目的不是將Frida注入正在運行的進(jìn)程,而是我們可以讓它為我們生成進(jìn)程。使用-f選項,我們告訴Frida注入Zygote并開始啟動應(yīng)用程序。關(guān)閉設(shè)備上的應(yīng)用程序,看看當(dāng)我們啟動Frida時會發(fā)生什么:

frida?-U?-f?sg.vantagepoint.uncrackable2

我們得到如下輸出:

michael@sixtyseven:~/Development/UnCrackable2/lib/x86_64$?frida?-U?-f?sg.vantagepoint.uncrackable2?--no-pause____/?_??|???Frida?9.1.27?-?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/ Spawned?`sg.vantagepoint.uncrackable2`.?Resuming?main?thread!?????????? [USB::Android?Emulator?5554::['sg.vantagepoint.uncrackable2']]->

好吧!Frida注入到了Zygote,產(chǎn)生了我們的進(jìn)程并等待輸入。(我承認(rèn),告訴你在啟動Frida時添加-f選項是一個很長的介紹,不過你已被警告過…)

我們現(xiàn)在準(zhǔn)備繼續(xù)破解,?但是在我們繼續(xù)之前,我們將要檢查另一個解決方案來克服這個破解的調(diào)試保護(hù)。

繞過反調(diào)試解決方案2:補(bǔ)丁

除了讓Frida生成進(jìn)程之外,我們還可以通過對應(yīng)用打補(bǔ)丁來解決我們遇到的問題。這意味著我們需要反匯編應(yīng)用程序,對修改的apk進(jìn)行重建和簽名。但是,在這種情況下,這將會給我們麻煩帶來麻煩。不過我還是會告訴你如何解決這個麻煩,我們稍后會注意到這個問題。

我們可以通過apktool來實現(xiàn)補(bǔ)丁:

michael@sixtyseven:~/Disassembly$?/opt/apktool/apktool.sh?-r?d?UnCrackable-Level2.apk I:?Using?Apktool?2.2.0?on?UnCrackable-Level2.apk I:?Copying?raw?resources... I:?Baksmaling?classes.dex... I:?Copying?assets?and?libs... I:?Copying?unknown?files... I:?Copying?original?files...

(我跳過了資源的提取, 因為-r參數(shù)在重新編譯apk時引起了新的問題,我們在這里不需要APP的資源。)

看一下smali/sg/vantagepoint/uncrackable2/MainActivity.smali 文件里的smali代碼。你可以在82行處找到調(diào)用init的代碼,并且可以將其注釋掉:

#?virtual?methods .method?protected?onCreate(Landroid/os/Bundle;)V.locals?4const/4?v3,?0x0 #????invoke-direct?{p0},?Lsg/vantagepoint/uncrackable2/MainActivity;->init()Vinvoke-static?{},?Lsg/vantagepoint/a/b;->a()Z

重新編譯apk(忽略致命錯誤…):

michael@sixtyseven:~/Disassembly/UnCrackable-Level2$?/opt/apktool/apktool.sh?b I:?Using?Apktool?2.2.0 I:?Checking?whether?sources?has?changed... I:?Smaling?smali?folder?into?classes.dex... [Fatal?Error]?AndroidManifest.xml:1:1:?Content?ist?nicht?zul?ssig?in?Prolog. I:?Checking?whether?resources?has?changed... I:?Copying?raw?resources... I:?Copying?libs...?(/lib) I:?Building?apk?file... I:?Copying?unknown?files/dir...

對齊:

michael@sixtyseven:~/Disassembly/UnCrackable-Level2$?zipalign?-v?4?dist/UnCrackable-Level2.apk??UnCrackable2.recompiled.aligned.apk Verifying?alignment?of?UnCrackable2.recompiled.aligned.apk?(4)...49?AndroidManifest.xml?(OK?-?compressed)914?classes.dex?(OK?-?compressed)269899?lib/arm64-v8a/libfoo.so?(OK?-?compressed)273297?lib/armeabi-v7a/libfoo.so?(OK?-?compressed)279346?lib/armeabi/libfoo.so?(OK?-?compressed)

簽名(注意:你需要有一個密鑰和密鑰庫):

michael@sixtyseven:~/Disassembly/UnCrackable-Level2$?jarsigner?-verbose?-keystore?~/.android/debug.keystore??UnCrackable2.recompiled.aligned.apk?signkey Enter?Passphrase?for?keystore:adding:?META-INF/MANIFEST.MFadding:?META-INF/SIGNKEY.SFadding:?META-INF/SIGNKEY.RSAsigning:?AndroidManifest.xmlsigning:?classes.dexsigning:?lib/arm64-v8a/libfoo.sosigning:?lib/armeabi-v7a/libfoo.sosigning:?lib/armeabi/libfoo.sosigning:?lib/mips/libfoo.so [...]

你可以在“?OWASP移動安全測試指南”中找到更廣泛的描述。卸載掉原始的apk并安裝打過補(bǔ)丁的apk:

adb?uninstall?sg.vantagepoint.uncrackable2 adb?install?UnCrackable2.recompiled.aligned.apk

再次啟動該應(yīng)用程序。運行frida-ps后我們發(fā)現(xiàn)現(xiàn)在只有一個進(jìn)程:

29996?sg.vantagepoint.uncrackable2

Frida連接也沒有問題:

michael@sixtyseven:~/Disassembly/UnCrackable-Level2$?frida?-U?sg.vantagepoint.uncrackable2____/?_??|???Frida?9.1.27?-?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/ [USB::Android?Emulator?5554::sg.vantagepoint.uncrackable2]->

比起給Frida增加 -r選項更為繁瑣一點,但也更普遍的適用。

如前所述,當(dāng)我們使用補(bǔ)丁版本后(我會告訴你如何克服這個,所以不要把它丟棄),我們就不能輕易地提取這個秘密字符串了。但是現(xiàn)在我們繼續(xù)使用原來的apk。確保你按照正確的方式安裝了原始的apk。

繼續(xù)解惑

在我們找到了一些擺脫反調(diào)試的可能性之后,我們來看看我們接下來該如何進(jìn)行。一旦我們按下OK按鈕,應(yīng)用程序就會在模擬器的運行時中進(jìn)行root權(quán)限的檢測并退出。我們已經(jīng)知道UnCrackable1的一些行為。另外,我們可以對這種檢測行為打補(bǔ)丁,刪除System.exit的調(diào)用代碼,但是我們試圖用Frida來解決這個問題。再看看反編譯的代碼,我們看到?jīng)]有OnClickListener類,只是一個匿名的內(nèi)部類。由于onClickListener的實現(xiàn)中調(diào)用了System.exit所以我們簡單地Hook住該函數(shù)并無卵用。

這是Frida腳本:

setImmediate(function()?{console.log("[*]?Starting?script");Java.perform(function()?{exitClass?=?Java.use("java.lang.System");exitClass.exit.implementation?=?function()?{console.log("[*]?System.exit?called");}console.log("[*]?Hooking?calls?to?System.exit");}); });

再次關(guān)閉任何正在運行的UnCrackable2實例,并再次在Frida的幫助下啟動它:

frida?-U?-f?sg.vantagepoint.uncrackable2?-l?uncrackable2.js?--no-pause

等到App啟動后,Frida?在控制臺中顯示了Hooking calls…的消息。然后按“確定”。你應(yīng)該會得到這樣的輸出信息:

michael@sixtyseven:~/Development/frida$?frida?-U?-f?sg.vantagepoint.uncrackable2?--no-pause?-l?uncrackable2.js____/?_??|???Frida?9.1.27?-?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/ Spawned?`sg.vantagepoint.uncrackable2`.?Resuming?main?thread!?????????? [USB::Android?Emulator?5554::['sg.vantagepoint.uncrackable2']]->?[*]?Hooking?calls?to?System.exit [*]?System.exit?called

該應(yīng)用程序不再退出。我們可以輸入一個秘密字符串試試:

但是我們應(yīng)該在這里輸入什么呢?看看MainActivity的Android代碼,檢查正確的輸入邏輯如下:

this.m?=?new?CodeCheck(); [...] //in?method:?public?void?verify if?(this.m.a(string))?{alertDialog.setTitle((CharSequence)"Success!");alertDialog.setMessage((CharSequence)"This?is?the?correct?secret."); }

這是CodeCheck類代碼:

package?sg.vantagepoint.uncrackable2; public?class?CodeCheck?{private?native?boolean?bar(byte[]?var1);public?boolean?a(String?string)?{return?this.bar(string.getBytes());?//Call?to?a?native?function} }

我們注意到,我們的文本字段的輸入也就是我們的“秘密字符串” 被傳遞給一個native函數(shù)bar。我們可以在libfoo.so庫中找到這個函數(shù)。搜索函數(shù)地址(如我們之前使用的init函數(shù)),并用radare2進(jìn)行反匯編:

看看反匯編代碼,我們注意到有一些字符串比較的邏輯,另外我們還注意到一個有趣的明文字符串Thanks for all t.測試這個字符串作為我們的crackme的解決方案后,我們發(fā)現(xiàn)它并不起作用。我們必須繼續(xù)向前。

看看0x000010d8這個地址處的反匯編代碼:

0x000010d8??????83f817?????????cmp?eax,?0x17??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? 0x000010db??????7519???????????jne?0x10f6??????????????????;[1]

這里有一個eax寄存器與0x17的比較,其十進(jìn)制格式為23。如果這個比較不成功,strncmp在這里就不會調(diào)用。我們也注意到了0x17已作為參數(shù)傳遞給了在

0x000010e1 ba17000000 mov edx, 0x17 處的strncmp。

記住,根據(jù)linux 64位的調(diào)用約定,函數(shù)參數(shù)在寄存器中傳遞至少1到6個參數(shù)。尤其是前3個參數(shù)要按照這個順序在RDI,RSI和RDX中傳遞(參見[PDF],第20頁)。Strncmp函數(shù)聲明如下:

int?strncmp?(?const?char?*?str1,?const?char?*?str2,?size_t?num?);

所以我們的strncmp函數(shù)將比較0x17 = 23個字符。我們可以推斷,我們的秘密字符串的長度應(yīng)該是23個字符。

讓我們最后嘗試Hook住strncmp函數(shù),并簡單地打印出它的參數(shù)。我們可以期望這里給我們直接輸出解密的輸入字符串。我們必須

1.??? 查找strncmp函數(shù)在libfoo.so中的內(nèi)存地址

2.??? 使用 Interceptor.attach Hook libfoo.so的strncmp函數(shù)和轉(zhuǎn)儲參數(shù)

如果你這樣做了,你會發(fā)現(xiàn)有很多地方調(diào)用了strncmp,我們將進(jìn)一步限制輸出。這是Frida代碼片段:

var?strncmp?=?undefined; imports?=?Module.enumerateImportsSync("libfoo.so"); for(i?=?0;?i?<?imports.length;?i++)?{ if(imports[i].name?==?"strncmp")?{strncmp?=?imports[i].address;break;} } Interceptor.attach(strncmp,?{onEnter:?function?(args)?{if(args[2].toInt32()?==?23?&&?Memory.readUtf8String(args[0],23)?==?"01234567890123456789012")?{console.log("[*]?Secret?string?at?"?+?args[1]?+?":?"?+?Memory.readUtf8String(args[1],23));}} });

對這個腳本的一些說明:

1.??該腳本調(diào)用Module.enumerateImportsSync從libfoo.so(查閱文檔)中獲取有關(guān)導(dǎo)入信息的對象數(shù)組。我們遍歷這個數(shù)組,直到找到strncmp并檢索其地址。然后我們將攔截器附加到它上面。

2. ?Java中的字符串不會已空字符終止。當(dāng)我們使用Frida的Memory.readUtf8String方法訪問strncmp字符串指針的內(nèi)存位置,并且不提供長度時,Frida會期望一個終止符,否則會輸出一些內(nèi)存垃圾。因為它不知道字符串在哪里結(jié)束。如果我們指定要讀取的字符數(shù)量作為第二個參數(shù),我們就可以解決掉這個警告。

3.??如果我們沒有限制我們轉(zhuǎn)儲strncmp參數(shù)的條件,我們會得到很多輸出。所以我們只輸出strncmp中當(dāng)?shù)谌齻€參數(shù)的參數(shù)size_t為23且第一參數(shù)的字符串指針指向我們在輸入框輸入的01234567890123456789012這個字符串作為過濾條件

我是如何知道args[0]也就是我們的輸入和args[1]也就是秘密字符串的?我其實并不知道,我只是在測試它,并將大量的輸出轉(zhuǎn)儲到屏幕上,以找到我的輸入。如果你不想跳過,你可以在上述腳本中移除if語句,并使用Frida的hexdump輸出:

buf?=?Memory.readByteArray(args[0],32); console.log(hexdump(buf,?{offset:?0,length:?32,header:?true,ansi:?true })); buf?=?Memory.readByteArray(args[1],32); console.log(hexdump(buf,?{offset:?0,length:?32,header:?true,ansi:?true }));

每次調(diào)用strncmp時都會輸出很多hexdumps,所以要提醒你一下。

以下是完整版本的腳本,可以更好地輸出參數(shù):

setImmediate(function()?{Java.perform(function()?{console.log("[*]?Hooking?calls?to?System.exit");exitClass?=?Java.use("java.lang.System");exitClass.exit.implementation?=?function()?{console.log("[*]?System.exit?called");}var?strncmp?=?undefined;imports?=?Module.enumerateImportsSync("libfoo.so");for(i?=?0;?i?<?imports.length;?i++)?{if(imports[i].name?==?"strncmp")?{strncmp?=?imports[i].address;break;}}Interceptor.attach(strncmp,?{onEnter:?function?(args)?{if(args[2].toInt32()?==?23?&&?Memory.readUtf8String(args[0],23)?==?"01234567890123456789012")?{console.log("[*]?Secret?string?at?"?+?args[1]?+?":?"?+?Memory.readUtf8String(args[1],23));}},});console.log("[*]?Intercepting?strncmp");}); });

現(xiàn)在,啟動Frida并加載腳本:

frida?-U?-f?sg.vantagepoint.uncrackable2?--no-pause?-l?uncrackable2.js

輸入字符串并按驗證:

在控制臺,你會得到:

michael@sixtyseven:~/Development/frida$?frida?-U?-f?sg.vantagepoint.uncrackable2?--no-pause?-l?uncrackable2.js____/?_??|???Frida?9.1.27?-?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/ Spawned?`sg.vantagepoint.uncrackable2`.?Resuming?main?thread!?????????? [USB::Android?Emulator?5554::['sg.vantagepoint.uncrackable2']]->?[*]?Hooking?calls?to?System.exit [*]?Intercepting?strncmp [*]?System.exit?called [*]?Secret?string?at?0x7fffa628f010:?Thanks?for?all?the?fish

沒錯,輸出內(nèi)容很好很簡單:完整的秘密字符串。將其輸入到輸入框中并享受成功吧

修復(fù)補(bǔ)丁的解決方案

最后,是有一些關(guān)于補(bǔ)丁修復(fù)的說明,以及為什么我們在使用打過補(bǔ)丁的apk時不會得到秘密字符串。Libfoo中的init函數(shù)包含一些初始化邏輯,阻止應(yīng)用程序根據(jù)我們的輸入檢查或解碼秘密字符串。

如果我們再次看看init函數(shù)的反匯編,我們會看到有趣的一行代碼:

0x00001056?c605af2f0000.?mov?byte?[0x0000400c],?1

在bar函數(shù)的后面會檢查相同的變量libfoo,如果未設(shè)置,則代碼會跳過strncmp:

0x0000107d??????803d882f0000.??cmp?byte?[0x0000400c],?1????;?[0x1:1]=69???????????????????????????????????????????????????????????????????????????????????????????????????????????????? 0x00001084??????7570???????????jne?0x10f6??????????????????;[1]

所以在后面它可能是一個布爾變量,如果init函數(shù)運行,它將被設(shè)置。如果我們想要在我們的apk的修補(bǔ)版本中調(diào)用strncmp那么我們必須設(shè)置此變量,或者至少阻止它跳過實際的strncmp調(diào)用。

我們現(xiàn)在可以再次進(jìn)行修補(bǔ),反編譯apk,覆蓋jmp指令,并重新編譯一次。的確有些餓笨重。?由于這是Frida教程,我們將使用Frida來動態(tài)更改內(nèi)存。

因此,我們需要:

1.??獲取加載foo庫的基址

2.??找到相對于庫基地址的變量(通過反匯編中,我們知道從基地址的偏移量是0x400C字節(jié))

3.??將變量設(shè)置為1

所以,在Frida中的相關(guān)代碼如下:

//Get?base?address?of?library var?libfoo?=?Module.findBaseAddress("libfoo.so"); //Calculate?address?of?variable var?initialized?=?libfoo.add(ptr("0x400C")); //Write?1?to?the?variable Memory.writeInt(initialized,1);

以下是該修補(bǔ)程序版本的完整腳本:

setImmediate(function()?{Java.perform(function()?{console.log("[*]?Hooking?calls?to?System.exit");exitClass?=?Java.use("java.lang.System");exitClass.exit.implementation?=?function()?{console.log("[*]?System.exit?called");}var?strncmp?=?undefined;imports?=?Module.enumerateImportsSync("libfoo.so");for(i?=?0;?i?<?imports.length;?i++)?{if(imports[i].name?==?"strncmp")?{strncmp?=?imports[i].address;break;}}//Get?base?address?of?libraryvar?libfoo?=?Module.findBaseAddress("libfoo.so");//Calculate?address?of?variablevar?initialized?=?libfoo.add(ptr("0x400C"));//Write?1?to?the?variableMemory.writeInt(initialized,1);Interceptor.attach(strncmp,?{onEnter:?function?(args)?{if(args[2].toInt32()?==?23?&&?Memory.readUtf8String(args[0],23)?==?"01234567890123456789012")?{console.log("[*]?Secret?string?at?"?+?args[1]?+?":?"?+?Memory.readUtf8String(args[1],23));}},});console.log("[*]?Intercepting?strncmp");}); });

現(xiàn)在運行應(yīng)用程序,通過frida加載腳本,再次輸入01234567890123456789012。按驗證按鈕。應(yīng)用程序會調(diào)用strncmp并且會記錄秘密字符串:

root@sixtyseven:/home/michael/Development/frida#?frida?-U?sg.vantagepoint.uncrackable2?-l?uncrackable2-final.js____/?_??|???Frida?9.1.27?-?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/ [USB::Android?Emulator?5554::sg.vantagepoint.uncrackable2]->?[*]?Hooking?calls?to?System.exit [*]?Intercepting?strncmp [*]?System.exit?called [*]?Secret?string?at?0x7fffd52c6570:?Thanks?for?all?the?fish

希望你在使用Frida后能體驗到更多的樂趣。




原文發(fā)布時間為:2017年5月11日 本文作者:李白 本文來自云棲社區(qū)合作伙伴嘶吼,了解相關(guān)信息可以關(guān)注嘶吼網(wǎng)站。 原文鏈接

總結(jié)

以上是生活随笔為你收集整理的Android APP破解利器Frida之反调试对抗的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。