Hooking

In computer programming, the term hooking covers a range of techniques used to alter or augment the behavior of an operating system, of applications, or of other software components by intercepting function calls or messages or events passed between software components. Code that handles such intercepted function calls, events or messages is called a “hook”.

Hooking is used for many purposes, including debugging and extending functionality. Examples might include intercepting keyboard or mouse event messages before they reach an application, or intercepting operating system calls in order to monitor behavior or modify the function of an application or other component. It is also widely used in benchmarking programs, for example frame rate measuring in 3D games, where the output and input is done through hooking.

Hooking can also be used by malicious code. For example, rootkits, pieces of software that try to make themselves invisible by faking the output of API calls that would otherwise reveal their existence, often use hooking techniques. A wallhack is another example of malicious behavior that can stem from hooking techniques. It is done by intercepting function calls in a computer game and altering what is shown to the player to allow them to gain an unfair advantage over other players.

Reference: https://en.wikipedia.org/wiki/Hooking

Use source servers

Use source servers

When there is no source code on the local machine or the .pdb file does not match the source code, you can use Source Server to help debug an application. Source Server takes requests for files and returns the actual files. Source Server runs by means of a DLL file named srcsrv.dll. Source Server reads the application’s .pdb file, which contains pointers to the source code repository, as well as commands used to retrieve source code from the repository. You can limit what commands are allowed to be executed from the application’s .pdb file by listing the allowed commands inside a file named srcsrv.ini, which must be placed in the same directory as srcsrv.dll and devenv.exe.

System_CAPS_security Security Note
Arbitrary commands can be embedded in the application’s .pdb file, so make sure you put only the ones you want to execute in the srcsrv.ini file. Any attempt to execute a command not in the srcsvr.ini file will cause a confirmation dialog box to appear. For more information, see Security Warning: Debugger Must Execute Untrusted Command. No validation is done on command parameters, so be careful with trusted commands. For example, if you trusted cmd.exe, a malicious user might specify parameters that would make the command dangerous.

To enable the use of a Source Server

  1. Ensure that you have complied with the security measures described in the previous section.
  2. On the Tools menu, choose Options.The Options dialog box appears.
  3. In the Debugging node, choose General.
  4. Select the Enable source server support check box.
    Enable source server options
  5. (Optional) Choose the child options that you want.Note that both Allow source server for partial trust assemblies (Managed only) and Always run untrusted source server commands without prompting can increase the security risks discussed above.

Reference: https://msdn.microsoft.com/en-us/library/ms241613.aspx

Set compiler options for symbol files

Set compiler options for symbol files

When you build your project from the VS IDE and use the standard Debug build configuration, the C++ and managed compilers create the appropriate symbols files for your code. You can also set compiler options on the command line to create the symbol files.

C++ options

A program database (.pdb) file holds debugging and project state information that allows incremental linking of a Debug configuration of your program. A .pdb file is created when you build with /ZI or /Zi (for C/C++).

In Visual C++, the /Fd option names the .pdb file created by the compiler. When you create a project in Visual Studio using wizards, the /Fd option is set to create a .pdb file named project.pdb.

If you build your C/C++ application using a makefile, and you specify /ZI or /Zi without /Fd, you end up with two .pdb files:

  • VCx.pdb, where x represents the version of Visual C++, for example VC11.pdb. This file stores all debugging information for the individual OBJ files and resides in the same directory as the project makefile.
  • project.pdb   This file stores all debug information for the.exe file. For C/C++, it resides in the \debug subdirectory.

Each time it creates an OBJ file, the C/C++ compiler merges debug information into VCx.pdb. The inserted information includes type information but does not include symbol information such as function definitions. So even if every source file includes common header files such as <windows.h>, the typedefs from those headers are stored only once, rather than being in every OBJ file.

The linker creates project.pdb, which contains debug information for the project’s EXE file. The project.pdb file contains full debug information, including function prototypes, not just the type information found in VCx.pdb. Both .pdb files allow incremental updates. The linker also embeds the path to the .pdb file in the .exe or .dll file that it creates.

The Visual Studio debugger uses the path to the .pdb file in the EXE or DLL file to find the project.pdb file. If the debugger cannot find the .pdb file at that location or if the path is invalid (for example, if the project was moved to another computer), the debugger searches the path containing the EXE, the symbol paths specified in the Options dialog box (Debugging folder, Symbols node). The debugger will not load a .pdb file that does not match the executable being debugged. If the debugger cannot find a .pdb file, a Find Symbols dialog box appears, which allows you to search for symbols or to add additional locations to the search path.

.NET Framework options

A program database (.pdb) file holds debugging and project state information that allows incremental linking of a debug configuration of your program. A .pdb file is created when you build with /debug. You can build applications with /debug:full or/debug:pdbonly. Building with /debug:full generates debuggable code. Building with /debug:pdbonly generates .pdb files but does not generate the DebuggableAttribute that tells the JIT compiler that debug information is available. Use /debug:pdbonly if you want to generate .pdb files for a release build that you do not want to be debuggable. For more information, see /debug (C# Compiler Options) or /debug (Visual Basic).

The Visual Studio debugger uses the path to the .pdb file in the EXE or DLL file to find the project.pdb file. If the debugger cannot find the .pdb file at that location, or if the path is invalid, the debugger searches the path containing the EXE, and then the symbol paths specified in the Options dialog box. This path is generally the Debugging folder in the Symbols node. The debugger will not load a .pdb file that does not match the executable file being debugged. If the debugger cannot find a .pdb file, a Find Symbolsdialog box appears, which allows you to search for symbols or to add additional locations to the search path.

Web applications

The configuration file of your application (Web.config) must be set to debug mode. Debug mode causes ASP.NET to generate symbols for dynamically generated files and enables the debugger to attach to the ASP.NET application. VS sets this automatically when you start to debug, if you created your project from the Web projects template.

Reference: https://msdn.microsoft.com/en-us/library/ms241613.aspx

Why do symbol files need to exactly match the executable files?

The debugger will load only a .pdb file for an executable file that exactly matches the .pdb file that was created when the executable was built (that is, the .pdb must be the original or a copy of the original .pdb file). Because the compiler is optimized for compilation speed in addition to its main task of creating correct and efficient code, the actual layout of an executable can change even if the code itself has not changed. For more information see the MSDN blog post http://blogs.msdn.com/b/jimgries/archive/2007/07/06/why-does-visual-studio-require-debugger-symbol-files-to-exactly-match-the-binary-files-that-they-were-built-with.aspx

Reference: https://msdn.microsoft.com/en-us/library/ms241613.aspx

Where the debugger searches for .pdb files

  1. The location that is specified inside the DLL or the executable file.(By default, if you have built a DLL or an executable file on your computer, the linker places the full path and file name of the associated .pdb file inside the DLL or the executable file. The debugger first checks to see if the symbol file exists in the location that is specified inside the DLL or the executable file. This is helpful, because you always have symbols available for code that you have compiled on your computer.)
  2. .pdb files that could be present in the same folder as the DLL or executable file.
  3. Any local symbol cache folders.
  4. Any network, internet, or local symbol servers and locations that are specified on, such as the Microsoft symbol server if enabled.

Reference: https://msdn.microsoft.com/en-us/library/ms241613.aspx