Mac IDA動態調試Android應用dump dex

前言

由於本人使用的是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

  1. 上傳IDA調試服務器地址:IDAPro70\dbgsrv\android_server
  2. cmd進入到該目錄下: IDAPro70\dbgsrv
  3. 導入IDA調試服務器:adb push android_server /data/local/tmp
  4. adb shell 以su啓動(手機要求root)
  5. cd到/data/local/tmp下:chmod 777 android_server
  6. ./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 -r

3、 轉發ida端口 開啓adb應用調試

adb forward tcp:23946 tcp:23946
adb shell am start -D -n 包名/包名對應啓動Activity

4、 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=localhost

6 IDA開啓調試

啓動ida F9 開始進行調試

大致原理

通過IDA的動態調試系統庫libdvm.so的dvmDexFileOpenPartial方法,來尋找內存中的dex段地址,然後進行dump,最終達到脫殼的目的。
(4.4前後的不同java虛擬機類型,所以這裏用的是4.4.2的手機,系統庫爲libdvm,如果是之後的便是libart,調試方法爲openMemory)

詳細過程

看似原理很簡單,但是會遇到許多的問題和坑,每個都能卡你半天,所以這裏分享給大家一些細節東西,望君莫要重蹈覆轍。

1、 copy 啓動 Android server
  1. 上傳IDA調試服務器地址:IDAPro70\dbgsrv\android_server
  2. cmd進入到該目錄下: IDAPro70\dbgsrv
  3. 導入IDA調試服務器:adb push android_server /data/local/tmp
  4. adb shell 以su啓動(手機要求root)
  5. cd到/data/local/tmp下:chmod 777 android_server
  6. ./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來過了一遍手,而後在想要脫殼的時候,卻遇到了更多的問題,總之,初來乍到,還要繼續學習和探索,有志同道合者,希望相互交流。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章