安卓應用加固之反動態調試技術總結


0x00 前言

動態調試是比靜態分析更為高效地一種破解手段。因此在破解安卓應用之前,一般會先對應用進行動態調試,了解應用大致運行流程和各個類之間的邏輯關系。

反動態調試可以從以下兩個個方向着手:

1.運行環境檢測:檢測應用的運行環境是否安全,是否可能存在被調試的風險

2.動態調試指令檢測:檢測應用的運行過程中是否受到動態調試指令的控制

 

本文完全參考自網友  愛吃菠菜  的反調試總結,由於我的資料是pdf文檔,已經找不到出處,在此對網友 愛吃菠菜 說一聲抱歉。

 

0x01 運行環境檢測

1.調試端口檢測

不同調試器默認使用不同的調試端口,且這些端口默認值往往不被修改。

 

2.調試器進程檢測

不同調試器會在系統中創建不同進程對應用進行劫持以達到動態調試目的。

 

3.父進程名檢測

針對so文件,破解者可以自己編寫一個APK對so庫進行調試。

(1)正常啟動的apk程序:父進程是zygote
(2)調試啟動的apk程序:在AS中用LLDB調試發現父進程還是zygote
(3)附加調試的apk程序:父進程是zygote
(4)vs遠程調試 用可執行文件加載so:父進程名為gdbserver
父進程名非zygote的,判定為調試狀態。
 

4.自身進程名檢測

原理同上條。正常的APK進程名一般為入口類的目錄。形如:com.xxx.xxx.xxxx.xxxMainActivity。在開發時,該值是已知的,因此可對該值進行檢測。

 

5.apk線程檢測

正常APK運行時一般會有多個線程在運行,可以在開發階段分析自己的源碼,正常運行時至少會有多少線程同時運行。針對如果破解者仍是自己編寫APK調用so庫調試分析的情況,此時的APK中一般只有一條線程。

 

6.apk進程fd文件檢測

分析系統中/ proc/pid/fd路徑下的文件差異進行判斷。

1)APK本身啟動的進程和非APK啟動的進程,fd數量不一樣

2)APK正常啟動和APK動態調試啟動,進程fd數量也不一樣

 

7.安卓系統自帶的動態調試檢測函數

android.os.Debug.isDebuggerConnected();

 

8.tracepid

/proc/pid/status文件中有一個tracepid字段,若進程被調試,則tracepid值不為0,否則為0。可以對該值進行檢測以判斷該進程是否被調試。

可以將statue字段寫為t,停止調試

 

10.stat

如果是被調試狀態,則

/proc/pid/stat

/proc/pid/task/pid/stat

第二個字段是t(T)

 

11.wchan

/proc/pid/wchan

/proc/pid/task/pid/wchan

ptrace_stop

 

12.ptrace

每個進程同一時刻只能被一個進程ptrace。

可以主動ptrace自己,讓別的進程無法對自己ptrace;也可以寫多個進程,讓其互相之間ptrace以免被調試器ptrace

 

13.代碼執行時間間隔檢測

在兩段不同代碼處插入時間函數,獲取當前時間。對兩個時間差進行檢測,如果差值過大,則說明兩段代碼運行時間間隔過長,可能是被單步調試。

 

14.mem、pagemap監測

第三代殼技術原理:通常殼會在程序運行前完成對text的解密,所以脫殼可以通過dd與gdb_gcore來dump  /proc/pid/mem或/proc/pid/pagemap,獲取到解密后的代碼內容。針對這種運行時解密再加密的殼,有的脫殼技術需要用到動態調試來dump內存中的數據。
可以通過Inotify系列的API來監控mem或pagemap的打開或訪問事件,一旦發生就結束進程來阻止dump。

 

 

0x02  動態調試中檢測

 

1.斷點指令檢測

如果函數被下軟件斷點,則斷點地址會被改寫為bkpt指令,可以在函數體中搜索bkpt指令來檢測軟件斷電。

 

2.函數hash值檢測

so文件中函數的指令是固定,但是如果被下了軟件斷點,指令就會發生改變(斷點地址被改寫為bkpt斷點指令),可以計算內存中一段指令的hash值進行校驗,檢測函數是否被修改或被下斷點。

 

3.單步調試陷阱

調試器從下斷點到執行斷點的過程分析:
1)保存:保存目標處指令
2)替換:目標處指令替換為斷點指令
3)命中斷點:命中斷點指令(引發中斷 或者說發出信號)
4)收到信號:調試器收到信號后,執行調試器注冊的信號處理函數。
5 )恢復:調試器處理函數恢復保存的指令
6)回退:回退PC寄存器
7 )控制權回歸程序.
 
主動設置斷點指令/注冊信號處理函數的反調試方案:
1)在函數中寫入斷點指令
2)在代碼中注冊斷點信號處理函數
3)程序執行到斷點指令,發出信號,分兩種情況:
  (1)非調試狀態
  進入自己注冊的函數,NOP指令替換斷點指令,回退PC后正常指令。
  (執行斷點發出信號—進入處理信號函數—NOP替換斷點—退回PC)
  (2)調試狀態
  進入調試器的斷點處理流程,他會恢復目標處指令失敗,然后回退PC,進入死循環。
 

4.利用IDA先截獲信號的特性進行檢測

IDA會首先截獲信號,導致進程無法接收到信號,導致不會執行信號處理函數。將關鍵流程放在信號處理函數中,如果沒有執行,就是被調試狀態。

 

5.利用IDA解析缺陷攻擊IDA調試器

IDA調試器原理:IDA采用遞歸下降算法來反匯編指令,而該算法最大的缺點在於它無法處理間接代碼路徑,無法識別動態算出來的跳轉。而arm架構下由於存在arm和thumb指令集,就涉及到指令集切換,IDA在某些情況下無法智能識別arm和thumb指令,進一步導致無法進行偽代碼還原。

在IDA動態調試時,仍然存在該問題,若在指令識別錯誤的地點寫入斷點,有可能使得調試器崩潰。
 
 
待更.....之后我會把相應反調試技術的實現代碼補充上

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM