I have recently learned the Win32 debugging API, and made a simple debugger, slightly experienced, it is recommended to help friends needed. Reference: LCZLion: << Win32 assembly program design >> Peng Chunhua: << Use the debug function to implement the API function tracking >>
Overview: Windows provides a set of APIs for programmers, using these APIs, we can build or bundle the underlying program to debug them, get the underlying information and debugging information of the program. If you want, even You can modify the debugged program (using WriteProcessMemory).
Let us start from an interesting little example: Open Delphi, create a new project, then double-click the main form, write down the following code in the main form of the main form .procedure TFORM1.FormCreate (Sender: TOBJECT); var isdebuggerpresent: function: Boolean; DllModule: THandle; begin DllModule: = LoadLibrary ( 'kernel32.dll'); isDebuggerPresent: = GetProcAddress (DllModule, 'IsDebuggerPresent'); if isDebuggerPresent then begin MessageBox (self.Handle, '! I do not debug' , 'Protests', MB_OK or MB_ICONASTERISK; Application.Terminate; End; End; Press F9 to run, the program is not smooth, and it will stop after playing a complaint that you debug it. Then we are in Delphi Under the Projecs directory, find the program that has just been released, double-click to execute it, this window is very real, what is going on?
The original is DEDEBUGERPRESENT is one of the Win32 debug API. Its role is to determine if the process calling it is running in the debug description (that is, if it is in a status), on the other hand, the Delphi debugger is also Use the Win32 debugging API implementation. This is interested in debugging API? Let us continue to debug the API world!
A program for debugging: Since our program is to play a debugger role, we must also have a program for debug. This program can be obtained by two-method: 1: Use the debugactiveProcess function. This function is defined by DebugActiveProcess (DWProcessID: DWord): bool; stdcall, dwprocessID is used to specify the identifier of the debugged process, if the function call successfully returns true, failure returns false. Note that if it is in NT / 2000 / XP, if the target process is The security descriptor is created, and the security descriptor makes the debugger no sufficient access, then the call of this function may fail. 2: Using the CreateProcess function. This function is defined by CreateProcess (LPApplicationName: Pchar; lpCommandline: pchar; lpProcessAttributes, lpThreadAttributes: PSecurityAttributes; bInheritHandles: BOOL; dwCreationFlags: DWORD; lpEnvironment: Pointer; lpCurrentDirectory: PChar; const lpStartupInfo: TStartupInfo; var lpProcessInformation: TProcessInformation): BOOL; stdcall lack of space, here Detailed not each parameter of CreateProcess Meaning, specifically, please refer to the API Daquan, let us only talk about how to create a debugged process. That is, set the dwcreationFlags parameter, you can specify the debug_process flag to create a debug process, and debug information of the sub-process that is debugged process will also be notified. Our debugger. You can also specify the debug_process or debug_only_this_process flag to represent only the current process. Process debugging information: After we open the debugged program with one of the above methods, our program should call WaitFordeBugevent Wait to process debug events. It blocks the call to the thread until the debugged event happens. This function is defined by: WaitfordeBuGevent (Var LPDebugEvent: TDebugEvent; dwmillisec ONDS: DWORD): Bool; stdcall; where the LPDeBugevent structure will return the debug event information when the debug event occurs. DWMilliseConds value specifies the time of the function waiting for debugging events, in milliseconds, generally set to infinite, indicating waiting until debugging The event happens. This is a bit similar to a message loop. We generally create a new thread, using DebugActiveProcess or CreateProcess to get a program for debugging, then call WaitFordeBugevent with a loop to handle the subsequent debug event. As for why Have it in a new thread? You don't think that your debugger is opened after the debugger is turned on, you can't move ;-)
Continue to run the debugger: When the debug event happens, the debugging will be suspended by Windows. When we handle the debug event, let the debugged program continues to run, this is to use the ContinueDeBugevent function, defined as follows: ContinueDebugevent (dwProcessId, dwThreadId, dwContinueStatus: DWORD): BOOL; stdcall; dwProcessID and dwThreadID which is to be restored process and thread ID, you can get .dwContinueStatus is to specify how to recover from a thread lpDebugEvent structure dwProcessID and dwThreadID, possible values There are DBG_CONTINUE and DBG_EXCEPTION_NOT_HANDLED, DBG_CONTINUE indicates that if the debugger occurs, the abnormality is handled by the debugger. DBG_EXCEPTION_NOT_HANDLED indicates that the debugger does not process the abnormality of the debugged program, and is processed by the default exception handler of the debugprper. Exception.
Here is a simple example to achieve monitoring and exit. UNIT UNIT1;
Interface
Uses Windows, Messages, Sysutils, Variants, Classes, Graphics, Controls, Forms, Dialogs, Stdctrls;
TYPE TFORM1 = Class (TFORM) Button1: TButton; Procedure Button1Click (sender: TOBJECT); private {private declarations} end;
Var Form1: TFORM1;
IMPLEMENTATION
{$ R * .dfm}
{Debugging information processing} procedure debugpro; var si: _StartupinfoA; {process startup information} pi: _process_information; {process information} Flage: DWORD; debugd: debug_event; {debugging event} rc: boolean; begin {establishment debugging process} Flagin : = Debug_process or debug_only_this_process; getStartupInfo (Si); {Initializing Si structure, no way to establish a process} if not createprocess (NIL, PCHAR ('c: /winnt/notepad.exe c: /boot.ini'), NIL, NIL, FALSE, FLAGE, NIL, NIL, SI, PI) THEN BEGIN MessageBox (Application.Handle, 'Establishing the debugged process failed', '!!!', mb_ok or mb_iconerror); EXIT; End; While Waitfordebugevent (Debugd, INFINITE) do begin {event code corresponding processing according} case DebugD.dwDebugEventCode of EXIT_PROCESS_DEBUG_EVENT: begin MessageBox (Application.Handle, 'debugging process is suspended', '!!!', MB_OK or MB_ICONERROR); Break; end; CREATE_PROCESS_DEBUG_EVENT: MessageBox (Application.Handle, 'was established debugging process', '!!!', MB_OK or MB_ICONERROR); EXCEPTION_DEBUG_EVENT: begin if (DebugD.Exception.ExceptionRecord.ExceptionCode <> EXCEPTION_SINGLE_STEP) and (debug D.Exception.ExceptionRecord.ExceptionCode <> EXCEPTION_BREAKPOINT) then Rc: = False {debugger if an abnormality has occurred, let it processed} else Rc: = True; end; end; if Rc then ContinueDebugEvent (DebugD.dwProcessId, DebugD .dwThreadId, DBG_CONTINUE) else ContinueDebugEvent (DebugD.dwProcessId, DebugD.dwThreadId, DBG_EXCEPTION_NOT_HANDLED); end; CloseHandle (pi.hProcess); Closehandle (pi.hThread); end; procedure TForm1.Button1Click (Sender: TObject); var ThreadHandle, Threadid: Thandle; Begin ThreadHandle: = CreateThread (NIL, 0, @debugpro, nil, 0, threadid);
End.
Next article will explain the meaning of the restructuring of the event and the meaning of the event structure. Please pay attention.