Dr. Dobb's is part of the Informa Tech Division of Informa PLC

This site is operated by a business or businesses owned by Informa PLC and all copyright resides with them. Informa PLC's registered office is 5 Howick Place, London SW1P 1WG. Registered in England and Wales. Number 8860726.


Channels ▼
RSS

.NET

DLL Hooking


After reading the question for this article, you might be wondering why anyone would want to do such a thing—other than a hacker. Actually, there are some really good reasons why you might find yourself with this problem. For example, suppose that you wanted to write a tool that would allow you to see that API traffic generated by a particular application? As each call is made, you dump out the parameter values and name of the function. With this you get a call trace and context information that enables you to see how the functions are being used.

Although there are many third-party applications that provide such a capability, you might be in a situation where you need something that can ship with your application, or you might not be able to afford to buy a tool. So rolling your own might be preferable (or your only choice). Fortunately, it’s relatively straightforward to put together some code do just this with a few limitations. First, what I describe in this article is relevant to hooking DLLs (not calls from functions in an EXE to functions in an EXE), and is practical only for DLLs with unadorned (non-C++) style export function definitions. Yes, hooking C++ methods is possible, but more cumbersome due to the mangling of names that goes on for class methods.

First off, let's consider what happens when an EXE needs to make calls (or DLLs need to make calls) into functions contained in a DLL. At load time, the Windows OS loader determines what import references exist in the EXE and proceeds to find the DLLs by searching a well-known set of directory paths. Here is what MSDN has to say about where Windows looks and in what order:

  1. The directory where the executable program is located.
  2. The current directory.
  3. The Windows system directory.
  4. The Windows directory.
  5. The directories that are listed in the PATH environment variable.

Looking through this list, we see that even for known Windows system DLLs like WINSOCK.DLL or MSHTML.DLL, the OS begins looking in the directory where the EXE is located. This gives us our first clue as to how to begin.

Recall that Win32 DLLs don’t come with all of the security provisions that newer .NET assemblies come with. Windows is happy to load a DLL from a location based simply on a name match with what it is looking for. It doesn’t bother to check if the size of the DLL is correct, or if the DLL is in the expected location. Windows simply loads it and attempts to find the exported functions so it can do fixups before the EXE actually runs. This is actually one of the reasons we’ve all suffered from the notorious “DLL Hell” over the years—Windows would blindly load an older (or newer) version of a DLL than what the application was designed for and strange things would happen when the user attempted to work with the application. .NET attempts to solve this problem in a variety of ways, which you can read more about in other Windows Developer articles (see Richard Grimes’s article "NET and DLL Hell" ).

We can make use of this flexibility in Win32 DLLs to solve our problem. Here’s how:

First, we generate the set of exported functions contained in the DLL that we want to hook. Unfortunately, you can’t just hook a subset of them using this technique, but even if there are many functions, it can be fairly straightforward to manufacture a ‘C’ header file containing the definitions. You can use DUMPBIN.EXE from the Platform SDK to get a listing of what is available in the DLL.

Next, we create a standard Win32 DLL and implement stubs for each of these functions. They need to have the exact same signatures (parameters, names, etc.) as the ones we are trying to hook. Be sure that each function is marked for export (or do so in the .DEF) file. Also, you need to be sure that you use the same ordinal numbers (if specified) that the hooked DLL uses.

Next, create a static method in the DLL named something unique like _InitHook that will dynamically load the DLL that you want to hook. This is done using LoadLibrary, as you would expect. The DLL module handle would be cached off into a static or other global variable for the DLL. The _InitHook() function would be optimized to check the global variable and only reload the hook DLL if not already loaded.

Next, each function you stubbed out would call _InitHook() to be sure everything is initialized properly. Then, it would call GetProcAddress to get a pointer to the same function in the hooked (loaded) DLL. Once this function reference is obtained, a call is made and any return values are returned out of the hook.

Next, in the DllMain() function for the DLL, be sure to unload the dynamically loaded DLL using the cached handle when the hooking DLL Next, compile and link the DLL. Be sure that the name of the DLL file is the same as the name of the DLL you want to hook.

Now, for fooling Windows into using your DLL: Place the DLL in the same directory as the EXE. If the DLL you want to hook is also there, move it to a directory in the PATH or other location where Windows can find it when you call LoadLibrary() in your hooking DLL.

At this point, launch the application and your hook DLL should get loaded and magically do its stuff. The EXE should be none the wiser and the DLL functionality should pass through to the EXE just fine. There are other more involved techniques for hooking DLLs or even EXE functions, but I would point you to MSDN. Search through the years for articles written by Matt Pietrek or Jeffrey Richter.


Mark M. Baker is the Chief of Research & Development at BNA Software located in Washington, D.C.


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.