Windows內核調試器原理淺析(二)
——
if (NT_SUCCESS(ManipulateState.u.Continue.ContinueStatus) != FALSE) {
return ContinueSuccess;
} else {
return ContinueError;
}
break;
case DbgKdContinueApi2:
if (NT_SUCCESS(ManipulateState.u.Continue2.ContinueStatus) != FALSE) {
KdpGetStateChange(&ManipulateState,ContextRecord);
return ContinueSuccess;
} else {
return ContinueError;
}
break;
case DbgKdRebootApi:
KdpReboot();
break;
case DbgKdReadMachineSpecificRegister:
KdpReadMachineSpecificRegister(&ManipulateState,&MessageData,ContextRecord);
break;
case DbgKdWriteMachineSpecificRegister:
KdpWriteMachineSpecificRegister(&ManipulateState,&MessageData,ContextRecord);
break;
case DbgKdSetSpecialCallApi:
KdSetSpecialCall(&ManipulateState,ContextRecord);
break;
case DbgKdClearSpecialCallsApi:
KdClearSpecialCalls();
break;
case DbgKdSetInternalBreakPointApi:
KdSetInternalBreakpoint(&ManipulateState);
break;
case DbgKdGetInternalBreakPointApi:
KdGetInternalBreakpoint(&ManipulateState);
break;
case DbgKdGetVersionApi:
KdpGetVersion(&ManipulateState);
break;
case DbgKdCauseBugCheckApi:
KdpCauseBugCheck(&ManipulateState);
break;
case DbgKdPageInApi:
KdpNotSupported(&ManipulateState);
break;
case DbgKdWriteBreakPointExApi:
Status = KdpWriteBreakPointEx(&ManipulateState,
&MessageData,
ContextRecord);
if (Status) {
ManipulateState.ApiNumber = DbgKdContinueApi;
ManipulateState.u.Continue.ContinueStatus = Status;
return ContinueError;
}
break;
case DbgKdRestoreBreakPointExApi:
KdpRestoreBreakPointEx(&ManipulateState,&MessageData,ContextRecord);
break;
case DbgKdSwitchProcessor:
KdPortRestore ();
ContinueStatus = KeSwitchFrozenProcessor(ManipulateState.Processor);
KdPortSave ();
return ContinueStatus;
case DbgKdSearchMemoryApi:
KdpSearchMemory(&ManipulateState, &MessageData, ContextRecord);
break;
讀寫內存、搜索內存、設置/恢復斷點、繼續執行、重啟等等,WinDBG里的功能是不是都能實現了?呵呵。
每次內核調試器接管系統是通過調用在KiDispatchException里調用KiDebugRoutine(KdpTrace),但我們知道要讓系統執行到KiDispatchException必須是系統發生了異常。而內核調試器與被調試系統之間只是通過串口聯系,串口只會發生中斷,并不會讓系統引發異常。那么是怎么讓系統產生一個異常呢?答案就在KeUpdateSystemTime里,每當發生時鐘中斷后在HalpClockInterrupt做了一些底層處理后就會跳轉到這個函數來更新系統時間(因為是跳轉而不是調用,所以在WinDBG斷下來后回溯堆棧是不會發現HalpClockInterrupt的地址的),是系統中調用最頻繁的幾個函數之一。在KeUpdateSystemTime里會判斷KdDebuggerEnable是否為TRUE,若為TRUE則調用KdPollBreakIn判斷是否有來自內核調試器的包含中斷信息的包,若有則調用DbgBreakPointWithStatus,執行一個int 0x3指令,在異常處理流程進入了KdpTrace后將根據處理不同向內核調試器發包并無限循環等待內核調試的回應。現在能理解為什么在WinDBG里中斷系統后堆棧回溯可以依次發現KeUpdateSystemTime->RtlpBreakWithStatusInstruction,系統停在了int 0x3指令上(其實int 0x3已經執行過了,只不過Eip被減了1而已),實際已經進入KiDispatchException->KdpTrap,將控制權交給了內核調試器。
評論