ACTF flutter逆向学习
參考了許多大佬的博客,在此特別誠(chéng)摯感謝oacia大佬和其他大佬的博客和指導(dǎo)!
1.flutter和apk基礎(chǔ)結(jié)構(gòu)介紹
首先下載附件,是一個(gè)apk文件,用jadx打開
可以看見flutter字樣,而flutter是一種目前比較流行的android框架,很多app都是用的該框架構(gòu)建,而該原生框架是建立在app的native層。
Android的系統(tǒng)架構(gòu)采用了分層架構(gòu)的思想。從下往上依次分為L(zhǎng)inux內(nèi)核、硬件抽象層(HAL)、系統(tǒng)Native庫和Android運(yùn)行時(shí)環(huán)境、Java框架層以及應(yīng)用層這5層架構(gòu),其中每一層都包含大量的子模塊或子系統(tǒng)
而平時(shí)我們接觸到的都是應(yīng)用層和Java框架層,包括用Jadx對(duì)apk進(jìn)行逆向時(shí)也只是在逆向Java層的邏輯。如果想要逆向native層,就需要對(duì)android進(jìn)行解包
apk本身是一個(gè)包,壓縮了運(yùn)行時(shí)的依賴、配置文件以及native庫,也就是.so,將apk文件后綴名修改成.zip后,即可解壓查看這些文件
也可以使用androidkiller這個(gè)工具對(duì)apk進(jìn)行分析、修改
最基礎(chǔ)的app配置文件放在AndroidManifest.xml,這個(gè)文件里面存放的有app的很多配置,如該題的配置情況如下,可以在這個(gè)文件里面看到該應(yīng)用的包名,名稱、SDK的版本等等信息,這些信息在app取證里面很有用,對(duì)之后的動(dòng)態(tài)調(diào)試SO層也有很大幫助。
<?xml version="1.0" encoding="utf-8" standalone="no"?><manifest xmlns:android="http://schemas.android.com/apk/res/android" android:compileSdkVersion="33" android:compileSdkVersionCodename="13" package="com.example.flutter_application_1" platformBuildVersionCode="33" platformBuildVersionName="13">
<application android:appComponentFactory="androidx.core.app.CoreComponentFactory" android:icon="@mipmap/ic_launcher" android:label="flutter_application_1" android:name="android.app.Application">
<activity android:configChanges="density|fontScale|keyboard|keyboardHidden|layoutDirection|locale|orientation|screenLayout|screenSize|smallestScreenSize|uiMode" android:exported="true" android:hardwareAccelerated="true" android:launchMode="singleTop" android:name="com.example.flutter_application_1.MainActivity" android:theme="@style/LaunchTheme" android:windowSoftInputMode="adjustResize">
<meta-data android:name="io.flutter.embedding.android.NormalTheme" android:resource="@style/NormalTheme"/>
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<meta-data android:name="flutterEmbedding" android:value="2"/>
<uses-library android:name="androidx.window.extensions" android:required="false"/>
<uses-library android:name="androidx.window.sidecar" android:required="false"/>
</application>
</manifest>
至于其他的文件夾,大家可以自行查閱,這里就不一一說明。
而native層的.so文件就放在lib的幾個(gè)文件夾里面
這三個(gè)文件夾分別代表了不同架構(gòu)的.so文件。我們?nèi)绻胗谜鏅C(jī)調(diào)試.so文件,那么就要用真機(jī)對(duì)應(yīng)的架構(gòu),不能亂用。
2.blutter安裝以及使用
接下來把lib文件進(jìn)行解包,因?yàn)閒lutter使用的是dart語言,并且采用了dartVM的方法進(jìn)行拍攝快照,所以我們現(xiàn)在要使用一些工具對(duì).so文件進(jìn)行快照解析,市面上對(duì)flutter的逆向工具都是這個(gè)原理。
但是有一個(gè)問題,dart快照是可以更改的,隨著DartSdk版本的更新,reflutter和flutter逆向助手已經(jīng)停止更新,這次的這個(gè)題flutterSDK過高,兩個(gè)工具都無法破解,于是找到了blutter這個(gè)工具
官方地址:
GitHub - worawit/blutter: Flutter Mobile Application Reverse Engineering Tool
用git把blutter.py拉進(jìn)kali里面(如果拉不進(jìn)就直接到GitHub上下zip解壓就行),然后安裝依賴。
sudo apt install python3-pyelftools python3-requests git cmake ninja-build
build-essential pkg-config libicu-dev libcapstone-dev
若報(bào)錯(cuò)如下
說明你該更新你的apt源了
sudo apt-get update
下載完成情況如圖
接下來就可以用這個(gè)工具了,將解壓后的app放進(jìn)虛擬機(jī),在blutter目錄下運(yùn)行.py文件,注意有兩個(gè)參數(shù),前一個(gè)參數(shù)是.so文件所在的其中一個(gè)目錄,后一個(gè)參數(shù)是結(jié)果輸出目錄
若成功會(huì)解析稍微長(zhǎng)一點(diǎn)的時(shí)間,耐心等待即可,如果有下圖結(jié)果即為解析完成
完成后在輸出目錄會(huì)有五個(gè)文件和文件夾
按照作者的說法,分別對(duì)應(yīng)的是
pp.txt:在對(duì)象池里面的所有dart對(duì)象(dart采用了對(duì)象池的設(shè)計(jì)模式),這里面可以查看很多對(duì)象池變量的偏移地址
objs.txt:對(duì)象池中對(duì)象的完整(嵌套)轉(zhuǎn)儲(chǔ),在這里我理解成對(duì)象池里面的方法和相應(yīng)的偏移量
blutter_frida.js:這個(gè)是用于對(duì)該flutter程序hook的js代碼,應(yīng)用在frida這個(gè)工具里面(接下來會(huì)講到)
ida_script:這個(gè)文件夾裝的是.so文件的符號(hào)表還原腳本,因?yàn)閐art語言是依靠偏移量識(shí)別函數(shù)的,所以也能依靠偏移量還原函數(shù)
asm:對(duì)dart語言的反編譯結(jié)果,里面有很多dart源代碼的對(duì)應(yīng)偏移
3.動(dòng)態(tài)調(diào)試flutter程序
接下來就是利用frida工具hook插樁以及動(dòng)態(tài)調(diào)試破解該程序了
環(huán)境:具有python環(huán)境的win10系統(tǒng)、kali系統(tǒng)
設(shè)備:pixel3(需要root)
重點(diǎn):必須是歐版,如果不是歐版OEM無法打開,不可能刷的了機(jī)
具體root過程參考https://sspai.com/post/76276
工具:adb調(diào)試橋、IDA7.7工具
3.1.下載adb
https://blog.csdn.net/x2584179909/article/details/108319973
3.2.運(yùn)行IDA
注意,在此之前需要將chall.apk修改成可調(diào)試狀態(tài)
具體方法為利用androidkiller打開程序->在AndroidManifest.xml里面第二行插入
android:debuggable="true"
如果程序SDK版本比較老,這樣就可以,但是這個(gè)程序的targetSdkVersion是33,是高版本,簽名會(huì)出問題,所以在apktool.xml改成27或者28即可
兩處改好后就可以進(jìn)行編譯,得到新的程序。
完成后即可安裝到手機(jī)上
adb install chall_killer.apk
查看自己的手機(jī)是什么架構(gòu)可以用下列代碼
adb shell getprop ro.product.cpu.abi
在ida的下圖文件夾內(nèi)找到android_server64(我的真機(jī)架構(gòu)是arm64位的)
連接手機(jī)(手機(jī)上打開USB調(diào)試),打開終端,利用adb程序在手機(jī)上下載chall.apk,安裝完成后把之前找到的server文件push到手機(jī)里執(zhí)行
adb push android_server64 /data/local/tmp/as
adb shell
su #加載手機(jī)root權(quán)限
cd /data/local/tmp/
chmod 777 as #給server文件可讀可寫可執(zhí)行權(quán)限
./as -p 12345 #用12345端口運(yùn)行server
如果運(yùn)行成功會(huì)有一個(gè)正在監(jiān)聽的提示,說明這個(gè)命令端已經(jīng)成為了server端監(jiān)聽了
接下來重新開啟一個(gè)命令行,adb轉(zhuǎn)發(fā)端口
adb forward tcp:12345 tcp:12345
保持收發(fā)端口一致后啟動(dòng)ida,將libapp.so放進(jìn)ida
用剛才blutter解析得到的addName.py還原符號(hào)表
得到了符號(hào)表之后,查看解析的asm里面的main.dart,查找主程序里面的函數(shù)
在flutter官網(wǎng)查找四個(gè)函數(shù)的含義均為dart的API
表單交互 (Forms)
或者可以在這篇博客上找到
Flutter基建 - 按鈕全解析 - 掘金
onChanged():這個(gè)API在刪除或插入文本的時(shí)候的回調(diào)函數(shù)
onSubmitted():當(dāng)用戶完成文本輸入并按下鍵盤上的“完成”按鈕時(shí)的回調(diào)函數(shù)
onLongPressed():在屏幕上保持了一段時(shí)間
onTap():用戶點(diǎn)擊事件完成(點(diǎn)擊提交按鈕時(shí))
現(xiàn)在查看我們的程序,可以看見這個(gè)程序的窗口組成,而最重要的應(yīng)該是提交按鈕,對(duì)應(yīng)的也就是onTap()回調(diào)函數(shù)所做的
所以直接過濾器查找這個(gè)函數(shù)(也可以直接用之前在main.dart里面找到的函數(shù)地址)
回調(diào)函數(shù)在0xE03C4處
之后我們查看程序發(fā)現(xiàn)有256這個(gè)變量
再加上這里很明顯的RC4加密流程
可以大概得知這是一個(gè)RC4加密。
3.3.frida工具h(yuǎn)ook key值
接下來需要用到frida工具,frida是一款基于python + java 的hook框架,可運(yùn)行在android、ios、linux、win、osx等各平臺(tái),主要使用動(dòng)態(tài)二進(jìn)制插樁技術(shù)。
安裝部分可以看這里
frida安裝正確流程
上面步驟中用blutter解析快照時(shí),工具自動(dòng)幫我們寫了一個(gè)插樁腳本,叫做blutter_frida.js,只需要在下圖所示部分修改成上面有RC4加密的函數(shù)地址,即可hook出密文
改完之后使用frida加載這個(gè)js腳本
frida -U -f com.example.flutter_application_1 -l blutter_frida.js
隨便輸入點(diǎn)什么執(zhí)行程序即可hook得到密文
3.4.動(dòng)態(tài)調(diào)試部分
現(xiàn)在可以調(diào)試一下我們的apk應(yīng)用程序
首先打開應(yīng)用debug模式,如果上面的androidkiller如果不行,可以用面具開,具體流程如下圖
adb shell
su
magisk resetprop ro.secure 0
magisk resetprop ro.debuggable 1
getprop ro.debuggable #如果回顯為1則已經(jīng)開啟
stop
start #上面兩步重啟手機(jī)
這個(gè)時(shí)候下載monitor(DDMS)用于觀察程序進(jìn)程是否開啟(如果是真機(jī)可能不需要這一步)
打開monitor.bat,可以看見設(shè)備上的進(jìn)程
這個(gè)時(shí)候掛起程序
jdb -connect com.sun.jdi.SocketAttach:hostname=127.0.0.1,port=8639
運(yùn)行結(jié)果如下圖
如果有報(bào)錯(cuò) 致命錯(cuò)誤:無法附加到目標(biāo) VM。
那可能是端口搞錯(cuò)了,這里要填寫的是應(yīng)用程序的端口,而不是adb運(yùn)行server的端口。
運(yùn)行成功的話monitor里面程序那行進(jìn)程欄會(huì)顯示為綠色
接下來進(jìn)行調(diào)試,調(diào)試設(shè)置如下圖
設(shè)置完成點(diǎn)擊Attach to process...進(jìn)行附加程序調(diào)試,附加我們的程序即可
現(xiàn)在先找密鑰,而密鑰是RC4加密的異或操作下的變量,我們把斷點(diǎn)下在異或的指令上
f9斷到這個(gè)地方之后可以看見X2變量是有賦值的,我們利用trace跟蹤該變量,并將值都打印出來
import idc
print(idc.ger_reg_value('X2'),',',end='')
此處點(diǎn)擊運(yùn)行直接跳過,跳過后發(fā)現(xiàn)手機(jī)上能夠輸入了,這個(gè)時(shí)候輸入字符(字符個(gè)數(shù)可以往前看用frida工具h(yuǎn)ook出來的key數(shù)量)然后點(diǎn)√
感謝oacia師傅的提示,如果不點(diǎn)√就f9不會(huì)有輸入,程序會(huì)一直卡在第一個(gè)異或的密鑰上
上圖是第一個(gè)異或的密鑰,但是如果檢查下來發(fā)現(xiàn)密文和這個(gè)密鑰異或之后得不到輸入,重新檢查一下會(huì)發(fā)現(xiàn)還要異或一個(gè)0xff即可
addr = [14, 14, 68, 80, 29, 201, 241, 46, 197, 208, 123, 79, 187, 55, 234, 104, 40, 117, 133, 12, 67, 137, 91, 31, 136,
177, 64, 234, 24, 27, 26, 214, 122, 217]
key = [184,
132,
137,
215,
146,
65,
86,
157,
123,
100,
179,
131,
112,
170,
97,
210,
163,
179,
17,
171,
245,
30,
194,
144,
37,
41,
235,
121,
146,
210,
174,
92,
204,
22
]
flag = ""
for i in range(len(addr)):
flag += chr(addr[i] ^ 0xff ^ key[i])
print(flag)
4.本文知識(shí)點(diǎn)來源
[原創(chuàng)]flutter逆向 ACTF native app-Android安全-看雪-安全社區(qū)|安全招聘|kanxue.com
認(rèn)識(shí) Flutter 是什么?
403 Forbidden
一日一技|如何 root 一臺(tái) Pixel 手機(jī) - 少數(shù)派
windows下載安裝adb(極其簡(jiǎn)單)-CSDN博客
frida安裝正確流程
Flutter基建 - 按鈕全解析 - 掘金
表單交互 (Forms)
總結(jié)
以上是生活随笔為你收集整理的ACTF flutter逆向学习的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: “报错”是编程世界中,最简单的事情!
- 下一篇: OpenEuler22.03安装Post