前言
由於本人使用的是Mac來做開發,並且最近要做逆向相關,苦於網上多數教程都是Win的,沒辦法只有到處蒐集資料和自己踩坑,摸着石頭過河。這裏分享一下Mac來做的整個過程。目標,IDA動態調試,dump dex脫殼。
脫殼的話,目前兩種方法,一種動態調試,一種xposed,當前爲動態調試學習
環境:
macOS 10.14.1
root過後的手機 htc 4.4.2
IDA 7.0 附送地址
IDA mac 高版本崩潰解決適配
mprop 設置手機所有應用爲可調試 下載地址
精簡方案
1、 copy 啓動 Android server
- 上傳IDA調試服務器地址:IDAPro70\dbgsrv\android_server
- cmd進入到該目錄下: IDAPro70\dbgsrv
- 導入IDA調試服務器:adb push android_server /data/local/tmp
- adb shell 以su啓動(手機要求root)
- cd到/data/local/tmp下:chmod 777 android_server
- ./android_server(如果失敗重啓手機)
2、 root手機使用mprop設置ro.debuggable爲1
adb push xxx/mprop /data/local/tmp/mprop
adb shell su
chmod 755 /data/local/tmp/mprop
data/local/tmp/mprop
setprop ro.debuggable 1
/data/local/tmp/mprop -r3、 轉發ida端口 開啓adb應用調試
adb forward tcp:23946 tcp:23946
adb shell am start -D -n 包名/包名對應啓動Activity4、 ida attach到應用進程 打斷點
打開IDA設置好process options 地址127.0.0.1 端口23946
Ida -》debugger -》attach process
選擇對應應用進程
選擇libdvm.so
找到dvmDexFileOpenPartial 計算偏移量
下斷點5、 jdb連接應用
連接jdb(兩種方式)
1、通過ddms(如果佔用8700 ps查看 kill殺掉 重來)
2、命令
adb shell ps | xxx 找到對應app的進程號
adb forward tcp:8700 jdwp:進程號
jdb -connect com.sun.jdi.SocketAttach:port=8700,hostname=localhost6 IDA開啓調試
啓動ida F9 開始進行調試
大致原理
通過IDA的動態調試系統庫libdvm.so的dvmDexFileOpenPartial方法,來尋找內存中的dex段地址,然後進行dump,最終達到脫殼的目的。
(4.4前後的不同java虛擬機類型,所以這裏用的是4.4.2的手機,系統庫爲libdvm,如果是之後的便是libart,調試方法爲openMemory)
詳細過程
看似原理很簡單,但是會遇到許多的問題和坑,每個都能卡你半天,所以這裏分享給大家一些細節東西,望君莫要重蹈覆轍。
1、 copy 啓動 Android server
- 上傳IDA調試服務器地址:IDAPro70\dbgsrv\android_server
- cmd進入到該目錄下: IDAPro70\dbgsrv
- 導入IDA調試服務器:adb push android_server /data/local/tmp
- adb shell 以su啓動(手機要求root)
- cd到/data/local/tmp下:chmod 777 android_server
- ./android_server(如果失敗重啓手機)
這裏啓動之後 可以看到IDA Android 32-bit remote debug server(ST) v1.22. Hex-Rays (c) 2004-2017
注意:這裏32-bit的話,你打開IDA就用32位的打開 不然就是64位的
2、 root手機使用mprop設置ro.debuggable爲1
adb push xxx/mprop /data/local/tmp/mprop
adb shell su
chmod 755 /data/local/tmp/mprop
data/local/tmp/mprop
setprop ro.debuggable 1
/data/local/tmp/mprop -r
使用getprop ro.debuggable 就可以查看是否修改成功
有時候遇到
android_server Address already in use
可以殺掉進程重來
進入adb shell
ps | grep android_server
kill -s 9 進程號
重新啓動android_server
注意:手機每次重啓都要重複此操作,都要重新設置debuggable爲1,有時候手機會無意重啓,注意。
3、 轉發ida端口 開啓adb應用調試
adb forward tcp:23946 tcp:23946
adb shell am start -D -n 包名/包名對應啓動Activity
這裏轉發了之後可以使用lsof -i:23946
來查看如果有Listen則說明轉發成功
接着調用adb 調試命令 填好對應包名和啓動的Activity注入調試
這裏提供一下 查詢啓動頁的方法
adb shell dumpsys activity top 啓動app之後查看現在的Activity信息可以拿到包名
然後
adb shell dumpsys package 包名
就可以查詢一下有action MAIN的Activity,一般類似爲SplashActivity
注入調試,手機上就有等待調試的彈框了。
4、 ida attach到應用進程 打斷點
打開IDA設置好process options 地址127.0.0.1 端口23946
Ida -》debugger -》attach process
選擇對應應用進程
選擇libdvm.so
找到dvmDexFileOpenPartial 計算偏移量
下斷點
這裏我們使用的是32位的IDA打開,一般要開兩個,一個爲了靜態分析so(也就是找到libdvm.so的對應的dexFileOpen函數地址,後面要做尋找斷點用);另外一個是拿來調試用的。
首先,需要獲取libdvm.so,一般是在手機的/system/lib/ 下面
adb pull /system/lib/libdvm.so /users/jafir/desktop/
直接pull到電腦上來,然後IDA打開
0004BB10
這個地址就是dexFileOpen函數在libdvm.so中的偏移地址,後面我們打斷點的時候,需要在整個內存中去尋找到真正的dexFileOpen的地址。
原理就是 找到libdvm.so在內存中的首地址,然後加上這裏的偏移地址,就可以得到libdvm.so中的dexFileOpen的地址。
好,這就是靜態分析獲取地址。
然後,再打開一個,File->New Instance,選擇 GO
Debugger->Attach->Remote ArmLinux/Android
接下來就ctrl+s找到libdvm.so然後查看,它在內存中的首地址,計算偏移量
計算一下偏移量 4152D000+ 0004BB10 = 41578b10,按G,進行地址跳轉
打上斷點
ok
5、 jdb連接應用
連接jdb(兩種方式)
1、通過ddms(如果佔用8700 ps查看 kill殺掉 重來)
2、命令
(-- adb shell ps | xxx 找到對應app的進程號
-- adb forward tcp:8700 jdwp:進程號)
jdb -connect com.sun.jdi.SocketAttach:port=8700,hostname=localhost
最簡單的打開ddms,它是在你Android sdk/tools下面的monitor
然後jdb -connect com.sun.jdi.SocketAttach:port=8700,hostname=localhost
(base) Jafir:~ jafir$ jdb -connect com.sun.jdi.SocketAttach:hostname=localhost,port=8700
設置未捕獲的java.lang.Throwable
設置延遲的未捕獲的java.lang.Throwable
正在初始化jdb...
>
如果打開DDMS報8700被佔用了,lsof -i :端口號
查看,然後kill -s 9 進程號
殺掉,重來
(base) Jafir:~ jafir$ lsof -i:8700
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
monitor 31587 jafir 121u IPv6 0x8c41b253ec7cd357 0t0 TCP localhost:8700 (LISTEN)
(base) Jafir:~ jafir$ kill -s 9 31587
如果不用ddms,也可以用命令,來連接jdb
adb shell ps | xxx包名 找到對應app的進程號
adb forward tcp:8700 jdwp:進程號
jdb -connect com.sun.jdi.SocketAttach:port=8700,hostname=localhost
6 IDA開啓調試
啓動ida F9 開始進行調試
點擊綠色啓動按鈕,就可以了,這時候按道理,手機的debug等待框也消失了,進入調試狀態。
ddms的燈變成綠色,然後斷點斷在了libc上頭,就成功了
之後便是一路F9,回車。F9,回車
直到我們的斷點處。
注意斷點,向下執行,不要超過BL,過了PUSH就可以了
到斷點處,如果成功的話,就可以從General registers裏面看到變量值。
static main(void){
auto fp, dex_addr,end_addr;
//打開或創建一個文件
fp = fopen("/users/jafir/desktop/dump.dex", "wb");
end_addr = r0+r1;
for ( dex_addr = r0; dex_addr < end_addr; end_addr ++ ){
//按字節將其dump到本地文件中
fputc(Byte(dex_addr), fp);
}
}
File->Script Command可以創建腳本命令
過一會就可以看到桌面上dump.dex文件了。
後面還會遇到很多坑:
命令相關分享
進程相關:
ps A 查看所有
ps a 顯示同一終端下的所有程序
lsof -i:xxx 查看端口進程信息
kill -9 xxxx 殺死某個進程逆向相關命令:
cat 查看
cat /proc/xxxpid/maps 查看xxx進程的lib庫文件(一般需要root才能查看)
echo touch 寫內容到文件中
echo 內容 >> 文件路徑 (如果有文件就追加 沒有就創建)
echo 內容 >文件路徑 (如果有文件就清空寫入 沒有就創建)
adb shell dumpsys activity top
adb shell dumpsys package [packagename]
adb shell dumpsys meminfo xxxx com.cctv4g.cctvmobiletv
adb shell dumpsys dainfo xxx
adb shell screencap -p xxx路徑
adb install -t xxx 以測試包的類型安裝查看當前的activity:
1、adb shell dumpsys activity activities | sed -En -e '/Running activities/,/Run #0/p'
2、adb shell dumpsys activity | grep -i run查看權限的命令:
ls -alf 查看文件及其權限
ls -a 可以查看包含隱藏文件
ls 查看查看keystore的信息摘要 sha1
keytool -list -keystore keystore
jadx-gui:
jadx-gui xxx.jar/xxxx.dex/xxx.apk
配置好環境變量Dx:
dx --dex --output=HelloWorld.dex HelloWorld.class
把class文件編譯成dex執行dex文件
1、生成dex文件(可以直接從apk中解壓出來,也可以從jar利用dx命令生成)
2、然後adb push xxx.dex xxx到手機中去
3、adb shell
4、dalvikvm -cp xxx.dex com.jafir.signprotect.Main(主類)
後記
本人也是剛入手,小白一個,摸索着石頭過河,請教過很多大神,但是不管怎麼說還是要自己動手,踩坑,嘗試,無數次嘗試。
這裏只進行到dump dex,其實後面還有很多的操作,比如什麼指令抽取的要還原啊,還要過濾反調試等的。
我只是用了自己的沒有反調試的apk來過了一遍手,而後在想要脫殼的時候,卻遇到了更多的問題,總之,初來乍到,還要繼續學習和探索,有志同道合者,希望相互交流。