Windows异常学习笔记(一)—— CPU异常记录模拟异常记录
Windows異常學(xué)習(xí)筆記(一)—— CPU異常記錄
- 基礎(chǔ)知識(shí)
- 異常的分類(lèi)
- CPU異常
- 分析中斷處理函數(shù) _KiTrap00
- 分析 CommonDispatchException
- 總結(jié)
- 軟件模擬異常
- 實(shí)驗(yàn):分析模擬異常
- 第一步:編譯并運(yùn)行以下代碼
- 第二步:查看匯編代碼
- 第三步:分析 __CxxThrowException
- 第四步:分析 RaiseException
- 第五步:分析 KiRaiseException
- 總結(jié)
基礎(chǔ)知識(shí)
一個(gè)異常產(chǎn)生后,首先是要記錄異常信息(異常的類(lèi)型、異常發(fā)生的位置等),然后要尋找異常的處理函數(shù),稱(chēng)為異常的分發(fā),最后找到異常處理函數(shù)并調(diào)用,稱(chēng)為異常處理。
異常的分類(lèi)
例一:在C語(yǔ)言中使用除法時(shí),若CPU檢測(cè)到除數(shù)為0,便會(huì)拋出異常(CPU產(chǎn)生的異常)
例二:使用代碼拋出異常(軟件模擬產(chǎn)生異常)
CPU異常
處理流程:
1.CPU指令檢測(cè)到異常(例:除0),異常一定是先由CPU發(fā)現(xiàn)的
2.查IDT表,執(zhí)行中斷處理函數(shù),不同的異常調(diào)用不同的中斷處理函數(shù)
3.CommonDispatchException
4.KiDispatchExceeption
Windows異常代碼(出自 張銀奎《軟件調(diào)試》):
分析中斷處理函數(shù) _KiTrap00
執(zhí)行流程:
查看IDT表反匯編(通過(guò) ntoskrnl.exe 搜索字符串 _IDT 進(jìn)行定位):
[ebp+68h]:指向 _Trap_Frame 中的 Eip 的位置,當(dāng)程序產(chǎn)生異常時(shí),保存進(jìn)入異常處理前的地址
0xC0000094h:除0異常的異常代碼
loc_407399 調(diào)用了 CommonDispatchException
總結(jié):
分析 CommonDispatchException
CommonDispatchException在堆棧上構(gòu)建了一個(gè)結(jié)構(gòu)體,然后把異常的一些相關(guān)信息存儲(chǔ)到一個(gè)結(jié)構(gòu)體里
結(jié)構(gòu)體:
總結(jié)
CPU異常執(zhí)行的流程:
1、CPU指令檢測(cè)到異常
2、查IDT表,執(zhí)行中斷處理函數(shù)
3、調(diào)用CommonDispatchException(構(gòu)建EXCEPTION_RECORD)
4、KiDispatchException(分發(fā)異常:目的是找到異常的處理函數(shù))
軟件模擬異常
模擬異常的產(chǎn)生:
CxxThrowException
↓
(KERNEL32.DLL)RaiseException(DWORD dwExceptionCode, DWORD dwExceptionFlags, DWORD nNumberOfArguments, const ULONG_PTR *lpArguments)
↓
NTDLL.DLL!RtlRaiseException()
↓
NT!NtRaiseException
↓
NT!KiRaiseException
實(shí)驗(yàn):分析模擬異常
第一步:編譯并運(yùn)行以下代碼
#include <stdio.h>int main() {throw 1;getchar();return 0; }第二步:查看匯編代碼
可以看到,當(dāng)人為拋出一個(gè)異常時(shí),實(shí)際上就是調(diào)用了 __CxxThrowException 這樣一個(gè)函數(shù)
注意:本實(shí)驗(yàn)使用的編輯器為vc6.0,為C++環(huán)境,在不同的環(huán)境中,調(diào)用的函數(shù)可能是不同的,但是最終調(diào)用的系統(tǒng)函數(shù)都是相同的
第三步:分析 __CxxThrowException
__CxxThrowException 調(diào)用了 Kernel32.dll 中的函數(shù) RaiseException
第四步:分析 RaiseException
2. 調(diào)用 Ntdll.dll!RtlRaiseException
注意一:當(dāng)CPU產(chǎn)生異常時(shí)會(huì)記錄一個(gè)ErrorCode,通過(guò)查表可以查到ErrorCode具體的含義,不同的異常對(duì)應(yīng)不同的錯(cuò)誤代碼,但是軟件拋出的ErrorCode是根據(jù)編譯環(huán)境決定的,如下圖的EDX中存儲(chǔ)的值即為當(dāng)前編譯環(huán)境的ErrorCode
注意二:CPU記錄異常的地址是真正發(fā)生異常的地址,但軟件拋出異常時(shí)記錄的地址是__RaiseException函數(shù)的地址
第五步:分析 KiRaiseException
(IDA代碼待補(bǔ)充)
EXCEPTION_RECORD.ExceptionCode最高位清零 用于區(qū)分CPU異常。
調(diào)用 KiDispatchException 開(kāi)始分發(fā)異常
總結(jié)
異常只有在記錄的時(shí)候處理方式不同,最終在分發(fā)時(shí)走向同一個(gè)地方
總結(jié)
以上是生活随笔為你收集整理的Windows异常学习笔记(一)—— CPU异常记录模拟异常记录的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Windows句柄表学习笔记 —— 句柄
- 下一篇: Windows异常学习笔记(二)—— 内