http://flier_lu.blogone.net/?id=1307208
Win32 debug interface design and implementation analysis so-called debugger is actually a broad concept, and all programs that can monitor other programs in some form may be called debuggers. On the Windows platform, depending on the principle of debuggers can be divided into three categories: kernel debuggers, user status modulators, and pseudocode debuggers. The kernel state debugger directly operates in the operating system core, debugging the system between the hardware and the operating system, common Softice, Windbg, WDEB386 and I386KD, etc., the user status is provided via the operating system Debug interface, debugging a user program between the operating system and the user state program, commonly available in various development environments such as debuggers, OLLYDBG, etc. with VC / Delphi; the pseudocode debugger uses the target system Definition debug interface, debug scripting language or virtual machine code supported by user state programs, common as JVM / CLR debugging tools, VB's PCode debugger, Active Script debugger, and more. Because the pseudo code debugger is too strong with the specific system, it does not have a versatility of the principle level. This series does not involve its content, and if there is an opportunity to discuss the debug interface provided by JVM / CLR / Active Script; The user state initiator is the most widely used, and the reference material is also more complete. I will spend more energy and everyone; the core strategy is tightly combined with the operating system, plus me is not too familiar, I can only try my best. Ha ha. You are welcome to make criticism and advice :) Also, John Robbins is highly recommended in MSDN's bugslayer column, and its
The following is referenced? Lt; / b>
// Start the process you want to debug or the mount adjuvement to the running process
CreateProcess (..., Debug_Process, ...) or debugactiveProcess (dwprocessid)
Debug_event de;
Bool bcontinue = true;
DWORD DWCONTINUESTATUSTAS;
While (bcontinue)
{
BContinue = Waitfordebugevent (& de, Infinite);
Switch (de.dwdebugeventcode)
{
...
DEFAULT:
{
DWCONTINUESTATUS = DBG_CONTINUE;
Break;
}
}
ContinueDebugevent (de.dwprocessid, de.dwthreadid, dwcontinuestus);
}
When the debugger starts debugging, the new process or mount (Attach) to the debugger is started to a running process, and the win32 system will start the server side of the debug interface; then the debugger calls the waitfordebugevent function Waiting for the debug server The end debug event is triggered; the debugger is processed according to the debug event; finally calls the ContinueDeBuGevent function request debug server to continue executing the debugged process to wait and process the next debug event. First, we will roughly look at the server-side implementation ideas of the debug interface: the server-side interface of the debugging service is actually the debug port that exists in the debugged process. This core object implementation is similar to the Win32 completed port. A core queue implemented LPC port. The startup server is actually the template of the Win32 to the debug process and constructs the debug port within the debug process. The debugger communicates through debugging the port and Win32 debug subsystem; debugging the sub-system response system operation, and distributes the debug event to the core state / user status via the debug port. When establishing a new process of the debugger, you need to set the debug_only_this_process or debug_process flag to indicate that the new process needs to be debugged in the CreateProcess function. The CREATEPROCESS function call path is here:
CreateProcessa / CreateProcessw (kernel32.dll)
CreateProcessInternalw (kernel32.dll)
NtcreateProcessex (Ntoskrnl.dll)
PSpCreateProcess (NTOS / PS / CREATE.C: 969)
The CreateProcessinternalW function determines whether to construct the port core object to debug the port according to the incoming dwcreationFlags parameter, and set the corresponding debug flag of the PEB; PSPCREATEPROCESS selects the debugging of the target process based on the debug option and port object handle of the incoming parameter. Port; if you want to create, the incoming port handle is converted into a kernel object reference, saved in the eProcess-> Debugport field of the debugged program process. The ISDebuggerPresent function provided by the Win32 API is to determine whether the current process is debugged by judging the flag bits set in the PEB by judging the flag bits set in the PEB. IsdebuggerPresent function pseudo code as follows:
The following is quoted:
Bool isdebuggerpresent (void)
{
Return ntcurrentteb () -> processenvironmentblock-> beingdebugged;
}
The structure of TEB and PEB can be found on http://www.ntinternals.net. However, this method is easy to directly modify the PEB memory structure directly by the debugger, so there is another method that is directly debugged by checking if the eProcess-> DebugPort field is used. There have been several discussions on the water on the water, such as the code given by the "Method of Detecting the Method of Debugger" in Blowfish. Windows XP / 2003 begins by the CHECKREMOTEDEBUGERPRESENT function provided by the Win32 API and uses the same idea. By calling the NTQueryInformationProcess function querying the debugging port is implemented, the pseudo code is as follows:
The following is quoted:
Bool CheckRemoteDebuggerPresent (Handle Hprocess, Pbool PbdebuggerPresent)
{
ENUM process_info_class {processdebugport = 7}; if (HProcess && PbdebuggerPresent)
{
Handle Hport;
* pbdebuggerpresent = nt_success (NTQueryInformationProcess (HProcess, ProcessDebugport, & Hport, SizeOf (Hport), NULL)? True: false;
Return * pbdebuggerpresent;
}
Return False;
}
Unlike the new process of creating the debugger, debug the debugActiveProcess function that is started to first connect to the port of the Win32 system debug server, and then activate the debug port currently running the debug process. The pseudo code for DebugActiveProcess is as follows:
The following is quoted:
Bool DebugActiveProcess (DWORD DWPROCESSID)
{
IF (dbguiconnecttodbg ())
{
Handle hprocess = processidtohandle (dwprocessid);
IF (HProcess)
{
DBGUIDEBUGACTIVEPROCESS (HPROCESS);
NTClose (HProcess);
}
}
Return False;
}
DBGUICONNECTTODBG function (NTOS / DLL / DLLUISTB.C: 27) Try connecting the core-provided debug subsystem port (name "/ dbguiapiPort"), if successful connection will get a port object (save in dbgusSReServed [ 1]), with a debug state converted signal script (saved in DBGSTATECHANGESEMAPHORE NTCURRENTTEB () -> DBGSSRESERVED [0]) to wait for debug events. The pseudo code is as follows:
The following is quoted:
#define dbgStatechangeseMaphore (NTCurrentteb () -> DBGSSRESERVED [0])
#define dbguiapiport (NTCurrentteb () -> DBGSSRESERVED [1])
NTSTATUS DBGUICONNECTTODBG (Void)
{
NTSTATUS ST = NTCONNECTPORT (& DBGUIAPIPORT, L "// dbguiapipody", ..., & dbgStateChangesemaphore;
IF (Nt_Success (ST))
{
NtregisterThreadterminaTeport (dbguiapiport);
}
Else
{
DBGUIAPIPORT = NULL;
}
Return ST;
}
If the connection tester is successful, call the NTREGISTERTHREADTERMINATEPORT function (NTOS / PS / PSDelete.c: 1202) Add the debug port to the termination port list of the current thread-controlled block (Ethread-> TerminationPortlist). Before the thread is over, the port in this list is activated, and the chance to the debugger is cleaned up. The DBGUIDebugActiveProcess function completes the function of the debug server that activates the debugged process. The pseudo code is as follows:
The following is quoted:
#define dbguiapiport (NTCurrentteb () -> DBGSSRESERVED [1])
Void dbguidebugactiveprocess (handle hprocess) {
Return NTDebugActiveProcess (DBGUIAPIPORT) &&
DBGUIISSUEREMOTEBREAKIN (HPROCESS) &&
DBGUISTOPDEBUGGING (HPROCESS);
}
As for the specific implementation of these functions, the next chapter detailed analysis of the Win32 debug subsystem is detailed, huh, huh, huh, huh, after the debug process starts debugging support, the debugger calls the waitfordeBugevent function Wait for debugging events. This function is actually a simple package for the DBGuiWaitStateChange function (NTOS / DLL / DLLUISTB.C: 93), and completes the actual functionality by waiting for the debug event signal to wait for the DBGuiconnectTodBG function. If you successfully get a debug event, you will also report the DBGuiWaitStateChangeApi message to the debug server via the NTREQUESTWAITREPLYPORT function (NTOS / LPC / LPCSEND.C: 717). After processing the debug event, the debugger called the ContinueDeBugevent function is a simple packaging of the dbguicontinue function, but also informing the debug server using the NTREQUESTWAITREPLYPORT function to the debug server. DBGuicontinueApi message. After completing the debug function, WinXP / 2003 also provides the debugactiveProcessStop function to stop debugging. The pseudo code is as follows:
The following is quoted:
Bool DebugActiveProcessStop (DWORD DWPROCESSID)
{
Handle hprocess = processidtohandle (dwprocessid);
IF (HProcess)
{
CloseallProcessHandles (dwprocessid);
DBGUISTOPDEBUGGING (HPROCESS);
IF (ntclose (hprocess))
Return True;
}
Return False;
}
DBGUISTOPDEBUGGING function (NTDLL.DLL) Call the zwremoveProcessDebug function (ntoskrnl.exe) Turns off the debugging port of the specified process, and implements the transfer port handle and process handle, call the 0xC7 system service to complete the final function. This is not discussed at this time. On this way: P After understanding these, the implementation of the user status invigilator should have a framework for understanding: its structure is an event-based model, and then requests a sub-system request Debug events and complete specific operations.