Set breakpoints in Windbg to track modules that turn on software remote debugging

Table of contents

1. Windbg dynamic debugging

2. Set breakpoints in Windbg

2.1. Set a breakpoint at the function entry

2.2. Set a breakpoint on a certain line inside the function

3. Set breakpoints to track calls to the remote debugging switch interface.

3.1. Write demo code

3.2. Set a breakpoint to call the SetRemoteDebugOn interface in Windbg for tracking

4. Finally


Summary of the development of common functions of VC++ (list of column articles, welcome to subscribe, continuous updates...) icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/124272585 C++ software anomaly troubleshooting series of tutorials from entry to proficiency (list of column articles) , welcome to subscribe and continue to update...) icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/125529931 C++ software analysis tools from entry to mastery case collection (column article is being updated...) icon-default.png?t=N7T8https:/ /blog.csdn.net/chenlycly/article/details/131405795 C/C++ basics and advanced (column article, continuously updated...) icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/category_11931267.html        Recently tested We discovered that our software will automatically turn on the remote debugging switch after it is started. However, due to security considerations, turning on the remote debugging switch requires the user to manually operate it in the settings and cannot be turned on automatically. Because our software module has hundreds of dll libraries and involves multiple development groups, it is impossible to determine which module is automatically opened. Later, I thought that I could use Windbg dynamic debugging to set breakpoints to quickly locate the problem. This article details the troubleshooting process for this issue.

1. Windbg dynamic debugging

       Generally, when troubleshooting C++ software exceptions, if there is a dump file containing exception context, we first use Windbg to open the dump file for static analysis. If the dump file is not generated when an exception occurs, you need to attach Windbg to the target process (or use Windbg to start the target program) for dynamic debugging.

       Windbg is mainly used to analyze C++ software exceptions. In addition, it can also help us locate some problems during dynamic debugging. We can set breakpoints (set the address of the code segment) in dynamic debugging Windbg to track the running trajectory of the program. In this case, the problem was located by setting breakpoints in Windbg.

        There are two ways to use Windbg for dynamic debugging:

1) Directly attach Windbg to the already running target process . Click File->Attach to a Process... in the menu bar.
2) You can directly use Windbg to start the target program . Click File->Open Executabe... in the menu bar. Use this method if the problem lies in the process of program startup.

       In this project problem, the operation of automatically turning on the remote debugging switch should be performed when the program starts, so we need to use Windbg to start the program.

2. Set breakpoints in Windbg

       You can use the bp command to set a breakpoint, either at the function entry or inside the function. Set a breakpoint on a certain line inside the function. After hitting the breakpoint, you can view the value of the local variable in the function at the time of the interruption. The value of the variable may be an important clue for troubleshooting the problem.

2.1. Set a breakpoint at the function entry

        Set a breakpoint at the function entry and just use the function name. The function name is the first address of the function in the code segment. Taking the SetRemoteDebugOn function in the netdll.dll library as an example, the command to set a breakpoint is:

bp netdll!SetRemoteDebugOn

Among them, netdll is the name of the dll library (without the .dll suffix), and SetRemoteDebugOn is the function name.

The SetRemoteDebugOn function here is an exported function of the netdll.dll library. The symbols of the function are public and do not require a pdb symbol library file. If the function to be set is a function inside a dll library and an exported function of a non-dll library, you need to set the library's pdb file into Windbg, because the internal function requires the function symbol in the pdb file, otherwise Windbg cannot recognize it.

2.2. Set a breakpoint on a certain line inside the function

       The line inside the function mentioned here is not a line in the C++ source code, but a line in the assembly code (binary machine code) in the binary file. Because the program ultimately runs a binary file and executes the binary code in the binary file (equivalent to assembly code, assembly code is the mnemonic of the binary code).

       In fact, it is to add an offset offset value based on the function (the function is the first address of the function in the code segment). However, this offset value is not written arbitrarily. You need to use IDA to open the binary file and view the assembly code to determine it. Because different assembly instructions have different lengths, you can only set the address of the assembly instruction, and you cannot set the address value between the addresses of two assembly instructions, otherwise it will be invalid and the breakpoint will not be hit.

       Taking the open source library libcurl.dll as an example, we use IDA Pro to open the library file to view the disassembled assembly code , find the internal function easy_perform of the library, and set a breakpoint at line 10007D2D in the function, as shown in the figure:

To see the symbols of the internal functions of the library in IDA, you need to take the pdb file and put it in the same directory as libcurl.dll, and IDA will load it automatically. Regarding how to use the IDA disassembly tool, you can check out the article I wrote before:

Detailed explanation of the use of IDA disassembly tool https://blog.csdn.net/chenlycly/article/details/120635120        To set a breakpoint at the specified 10007D2D line, you need to calculate the offset of this line of assembly instructions relative to the function:

0x10007D2D - 0x10007D10 = 0x1D

So the WIndbg command to set a breakpoint is:

bp libcurl!easy_perform+0x1D

       It can also be seen from the figure below that different assembly instructions occupy different lengths of code segment memory:

Note that the addresses mentioned here are all the addresses of the code segments, which are the addresses of the binary code (assembly code) of the binary file. The address of the code segment must be distinguished from the address of the data segment. The memory occupied by the variable is the data segment memory.   

       Regarding the memory partitions of C++ programs, you can check out the previous article:
Detailed examples of the five major memory partitions of C++ programs https://blog.csdn.net/chenlycly/article/details/120958761         In addition, we want to talk about the importance of understanding assembly code. , we can also see some clues from here. Being familiar with assembly code can not only help troubleshoot C++ program problems, but also understand programming details or code execution details that high-level languages ​​cannot understand. If you want to know the basic assembly knowledge needed to troubleshoot C++ software problems, you can check out the article I wrote before:
Summary of assembly knowledge needed to analyze C++ software exceptions https://blog.csdn.net/chenlycly/article/details/124758670

3. Set breakpoints to track calls to the remote debugging switch interface.

       In order to track which module automatically turns on the remote debugging switch, you only need to use the underlying library to use the name of the function that turns on remote debugging and the name of the module where it is located, and you can set breakpoints in the dynamic debugging Windbg for tracking.

It is not convenient to display the relevant modules and interfaces in the project here. In order to facilitate the explanation of future video courses, I specially wrote some test codes to describe the entire problem tracking process.

3.1. Write demo code

       Use Visual Studio to create an MFC main program TestDlg.exe, and a netdll.dll dynamic library that contains the remote debugging interface SetRemoteDebugOn. In the response function of the Test button of the TestDlg.exe main program, call the API interface SetRemoteDebugOn in the netdll.dll library for turning on remote debugging.

       The API interface SetRemoteDebugOn in the dynamic library netdll.dll is defined as follows:

The response function of the Test button in the main program TestDlg.exe calls SetRemoteDebugOn. The code is as follows:

3.2. Set a breakpoint to call the SetRemoteDebugOn interface in Windbg for tracking

       Use Windbg to start TestDlg.exe and use Windbg for dynamic debugging. Because the SetRemoteDebugOn interface in the netdll.dll module is ultimately called to turn on the remote debugging switch, you only need to set a breakpoint at the entrance of the SetRemoteDebugOn interface, that is: bp netdll !SetRemoteDebugOn , as shown below:

We use the bl command to view the currently set breakpoint list as shown above.

       Then click the Test button in the TestDlg.exe program window:

Call the SetRemoteDebugOn interface in the button's response function, thus hitting the breakpoint just set. Windbg is interrupted. Use the kn command to view the function call stack at this time. We will know which module called the SetRemoteDebugOn interface to turn off remote debugging. .

       View the function call stack when the breakpoint is hit as follows:

As can be seen from the above figure, the TestDlg.exe module calls the interface for turning on the remote debugging switch, and you can also see that it is called by the CTestDlgDlg::OnBnClickedTest function in the TestDlg.exe module. If you have pdb, you can also see which line of code in the function is called!

4. Finally

       In this example, by setting breakpoints in Windbg, we can quickly locate the module and function information that turns on the remote debugging switch. Windbg dynamic debugging function is indeed very useful. I hope this article can bring you some inspiration and reference.

Guess you like

Origin blog.csdn.net/chenlycly/article/details/133375507