debugging API in Win32

Source: Internet
Author: User
Tags continue exception handling execution thread win32

In this tutorial, we will learn the primitives that WIN32 provides to developers for debugging purposes. At the end of the tutorial, we'll learn how to debug a process.

Theory:
Win32 has some APIs for programmers to use, and they provide the equivalent of debugger functionality. They are called Win32 debugging APIs (or primitives). Using these APIs, we can:

Load a program or bundle it into a running program for debugging
Obtain low-level information about the program being debugged, such as process ID, entry address, image base, and so on.
Be notified when a debugging-related event occurs, such as the start/end of a process/thread, the load/release of a DLL, and so on.
Modifying a process or thread that is being debugged
In short, we can use these APIs to write a simple debugger. Because this topic is a bit too big, I divide it into several parts, and this tutorial is the first part of it. In this tutorial, I will explain some basic concepts and the general framework of the Win32 debugging API.
The steps for using the Win32 debugging API are as follows:

Create a process or bundle it onto a running process. This is the first step in using the Win32 debugging API. Because our program has to play the role of debugger, we need to find a program for debugging. A program that is debugged is called a debuggee. The debuggee can be obtained in the following two ways:
Create the debuggee process through CreateProcess. To create a process that is being debugged, you must specify the DEBUG_PROCESS flag. This flag tells Windows that we want to debug the process. When important debugging-related events (debug events) occur in debuggee, Windows sends notifications to our programs. Debuggee will hang up immediately to wait for our program to be ready. If debuggee also created a child process, Windows also sends notifications to our programs for debugging events in each child process. This feature is usually unnecessary. We can ban it by specifying the debug_only_this_process and debug_process combination flags.
We can also bind to a running process with the debugactiveprocess flag.
Wait for the debug event. After a debuggee process is obtained, the main thread of the debuggee is suspended, which continues until our program calls Waitfordebugevent. This function is similar to other waitforxxx functions, for example, It blocks the calling thread until the waiting event occurs. For this function, it waits for a debug event sent by Windows. Here's what it's defined:
Waitfordebugevent Proto Lpdebugevent:dword, Dwmilliseconds:dword

Lpdebugevent is the address of a debug_event this structure will be populated with information about debug events that occur in debuggee.

Dwmilliseconds the time, in milliseconds, that the function waits for a debug event. If no debug event occurs during this time, Waitfordebugevent returns the caller. On the other hand, if you specify the parameter as a INFINITE constant, The function waits until the debug event occurs.

Now let's look at the debug_event structure.

Debug_event STRUCT
Dwdebugeventcode DD?
DWPROCESSID DD?
dwThreadID DD?
U debugstruct <>
Debug_event ENDS

Dwdebugeventcode This value specifies the type of debug event that is waiting to occur. Because there are many types of events, our program checks the value, knows the type of event to occur, and responds. The value may be the following:

The

value meaning
Create_process_debug_event process is created. Events occur when the debuggee process has just been created (not yet running) or our program has just been bundled to a running process with debugactiveprocess. This is the first event that our program should get. The
Exit_process_debug_event process exits.
Create_thead_debug_event event occurs when a new thread is created in a deuggee process or when our program is first bundled into a running process. Note that the notification is not received when the main thread of the Debugge is created. The event occurs when the thread in the
Exit_thread_debug_event debuggee exits. The main thread of the Debugee will not receive the notification when it exits. We can assume that the debuggee main thread is synonymous with the Debugge process. When our program sees the CREATE_PROCESS_DEBUG_EVENT flag, the main thread says, is the Create_thread_debug_event logo. The
load_dll_debug_event debuggee loads a DLL. We will receive this event when the PE loader first breaks down a link to a DLL. (When the call CreateProcess mount debuggee) and occurs when Debuggee calls LoadLibrary. The
Unload_dll_debug_event event occurs when a DLL is unloaded from the debuggee. The
Exception_debug_event event occurs when an exception occurs in debuggee. Note: This event occurs only once before debuggee begins its first instruction. The exception is actually a debug interrupt (int 3h). If you want to recover debuggee things, call the Continuedebugevent function with the DBG_CONTINUE flag. Do not use the DBG_EXCEPTION_NOT_HANDLED flag otherwise debuggee will refuse to run under NT (Win98 run very well).
Output_debug_string_event occurs when the debuggee calls the Debugoutputstring function to send a message string to our program.
Error rip_event System debugging

Dwprocessid and dwThreadID the process and thread IDs where the debug events occurred. We can use these values as markers for the process or thread that we are interested in. Remember that if we use CreateProcess to load debuggee, we can still be in Process_ The info structure obtains debuggee processes and threads. We can use these values to distinguish whether a debug event occurs in Debuggee or in its subprocess (when the DEBUG_ONLY_THIS_PROCESS flag is not specified).

U is a union that contains more information about debugging events. Depending on the dwdebugeventcode above, it can be the following structure:

Explanation of Dwdebugeventcode U
The create_process_debug_info structure named Createprocessinfo create_process_debug_event
The exit_process_debug_info structure named ExitProcess exit_process_debug_event
The create_thread_debug_info structure named CreateThread create_thread_debug_event
The exit_thread_debug_event structure named ExitThread exit_thread_debug_event
The load_dll_debug_info structure named Loaddll load_dll_debug_event
The unload_dll_debug_info structure named Unloaddll unload_dll_debug_event
The exception_debug_info structure named EXCEPTION exception_debug_event
The output_debug_string_info structure named Debugstring output_debug_string_event
The rip_info structure named Ripinfo rip_event

I'm not going to talk about all the details of these structures in this tutorial, but here's a create_process_debug_info structure.
Assuming our program calls the Waitfordebugevent function and returns, the first thing we do is check the values in the Dwdebugeventcode to see what kind of debugging events occurred in the debuggee process. For example, If the value of the Dwdebugeventcode is create_process_debug_event, you can think of the members of U as Createprocessinfo and the U. Createprocessinfo to visit.

Do a response to the debug event in our program. When Waitfordebugevent returns, this means that a debug event has occurred in the debuggee process or a timeout has occurred. So our program has to check the Dwdebugeventcode to make a proper response. There are some things like handling Windows messages: The message is selected and ignored by the user.
Continue to run debuggee. Windows hangs debuggee when the debug event occurs, so when we're done with the debug events, let debuggee continue to run. Call the Continuedebugevent function to complete the process.
Continuedebugevent Proto Dwprocessid:dword, Dwthreadid:dword, Dwcontinuestatus:dword

The function resumes a thread that was suspended because of a debugging event.
Dwprocessid and dwThreadID are the process IDs and thread IDs of the threads to be recovered, usually from Dwprocessid and dwThreadID members of the debug_event structure. The
Dwcontinuestatus shows how to continue to report debugging events. There are two possible values: Dbg_continue and dbg_exception_not_handled. For most debugging events, both values are the same: The recovery thread. The only exception is exception_debug_event, if the thread reports an exception debug event, which means an exception occurred in the debuggee thread. If dbg_continue is specified, The thread ignores its own exception-handling parts and continues execution. In this case, our program must check and handle the exception before resuming the thread with Dbg_continue, otherwise the exception will continue to occur endlessly .... If we specify the dbg_exception_not_handled value, we tell windows that our program does not handle exceptions: Windows uses the debuggee default exception handling function to handle exceptions.
In summary, if our program does not consider an exception, and the debug event points to an exception in the debuggee process, the Continuedebugevent function with the DBG_CONTINUE flag should be invoked. Otherwise, our program must be Dbg_ Exception_not_handled call continuedebugevent. However, the DBG_CONTINUE flag must be used in the following cases: The first has a value in the Exceptioncode member Exception_ Breakpoint Exception_debug_event event. When Debuggee starts executing its first instruction, our function will accept the exception debug event. It is in fact a debug interrupt (int 3h). If we were to dbg_exception _not_handled calls Continuedebugevent to respond to debug events, Windows NT rejects the execution of debuggee (because it has no exception handling). So in this case, use the Dbg_ The continue flag tells Windows that we want the thread to continue executing.

Continue the above step loop until the debuggee process exits. Our program must be in an infinite loop like a message loop until the debuggee ends. The cycle is generally as follows:
. While TRUE
Invoke Waitfordebugevent, addr debugevent, INFINITE
. break. If debugevent.dwdebugeventcode==exit_process_debug_event
< debugging event Handling >
Invoke Continuedebugevent, Debugevent.dwprocessid, Debugevent.dwthreadid, dbg_exception_not_handled
. ENDW


That is, when we start debugging the program, our program cannot be separated from debuggee until it is finished.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.