從異常分發流程的實現看反用戶調試器

從異常分發流程的實現看反用戶調試器

本文是對 從3環調試器工作流程的實現看反調試 的一個補充和擴展,主要從異常分發的流程的實現來看怎麼反調試。

後面還有一篇鏈接:[原創]從異常分發流程的實現看反雙機調試【有碼】

後面順變會附帶上寫滿註釋的wrk代碼,方便大家對照著看。

由於本人水平有限,錯誤之處難免,請大神們不吝指正哈!

一個INT 3被執行的時候關鍵數據結構變化

棧的變化:

INT 3剛被執行的時候堆棧的情況:

從異常分發流程的實現看反用戶調試器

說明:

1. 從tss段中取出對應權限的esp

2. 把用戶空間的ss寄存器壓入HardwareSegss

3. 把用戶空間的esp寄存器壓入HardwareEsp

4. 把標誌寄存器壓入到EFLAGS

5. 把用戶空間的cs寄存器壓入到SegCs中

6. 把用戶空間的eip壓入到Eip中

填充TrapFrame結構:

從異常分發流程的實現看反用戶調試器

說明:

1. V8 6Gs、V86Fs、V86Ds、V86Es,這些寄存器現在僅僅作為保留,不必研究

2. HardwareSegSs、HardwareEsp、Eflags、SegCs、Eip,這些在中斷的時候cpu會幫我保存

3. 其他的寄存器操作系統在中斷例程保存

異常結構相關:

異常結構體

從異常分發流程的實現看反用戶調試器

說明:

1. 在學習階段只需要關注ExceptionCode和ExceptionAddress即可,其他的參數如果不寫調試器暫時用不到

異常結構體在什麼階段被填充(以INT 3為例):

從異常分發流程的實現看反用戶調試器

說明:

1. 從上圖可以看到在CommonDispatchException中被填充

2. 但是我們也可以看到我們分析的重點會在KiDispatchException中,是的我們的分析的重點就是他,但是分析它之前我們得做一些準備工作

異常結構體具體是如何被填充的

這個問題只能貼代碼了,就貼CommonDispatchException代碼,這塊的代碼已經有很詳細的註釋了,等會全部的代碼放到附件中提供下載

從異常分發流程的實現看反用戶調試器

為什麼講異常分發流程會講下核心數據結構:

1. 後面我會把詳細註釋過的wrk的源代碼作為附錄,大家可以對照註釋去看異常分發的源代碼

2. 根據我的經驗,阻礙看源代碼就是對這些數據結構不瞭解,特別是TrapFrame、異常時候的堆棧、在異常中怎麼返回這類問題

異常分發全流程:

從異常分發流程的實現看反用戶調試器

1. 如果你看到這張圖不想看了,你的感覺是對的,我第一次看到這張圖也是一臉懵逼,感覺好複雜啊,幸好我們今天僅僅只學習其中的一塊,就是圖的左半部分

2. 如果你看到這裡有什麼第一次、第二次XX,先不用糾結這個問題,我們只討論第一次的話題,因為男人的第一次是難以忘懷的,不對是第一次分發才和3環調試器有密切關係,第二次分發以後專門開個帖子對著源代碼講下

3. 忽略圖中的內核調試器

第一次分發且有用戶調試器:

先來個流程圖:

從異常分發流程的實現看反用戶調試器

說明:

1. 可以看到核心的函數是 DbgkForwardException

2. 把調試事件發送到調試對象的核心函數是DbgkSendApiMessage

核心代碼的分析:

KiDispatchException 的分析:

從異常分發流程的實現看反用戶調試器

主要調用了DbgkForwardException,這個是用戶調試的主要函數

從異常分發流程的實現看反用戶調試器

DbgkForwardException的分析:

從異常分發流程的實現看反用戶調試器

先檢查 CrossThreadFlags 的 PS_CROSS_THREAD_FLAGS_HIDEFROMDBG 標誌位是否被設置,如果被設置代表不會被調試。

從異常分發流程的實現看反用戶調試器

調用 DbgkpSendapiMessage 發送異常信息給調試器

從異常分發流程的實現看反用戶調試器

DbgkpSendApiMessage 的分析:

從異常分發流程的實現看反用戶調試器

說明:

1. 這個函數主要調用了 DbgkpQueueMessage 函數

DbgkpQueueMessage 的分析:

從異常分發流程的實現看反用戶調試器

這裡會獲取一個全局鎖,這個是一個反調試的好地方

從異常分發流程的實現看反用戶調試器

把調試事件插入DebugObject的EventList裡面去:

從異常分發流程的實現看反用戶調試器

等待調試器處理這個調試事件

從異常分發流程的實現看反用戶調試器

從異常分發流程中總結出來的反3環調試:

1. 直接對idt做hook,比如3號中斷,這樣就沒法使用軟件斷點了

2. 對需要保護的進程的每個線程的的 Ethread 結構體的CrossThreadFlag 設置 PS_CROSS_THREAD_FLAGS_HIDEFROMDBG,有一個專門的api是:ZwSetInformationThread(hThread, ThreadHideFromDebugger, NULL, NULL)

3. DbgkpSendApiMessage 進行掛鉤,直接返回STATUS_UNSUCCESSFUL

4. DbgkpQueueMessage 進行掛鉤,直接返回STATUS_UNSUCCESSFUL

5. 這個就比較比較猥瑣了:ExAcquireFastMutex (&DbgkpProcessDebugPortMutex),直接鎖住這個全局變量,所有的調試器都會卡死,並且沒有鉤子

6. DbgkpSuspendProcess和DbgkpResumeProcess 掛鉤,向0x64端口寫入0xFE,讓機器重啟

謝謝大家觀看!

原文鏈接:

[原創]從異常分發流程的實現看反用戶調試器-『軟件逆向』-看雪安全論壇bbs.pediy.com

更多幹貨請關注看雪學院公眾號 ikanxue!


分享到:


相關文章: