| 基于Kali Linux
| htop
查看當(dāng)前活躍進(jìn)程
| jnettop
實(shí)時(shí)查看系統(tǒng)網(wǎng)絡(luò)負(fù)載工具
| 源碼閱讀:https://cs.android.com
| 源碼閱讀:http://aospxref.com
| 源碼閱讀:http://androidxref.com
| 源碼閱讀:https://www.androidos.net.cn/sourcecode
1. 刷機(jī)
2. Shell 常用命令
-
cat
查看文本文件內(nèi)容:cat 1.txt
-
touch
創(chuàng)建空文件 :touch a.txt
-
echo >
覆蓋寫(xiě)操作:echo "afra55" > a.txt
-
echo >>
擴(kuò)展寫(xiě)操作 -
grep
過(guò)濾符合條件的輸出:cat a.txt | grep afra
-
ps -e
打印全部進(jìn)程料滥,查看手機(jī)的全部進(jìn)程 -
ps
打印當(dāng)前進(jìn)程 -
netstat
查看對(duì)應(yīng)APP進(jìn)程的IP然眼、端口、協(xié)議等網(wǎng)絡(luò)信息:netstat -alpe grep org.myapp
-
lsof
查看對(duì)應(yīng)進(jìn)程打開(kāi)的文件:lsof -p 21212 -l
-
top
查看當(dāng)前活躍進(jìn)程葵腹,查看手機(jī)當(dāng)前運(yùn)行的進(jìn)程
3. adb 常用命令
描述 | 命令 |
---|---|
查看當(dāng)前處于前臺(tái)的Activity | adb shell dumpsys activity top |
打印當(dāng)前焦點(diǎn)窗口 | adb shell dumpsys window | grep mCurrentFocus |
打印包信息高每,四大組件MIME權(quán)限等 | adb shell dumpsys 包名 |
查看APPP的數(shù)據(jù)庫(kù)信息 | adb shell dumpsys dbinfo 包名 |
截圖保存到手機(jī) | adb shell screencap -p 路徑 |
截圖保存到電腦 | adb exec-out screencap -p > screen.png |
錄制屏幕 | adb shell screenrecord /sdcard/filename.mp4 |
在焦點(diǎn)輸入框內(nèi)輸入文字,無(wú)法輸入中文 | adb shell input test 文字 |
列出所有按照的APK包名 | adb shell pm list packages |
安裝手機(jī)里的APK文件践宴,uninstall 包名 用于卸載 |
adb shell pm install 安裝包路徑 |
啟動(dòng)APP的Activity鲸匿, -D 是DEBUG模式 |
adb shell am start-activity -D -N 包名/類(lèi)名 |
啟動(dòng)主Activity | adb shell monkey -p 包名 -c android.intent.category.LAUNCHER 1 |
查看手機(jī)系統(tǒng)架構(gòu) | adb shell getprop ro.product.cpu.abi |
查看手機(jī)型號(hào) | adb shell getprop ro.product.model |
查看電池信息 | adb shell dumpsys battery |
查看屏幕分辨率 | adb shell wm size |
查看屏幕密度 | adb shell wm density |
查看android_id
|
adb shell settings get secure android_id |
adb獲取藍(lán)牙MAC地址 | adb shell settings get secure bluetooth_address |
adb獲取IMEI | adb shell "service call iphonesubinfo 1 | toybox cut -d \"'\" -f2 | toybox grep -Eo '[0-9]' | toybox xargs | toybox sed 's/\ //g'" |
清除應(yīng)用數(shù)據(jù)&緩存 | adb shell pm clear 包名 |
獲取設(shè)備IP地址 | adb shell ip route | awk '{print $9}' |
啟用設(shè)備的網(wǎng)絡(luò) adb 功能 | adb tcpip 5555 |
網(wǎng)絡(luò)連接設(shè)備 | adb connect DEVICE_IP:5555 |
截圖 | adb shell screencap -p /sdcard/screenshot.png |
查看應(yīng)用安裝路徑, 該路徑下的apk可以pull下來(lái)使用 | adb shell pm path 包名 |
強(qiáng)制停止應(yīng)用 | adb shell am force-stop 包名 |
模擬按鍵輸入,見(jiàn)附表一 | adb shell input keyevent 按鍵代碼 |
向上滑動(dòng)手勢(shì)解鎖 | adb shell input swipe 300 1000 300 500 |
發(fā)送廣播阻肩,見(jiàn)附表二 | adb shell am broadcast -a <action> [-d ] [-t <mime_type>] [-c <category>] |
查看實(shí)時(shí)資源占用情況,見(jiàn)附表四 | adb shell top |
附表一:按鍵代碼
keycode | 含義 |
---|---|
3 | HOME 鍵 |
4 | 返回鍵 |
5 | 打開(kāi)撥號(hào)應(yīng)用 |
6 | 掛斷電話(huà) |
24 | 增加音量 |
25 | 降低音量 |
26 | 電源鍵 |
27 | 拍照(需要在相機(jī)應(yīng)用里) |
64 | 打開(kāi)瀏覽器 |
82 | 菜單鍵 |
85 | 播放/暫停 |
86 | 停止播放 |
87 | 播放下一首 |
88 | 播放上一首 |
122 | 移動(dòng)光標(biāo)到行首或列表頂部 |
123 | 移動(dòng)光標(biāo)到行末或列表底部 |
126 | 恢復(fù)播放 |
127 | 暫停播放 |
164 | 靜音 |
176 | 打開(kāi)系統(tǒng)設(shè)置 |
187 | 切換應(yīng)用 |
207 | 打開(kāi)聯(lián)系人 |
208 | 打開(kāi)日歷 |
209 | 打開(kāi)音樂(lè) |
210 | 打開(kāi)計(jì)算器 |
220 | 降低屏幕亮度 |
221 | 提高屏幕亮度 |
223 | 系統(tǒng)休眠 |
224 | 點(diǎn)亮屏幕 |
231 | 打開(kāi)語(yǔ)音助手 |
276 | 如果沒(méi)有 wakelock 則讓系統(tǒng)休眠 |
附表二:常見(jiàn)廣播意圖
adb shell am broadcast -a android.intent.action.BOOT_COMPLETED
action | 觸發(fā)時(shí)機(jī) |
---|---|
android.net.conn.CONNECTIVITY_CHANGE | 網(wǎng)絡(luò)連接發(fā)生變化 |
android.intent.action.SCREEN_ON | 屏幕點(diǎn)亮 |
android.intent.action.SCREEN_OFF | 屏幕熄滅 |
android.intent.action.BATTERY_LOW | 電量低带欢,會(huì)彈出電量低提示框 |
android.intent.action.BATTERY_OKAY | 電量恢復(fù)了 |
android.intent.action.BOOT_COMPLETED | 設(shè)備啟動(dòng)完畢 |
android.intent.action.DEVICE_STORAGE_LOW | 存儲(chǔ)空間過(guò)低 |
android.intent.action.DEVICE_STORAGE_OK | 存儲(chǔ)空間恢復(fù) |
android.intent.action.PACKAGE_ADDED | 安裝了新的應(yīng)用 |
android.net.wifi.STATE_CHANGE | WiFi 連接狀態(tài)發(fā)生變化 |
android.net.wifi.WIFI_STATE_CHANGED | WiFi 狀態(tài)變?yōu)閱⒂?關(guān)閉/正在啟動(dòng)/正在關(guān)閉/未知 |
android.intent.action.BATTERY_CHANGED | 電池電量發(fā)生變化 |
android.intent.action.INPUT_METHOD_CHANGED | 系統(tǒng)輸入法發(fā)生變化 |
android.intent.action.ACTION_POWER_CONNECTED | 外部電源連接 |
android.intent.action.ACTION_POWER_DISCONNECTED | 外部電源斷開(kāi)連接 |
android.intent.action.DREAMING_STARTED | 系統(tǒng)開(kāi)始休眠 |
android.intent.action.DREAMING_STOPPED | 系統(tǒng)停止休眠 |
android.intent.action.WALLPAPER_CHANGED | 壁紙發(fā)生變化 |
android.intent.action.HEADSET_PLUG | 插入耳機(jī) |
android.intent.action.MEDIA_UNMOUNTED | 卸載外部介質(zhì) |
android.intent.action.MEDIA_MOUNTED | 掛載外部介質(zhì) |
android.os.action.POWER_SAVE_MODE_CHANGED | 省電模式開(kāi)啟 |
附表三:系統(tǒng)屬性
屬性名 | 含義 |
---|---|
ro.build.version.sdk | SDK 版本 |
ro.build.version.release | Android 系統(tǒng)版本 |
ro.build.version.security_patch | Android 安全補(bǔ)丁程序級(jí)別 |
ro.product.model | 型號(hào) |
ro.product.brand | 品牌 |
ro.product.name | 設(shè)備名 |
ro.product.board | 處理器型號(hào) |
ro.product.cpu.abilist | CPU 支持的 abi 列表 |
persist.sys.isUsbOtgEnabled | 是否支持 OTG |
dalvik.vm.heapsize | 每個(gè)應(yīng)用程序的內(nèi)存上限 |
ro.sf.lcd_density | 屏幕密度 |
附表四:實(shí)時(shí)資源占用情況表描述
列名 | 含義 |
---|---|
PID | 進(jìn)程 ID |
PR | 優(yōu)先級(jí) |
CPU% | 當(dāng)前瞬間占用 CPU 百分比 |
S | 進(jìn)程狀態(tài)(R=運(yùn)行运授,S=睡眠,T=跟蹤/停止乔煞,Z=僵尸進(jìn)程) |
#THR | 線程數(shù) |
VSS | Virtual Set Size 虛擬耗用內(nèi)存(包含共享庫(kù)占用的內(nèi)存) |
RSS | Resident Set Size 實(shí)際使用物理內(nèi)存(包含共享庫(kù)占用的內(nèi)存) |
PCY | 調(diào)度策略?xún)?yōu)先級(jí)吁朦,SP_BACKGROUND/SPFOREGROUND |
UID | 進(jìn)程所有者的用戶(hù) ID |
NAME | 進(jìn)程名 |
3. Frida 環(huán)境
3.1 安裝 Frida
https://github.com/frida/frida
# frida --version
15.2.2
3.2 查看手機(jī)系統(tǒng)架構(gòu)
# adb shell getprop ro.product.cpu.abi
arm64-v8a
3.3 下載與安裝的Frida版本對(duì)應(yīng) frida-server
下載測(cè)試機(jī)系統(tǒng)架構(gòu)對(duì)應(yīng)的 frida-server
https://github.com/frida/frida/releases
frida-server-15.2.2-android-arm64.xz
3.4 講 frida-server 推送到手機(jī)
# 7z x frida-server-15.2.2-android-arm64.tar.xz
# adb push frida-server-15.2.2-android-arm64 /data/local/tmp/
# adb shell
# su
# cd /data/local/tmp
# chmod 777 frida-server-15.2.2-android-arm64
3.5 啟動(dòng) frida-server
# adb shell
# su
# cd /data/local/tmp
# ./frida-server-15.2.2-android-arm64
4 Frida 腳本智能提示
基于Node和NPM環(huán)境。
安裝 nodejs: https://nodejs.org/en/download/package-manager
推薦使用三方包管理器安裝:https://github.com/nodesource/distributions#installation-instructions
4.1 使用Frida示例項(xiàng)目
# git clone https://github.com/oleavr/frida-agent-example
# cd frida-agent-example
# npm install
使用vscode等IDE打開(kāi)此工程渡贾,在agent
文件夾下編寫(xiě)JavaScript逗宜,會(huì)有智能提示。
4.2 使用 npm 包 frida-gum
在系統(tǒng)里裝上這個(gè)這個(gè)npm包(https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/frida-gum)空骚,可以在任意工程獲得frida的代碼提示纺讲、補(bǔ)全和API查看。
npm i -g @types/frida-gum
5 Frida 注入命令
5.1 USB 注入
查看進(jìn)程
# frida-ps -U
注入腳本:
# frida -U 進(jìn)程名 -l 腳本路徑.js
或直接對(duì)當(dāng)前頂層應(yīng)用注入腳本:
# frida -UF -l 腳本路徑.js
加上 -f
參數(shù)則將啟動(dòng)App的權(quán)利交由Frida來(lái)控制囤屹,即使目標(biāo)App已經(jīng)啟動(dòng)刻诊,在使用Frida注入程序時(shí)還是會(huì)重新啟動(dòng)App.
# frida -U -f 進(jìn)程名 -l hook.js
--no-pause
是 Frida 的一個(gè)參數(shù),用于在啟動(dòng)時(shí)禁止自動(dòng)暫停目標(biāo)進(jìn)程牺丙。默認(rèn)情況下则涯,F(xiàn)rida 會(huì)在注入到目標(biāo)進(jìn)程后自動(dòng)暫停該進(jìn)程,以便用戶(hù)可以執(zhí)行進(jìn)一步的操作冲簿,比如在運(yùn)行時(shí)修改內(nèi)存或進(jìn)行調(diào)試粟判。使用 --no-pause
參數(shù)可以禁止這種自動(dòng)暫停行為,使目標(biāo)進(jìn)程繼續(xù)正常運(yùn)行峦剔。這在某些場(chǎng)景下可能很有用档礁,例如當(dāng)你只需要監(jiān)視應(yīng)用程序的行為而無(wú)需進(jìn)行交互式的調(diào)試時(shí)。
# frida -U -f 進(jìn)程名 -l hook.js --no-pause
5.2 網(wǎng)絡(luò)模式注入
5.2.1 安裝 Termux
可以在手機(jī)上執(zhí)行l(wèi)inux命令
https://github.com/termux/termux-app#installation
5.2.2 frida-server 使用網(wǎng)絡(luò)模式進(jìn)行監(jiān)聽(tīng)
在手機(jī)上執(zhí)行命令吝沫,打開(kāi) Termux:
# su
# cd /data/local/tmp/
# ./frida-server-15.2.2-android-arm64 -l 0.0.0.0:8888
或者直接在電腦上執(zhí)行也行呻澜,網(wǎng)絡(luò)模式一般用來(lái)分析那些禁止USB鏈接的應(yīng)用。
查看 frida-service 監(jiān)聽(tīng)的端口:
# netstat -tulp | grep frida
tcp 0 0 0.0.0.0:8888 0.0.0.0:* LISTEN 14541/frida-server-15.2.2-android-arm64
5.2.3 Frida網(wǎng)絡(luò)注入
# frida -H 192.168.0.107:8888 -l test.js FridaTest
使用參數(shù) -H
傳入測(cè)試機(jī)的IP和端口惨险,即可進(jìn)行網(wǎng)絡(luò)設(shè)備注入羹幸。
6 Frida腳本基礎(chǔ)
test.js
function main(){
Java.perform(function(){
console.log("任何對(duì)APP的JAVA層的操作,都要寫(xiě)在這個(gè)匿名函數(shù)里面")
// 獲取對(duì)應(yīng)類(lèi)的JavaScript對(duì)象
var Example = Java.use('com.example.Example')
// new 了一個(gè) Java Stirng 字符串
var JavaString = Java.use('java.lang.String').$new('122')
// Hook 重載 類(lèi)Example 的方法辫愉,在該方法調(diào)用的時(shí)候栅受,會(huì)觸發(fā)匿名函數(shù),可不加overload恭朗,fraida報(bào)錯(cuò)信息會(huì)提示是否應(yīng)該加上參數(shù)信息
Example.方法名.overload('java.lang.String', 'java.lang.String').implementation = function(str, str2){
// 傳入?yún)?shù)屏镊,獲取結(jié)果,可以自行修改傳入?yún)?shù)
var result = this.方法名(JavaString, JavaString.$new('123'))
console.log('str, str2, result: ', str, str2, result)
// 打印調(diào)用堆棧信息
console.log(Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Throwable").$new()))
return result // 返回結(jié)果痰腮,可以自行修改返回結(jié)果
}
// 主動(dòng)調(diào)用類(lèi) Example 的靜態(tài)方法
var subResult = Example.靜態(tài)方法名(JavaString.$new("6"), JavaString.$new("7"))
// 主動(dòng)調(diào)用 Example 的內(nèi)部方法和變量
Java.choose('com.example.Example', {
onMatch:function(instance){
console.log("變量值", instance.變量名.value)
// 調(diào)用內(nèi)部方法
instance.方法名()
},onComplete:function(){
console.log("動(dòng)態(tài)調(diào)用成功")
}
})
console.log(subResult)
})
}
setImmediate(main) // 注入后立即執(zhí)行 main函數(shù)
// setTimeout(main, 100) // 注入后而芥,100ms后再執(zhí)行 main函數(shù)
7 RPC 及Python自動(dòng)化
https://github.com/frida/frida-python
在 js 腳本末尾添加 rpc.exports
用于導(dǎo)出函數(shù),注意導(dǎo)出函數(shù)名必須小寫(xiě):
rpc.exports = {
callmain:main,
getfun:getNumber
}
上面導(dǎo)出了2個(gè)函數(shù)膀值,使得外部可以調(diào)用棍丐。
loader.py
import frida, sys, time
def on_message(message, data):
if message['type'] == 'send':
print("[*] {0}".format(message['payload']))
else:
print(message)
# 獲得USB句柄,
devices = frida.get_usb_device()
# 可以添加多個(gè)網(wǎng)絡(luò)設(shè)備
# devices = frida.get_usb_device().add_remote_device('192.168.0.107:8888')
# spawn 方式注入
# pid = devices.spawn(["進(jìn)程名"])
# devices.resume(pid) # 喚起進(jìn)程
# time.sleep(1)
# process = devices.attach(pid)
# attach 方式進(jìn)程注入
process = devices.attach('進(jìn)程名')
# 加載腳本代碼
with open('test.js') as f:
jscode = f.read()
script = process.create_script(jscode)
# 注冊(cè)信息打印函數(shù)
script.on('message', on_message)
script.load()
command = ""
while 1==1:
command = input("\nEnter:\n1:exit\n2:call\n3:get\nchoice:")
if command == "1":
break
elif command == "2":
script.exports.callmain() # 調(diào)用腳本方法
elif command == "3":
script.exports.getfun()
執(zhí)行該P(yáng)ython即可弟翘。
8 Objection 安裝
Objection 可以快速搜索內(nèi)存,搜索類(lèi)骄酗,Hook方法稀余,打印參數(shù)返回值調(diào)用棧,不寫(xiě)一行腳本就能進(jìn)行APP分析趋翻。
https://github.com/sensepost/objection
9 Objection 常用命令
注入后睛琳,把要HOOK的功能都觸發(fā)一次。
9.1 注入
# objection -g 包名 explore
9.2 列出內(nèi)存所有的類(lèi)
# android hooking list classes
9.3 搜索包含關(guān)鍵詞的類(lèi)
# android hooking search classes 關(guān)鍵詞
9.4 搜索包含關(guān)鍵詞的方法
# android hooking search methods 關(guān)鍵詞
9.5 查看指定類(lèi)的所有方法
# android hooking list class_methods 完整類(lèi)名
9.6 列出注入進(jìn)程的所有 Activity
# android hooking list activities
9.7 列出注入進(jìn)程的所有 services
# android hooking list services
9.8 HOOK 指定方法
# android hooking watch class_method 方法名 --dump-args --dump-backtrace --dump-return
9.9 查看當(dāng)前正在HOOK的作業(yè)信息
# jobs list
9.10 移除HOOK
# jobs kill 作業(yè)ID
9.11 啟動(dòng)Activity
# android intent launch_activity Activity名
9.12 搜索實(shí)例類(lèi)似 Java.use
# android heap search instance 類(lèi)名
9.13 執(zhí)行無(wú)參實(shí)例方法
# android heap execute 實(shí)例Handle 方法名
9.14 執(zhí)行有參實(shí)例方法
# android heap evaluate 實(shí)例Handle
clazz.方法名(參數(shù)...)
9.15 執(zhí)行靜態(tài)方法
TODO
9.16 使用插件Wallbreaker
打印相應(yīng)類(lèi)的具體內(nèi)容
需要使用Objection的插件 https://github.com/hluwa/wallbreaker踏烙,這個(gè)插件可以打印類(lèi)的具體內(nèi)容师骗,比如靜態(tài)成員實(shí)例成員的值,及所有函數(shù)讨惩。>
下載&安裝:
# git clone https://github.com/hluwa/wallbreaker ~/.objection/plugins/Wallbreaker
注入時(shí)使用-P加載插件即可:
# objection -g 包名 explore -P ~/.objection/plugins/
或者在注入后辟癌,再進(jìn)行加載使用 :
# plugin load /root/.objection/plugins/Wallbreaker/
# plugin wallbreaker objectsearch java.util.HashMap
# plugin wallbreaker objectdump <object-handle>
示例,打印系統(tǒng)主要API接口:
# objection -g com.android.settings explore
# plugin load /root/.objection/plugins/Wallbreaker/
# plugin wallbreaker classdump android.os.Build
9.17 ZenTracer
有界面的HOOK工具荐捻,更方便便捷黍少。
https://github.com/hluwa/ZenTracer
10 Objection 網(wǎng)絡(luò)模式
開(kāi)啟測(cè)試機(jī)的 frida-server 網(wǎng)絡(luò)模式監(jiān)聽(tīng),詳見(jiàn)5.2处面。
使用 -N 參數(shù)進(jìn)行網(wǎng)絡(luò)模式連接:
# objection -N -h 192.168.0.107 -p 8888 -g 包名 explore
11 脫殼
11.1 FRIDA-DEXDump
這個(gè)工具可以從內(nèi)存中搜索和dump符合條件的dex文件厂置,當(dāng)然VMP殼時(shí)脫不了的,只能脫1代殼魂角。
11.1.1 安裝插件
https://github.com/hluwa/frida-dexdump#frida-dexdump
這里作為Objection插件來(lái)使用:
# pip3 install frida-dexdump
11.1.2 脫殼&重打包
推薦使用 -d
模式昵济,開(kāi)啟深度搜索模式。
# frida-dexdump -U -f 包名 -d
或
# frida-dexdump -FU -d
等待一段時(shí)間野揪,完成脫殼访忿,記得脫殼前先玩玩APP。
classes.dex
classes02.dex
classes03.dex
classes04.dex
classes05.dex
可以使用gerp
定位關(guān)鍵類(lèi)所在的dex:
grep -ril "關(guān)鍵詞" ./*.dex
11.1.3 使用 apktool 重打包
https://github.com/iBotPeaches/Apktool/tree/docs
還是
MT管理器
方便斯稳,推薦使用
反編譯APK但不反編譯 dex, 加-s
命令即可:
# apktool d 包名 -s
將反編譯后的dex刪除海铆。
把脫殼后的class重命名并放入反編譯后的文件里:
classes.dex
classes2.dex
classes3.dex
classes4.dex
classes5.dex
重要的一點(diǎn)時(shí),脫殼后的Applicaiton入口變了平挑,需要找到脫殼后的Application游添,
# grep -ril "Application" ./*.dex
# grep -ril "android.app.Application" ./*.dex
# grep -ril "onCreate()" ./*.dex
找到關(guān)鍵 dex系草,反編譯后查找 extends Application
即可找到真正的Applicaiton通熄。
在清單文件中替換 application 節(jié)點(diǎn)的name即可。
重新編譯:
# apktool b 反編譯的文件夾
重新編譯的APK在反編譯目錄下的dist文件夾找都。
創(chuàng)建簽名文件:
# keytool -genkey -alias 別名 -keyalg RSA -validity 2000 -keystore test.jks
進(jìn)行簽名:
jarsigner -verbose -keystore 簽名文件 -signedjar 簽名后的.apk 等待簽名的.apk 別名
11.2 FRIDA-FART
https://github.com/hanbinglengyue/FART
這個(gè)工具用于脫二代抽取型加固殼唇辨。
12 Charles 抓包 (ROOT環(huán)境)
12.1 下載并安裝
https://www.charlesproxy.com/download/
12.2 手機(jī)安裝證書(shū)
手機(jī)配置代理后打開(kāi)網(wǎng)頁(yè)chls.pro/ssl
,下載并安裝用戶(hù)證書(shū)能耻。
12.3 將用戶(hù)證書(shū)變成系統(tǒng)證書(shū)
# adb shell
# su
# cd /data/misc/user/0/cacerts-added/
# mount -o remount,rw /system
# cp * /etc/security/cacerts
# chmod 777 /etc/security/cacerts/*
# mount -o remount,ro /system
# reboot
12.4 配置SOCKS5
移除手動(dòng)配置的代理赏枚,安裝應(yīng)用Postern并配置 SOCKS5協(xié)議亡驰,打開(kāi)Charles的 SOCKS 協(xié)議,端口號(hào)要和 HTTP協(xié)議不一樣饿幅。
13 HOOK關(guān)鍵詞OkHttp
抓包
13.1 OkHttp未被混淆
清空 Objection 日志:
# rm ~/.objection/objection.log
注入APP:
# objection -g 包名 explore
獲取APP已經(jīng)加載的所有類(lèi):
# android hooking list classes
退出確保日志已經(jīng)存儲(chǔ):
# exit
復(fù)制日志文件到其他目錄:
# cp ~/.objection/objection.log ./
過(guò)濾網(wǎng)絡(luò)相關(guān)的類(lèi), 并保存到文件中, 可以先掃描再使用符號(hào)重定向:
# cat objection.log | grep -i HttpURLConnection > HttpURLConnection.txt
# cat objection.log | grep -i okhttp > okhttp.txt
# cat objection.log | grep -i okhttp3 > okhttp3.txt
使用VIM再每行行首添加Hook命令:
# :%s/^/android hooking watch class /
保存并退出:
# :wq
注入并批量執(zhí)行HOOK命令:
# objection -g 包名 explore -c "./okhttp.txt"
查看相關(guān)函數(shù), 退出 Objection凡辱,然后再對(duì)該函數(shù)進(jìn)行HOOK:
# android hooking watch class_method 函數(shù)名 --dump-args --dump-backtrace --dump-return
就能找到調(diào)用的具體位置, 再對(duì)調(diào)用函數(shù)進(jìn)行HOOK栗恩。
13.2 OkHttp 被混淆了
https://github.com/siyujie/okhttpLogger-Frida
該項(xiàng)目使用了OkHttp3框架的特征去驗(yàn)證OkHtt3是否被使用了透乾,而不是直接搜所關(guān)鍵詞。
下載項(xiàng)目磕秤。
將 okhttpfind.dex
拷貝到 /data/local/tmp/
目錄下乳乌,并提升權(quán)限。
# adb push okhttpfind.dex /data/local/tmp/
# su
# chmod 777 /data/local/tmp/okhttpfind.dex
執(zhí)行命令啟動(dòng)frida -U -l okhttp_poker.js -f com.example.demo --no-pause
可追加 -o [output filepath]
保存到文件市咆。
或者打開(kāi)應(yīng)用到前臺(tái)執(zhí)行注入命令:frida -U -l okhttp_poker.js -F --no-pause
汉操。
執(zhí)行find()
方法。
如果提示方法未找到蒙兰,則修改腳本直接執(zhí)行 find()
磷瘤。
將 Find Complete
里的內(nèi)容覆蓋到腳本里的對(duì)應(yīng)參數(shù)。
再次注入執(zhí)行hold()
方法搜变,就會(huì)輸出所有的請(qǐng)求信息膀斋。
13.3 Frida 動(dòng)態(tài)注入 Dex
通過(guò)如下API即可動(dòng)態(tài)加載DEX到內(nèi)存中,使用我們自己的類(lèi)和方法:
Java.openClassFile("/data/local/tmp/HttpLoggingInter").load()
示例:OkHttp3 提供了日志打印庫(kù):
implementation("com.squareup.okhttp3:logging-interceptor")
但分析的APP使用了OkHttp3痹雅,而且沒(méi)有加日志打印庫(kù)的時(shí)候仰担,可以進(jìn)行dex動(dòng)態(tài)注入,自己寫(xiě)一個(gè)dex绩社,來(lái)加載APP里沒(méi)有的類(lèi)庫(kù)摔蓝。
一般OkHttp3是這樣加載日志打印攔截器的:
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
new OkHttpClient.Builder()
.addNetworkInterceptor(interceptor)
.build();
寫(xiě)一個(gè)空Android項(xiàng)目,添加該類(lèi)庫(kù)愉耙,并運(yùn)行起來(lái)贮尉。
在 app/build/intermediates/apk/debug
找到生成的APK,并解壓縮朴沿。
通過(guò)下面的命令找到類(lèi)庫(kù)所在的dex文件猜谚。
# grep -ril "HttpLoggingInterceptor" ./*.dex
將其推送至/data/local/tmp
目錄下:
adb push HttpLoggingInterceptor.dex /data/local/tmp/
編寫(xiě)Frida腳本:
function main(){
Java.perform(function(){
// 加載我們的dex文件
Java.openClassFile("/data/local/tmp/HttpLoggingInterceptor.dex").load();
var HttpLoggingInterceptor = Java.use("okhttp3.logging.HttpLoggingInterceptor");
var HttpLoggingInterceptorObj = HttpLoggingInterceptor.$new();
var Level = Java.use("okhttp3.logging.HttpLoggingInterceptor$Level");
// 設(shè)置枚舉值BODY,另OkHttp3打印所有日志
HttpLoggingInterceptorObj.setLevel(Level.BODY.value);
var Builder = Java.use("okhttp3.OkHttpClient$Builder");
Builder.build.implementation = function(){
this.networkInterceptors().add(HttpLoggingInterceptorObj);
console.log("add network interceptor");
return this.build();
};
console.log("hook okhttp3 log");
})
}
setImmediate(main)
執(zhí)行命令使用Spawned模式, 從APP啟動(dòng)的時(shí)候赌渣,就開(kāi)始HOOK注入:
# frida -U -f 進(jìn)程名 -l 腳本.js --no-pause
這時(shí)APP進(jìn)行網(wǎng)絡(luò)請(qǐng)求時(shí)魏铅,即可看到所有信息。
14. HOOK 應(yīng)用證書(shū)文件
保存證書(shū)到 sdcar里:
function hook_KeyStore_load() {
Java.perform(function () {
var myArray=new Array(1024);
var i = 0
for (i = 0; i < myArray.length; i++) {
myArray[i]= 0x0;
}
var buffer = Java.array('byte',myArray);
var StringClass = Java.use("java.lang.String");
var KeyStore = Java.use("java.security.KeyStore");
KeyStore.load.overload('java.security.KeyStore$LoadStoreParameter').implementation = function (arg0) {
console.log(Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Throwable").$new()));
console.log("KeyStore.load1:", arg0);
this.load(arg0);
};
KeyStore.load.overload('java.io.InputStream', '[C').implementation = function (arg0, arg1) {
console.log(Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Throwable").$new()));
console.log("KeyStore.load2: filename = ", arg0,',password = ', arg1 ? StringClass.$new(arg1) : null);
if (arg0){
var filename = "/sdcard/Download/"+ String(arg0)
var file = Java.use("java.io.File").$new(filename);
var out = Java.use("java.io.FileOutputStream").$new(file);
var r;
while( (r = arg0.read(buffer)) > 0){
out.write(buffer,0,r)
}
console.log('save_path = ',filename,", cert save success!")
out.close()
}
this.load(arg0, arg1);
};
console.log("hook_KeyStore_load...");
});
}
function main(){
hook_KeyStore_load()
}
setImmediate(main);
導(dǎo)出證書(shū)后坚芜,可使用 KeyStore Explorer 工具轉(zhuǎn)換證書(shū)格式览芳,以便導(dǎo)入到 Charles中。
如果API使用了非標(biāo)準(zhǔn)HTTPS端口鸿竖,還要手動(dòng)配置該端口為HTTP數(shù)據(jù)包沧竟。
15 安卓應(yīng)用層明文協(xié)議抓包通殺腳本 r0capture
https://github.com/r0ysue/r0capture
16. Java類(lèi)追蹤腳本 r0tracer
- 根據(jù)黑白名單批量追蹤類(lèi)的所有方法
- 在命中方法后打印出該類(lèi)或?qū)ο蟮乃杏蛑抵簟?shù)、調(diào)用棧和返回值
- 極簡(jiǎn)的文本保存日志機(jī)制悟泵、易于搜索關(guān)鍵參數(shù)
- 針對(duì)加殼應(yīng)用找不到類(lèi)時(shí)可以切換Classloader