Set breakpoint tracking in Windbg to open the module of remote debugging switch of C++ program

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 line inside the function

3. Set a breakpoint to track the call to open the remote debugging switch interface

3.1, write demo code

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

4. Finally


VC++ common function development summary (column article list, welcome to subscribe, continuous update...) https://blog.csdn.net/chenlycly/article/details/124272585 C++ software exception troubleshooting series tutorial from entry to mastery (column article list , Welcome to subscribe, keep updating...) https://blog.csdn.net/chenlycly/article/details/125529931 C++ software analysis tool case collection (updating) https://blog.csdn.net/chenlycly/ category_12279968.html?spm=1001.2014.3001.5482Recently        , during testing, we found that our software automatically turns on the remote debugging switch after it starts up, but for security reasons, the remote debugging switch needs to be manually operated by the user in the settings, and cannot be done automatically Open. Because our software module has hundreds of dll libraries and involves multiple development teams, it is impossible to determine which module is automatically opened. Later, I thought that we could use Winddbg dynamic debugging to set breakpoints to quickly locate the problem. This article describes the troubleshooting process for this issue in detail.

1. Windbg dynamic debugging

       Generally, when troubleshooting C++ software exceptions, if there is a dump file containing the exception context, we give priority to using Windbg to open the dump file for static analysis. If no dump file is generated when an exception occurs, 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 problems during dynamic debugging. We can set a breakpoint (set the address of the code segment) in Windbg for dynamic debugging to track the running track of the program. In this case, the problem is located by setting a breakpoint in Windbg.

        There are two ways to use Windbg for dynamic debugging:

1) Directly attach Windbg to the target process that is already running . 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 is during 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, you can set a breakpoint at the entry of the function, or you can set a breakpoint inside the function. Set a breakpoint on a certain line inside the function, and you can view the value of the local variable in the function at the time of interruption. The value of the variable may be an important clue for troubleshooting.

2.1. Set a breakpoint at the function entry

      Set a breakpoint at the function entry, just use the function name directly, and 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 export function of the netdll.dll library, and the symbol of the function is open to the outside world, without the pdb symbol library file. If the function to be set is a function inside the dll library, not an export function of the dll library, you need to set the pdb file of the library into Windbg, because the internal function needs the function symbol in the pdb file, otherwise Windbg cannot recognize it.

2.2. Set a breakpoint on a line inside the function

       A certain line inside the function mentioned here is not a certain line of C++ source code, but a certain line of assembly code in the binary file. Because the program finally runs the binary file, it executes the binary code in the binary file (equivalent to the assembly code, the assembly code is the mnemonic of the binary code).

       In fact, it is to add an offset offset value on the basis of the function (the function is the first address of the function in the code segment). But this offset value is not written randomly, you need to use IDA to open the binary file and check the assembly code to determine it. Because different assembly instructions have different lengths, only the address of the assembly instruction can be set, and the address value between the addresses of two assembly instructions cannot be set, 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 this 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 automatically load it back. For how to use the IDA disassembly tool, you can check out my previous article:

Detailed instructions for using the 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 where they are located

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 the length of code segment memory occupied by different assembly instructions is different:

Note that the address mentioned here is the address of the code segment, which is the address occupied by 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, and the memory occupied by the variable is the memory of the data segment. Regarding the memory partitions of C++ programs, you can check the previous article:
Examples explain 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 , from here we can also see a little clue. Familiarity with assembly code can not only assist in troubleshooting C++ program problems, but also understand programming details or code execution details that cannot be understood by high-level languages. If you want to understand the basic knowledge of assembly required to troubleshoot C++ software problems, you can check out my previous article:
Summary of assembly knowledge required to analyze C++ software exceptions https://blog.csdn.net/chenlycly/article/details/124758670

3. Set a breakpoint to track the call to open the remote debugging switch interface

       In order to track which module automatically turns on the remote debugging switch, as long as the underlying library is used to turn on the remote debugging function name and the module name, you can set a breakpoint in Windbg for dynamic debugging to track.

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

3.1, write demo code

       Use Visual Studio to create an MFC main program TestDlg.exe, and a netdll.dll dynamic library containing the remote debugging interface SetRemoteDebugOn. Call the API interface SetRemoteDebugOn for enabling remote debugging in the netdll.dll library in the response function of the Test button of the TestDlg.exe main program.

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

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

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

       Use Windbg to start TestDlg.exe, and use Windbg to dynamically debug. Because the final call is the SetRemoteDebugOn interface in the netdll.dll module to turn on the remote debugging switch, so just 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 current breakpoint list as shown above.

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

Call the SetRemoteDebugOn interface in the response function of the button, so that the breakpoint set just now is hit, and Windbg is interrupted. Use the kn command to view the function call stack at this time:

We know which module calls the SetRemoteDebugOn interface to turn off remote debugging. As can be seen from the above figure, the TestDlg.exe module calls the interface that enables the remote debugging switch, and it can also be seen that it is called by the CTestDlgDlg::OnBnClickedTest function in the TestDlg.exe module.

4. Finally

       In this example, by setting breakpoints in Windbg, you can quickly locate the module and function information that enables the remote debugging switch. The dynamic debugging function of Windbg is really useful. I hope this article can bring you some inspiration and reference.

Guess you like

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