After reading the question for this article, you might be wondering why anyone would want to do such a thingother 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, its 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:
- The directory where the executable program is located.
- The current directory.
- The Windows system directory.
- The Windows directory.
- 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 dont 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 doesnt 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 weve all suffered from the notorious DLL Hell over the yearsWindows 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 Grimess article "NET and DLL Hell" ).
We can make use of this flexibility in Win32 DLLs to solve our problem. Heres how:
First, we generate the set of exported functions contained in the DLL that we want to hook. Unfortunately, you cant 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.