Compilation Tutorial: Win32 Debugging API (1)

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:

Value meaning

The create_process_debug_event process is created. event occurs 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.

event occurs when the thread in the Exit_thread_debug_event debuggee exits. The primary thread of the debugee is not notified when it exits. We can assume that the debuggee main thread is synonymous with the Debugge process. So when our program sees the CREATE_PROCESS_DEBUG_EVENT flag, the main thread says, is the Create_thread_debug_event logo.

Load_dll_debug_event debuggee Load 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.

Unload_dll_debug_event event occurs when a DLL is unloaded from the debuggee.

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 restore debuggee, 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 This event occurs when Debuggee calls the Debugoutputstring function to send a message string to our program.

Rip_event System Debugging Error occurred

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

This function restores 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.

Dwcontinuestatus shows how to continue to report debugging events to the thread. 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, which means that an exception occurred in a debuggee thread if the thread reported an exception debug event. If the 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 conclusion, 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.

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.