top of page

Intercepting calls to dynamic libraries

In the last few posts we saw how we could extract the necessary data from our game. The next couple of posts will deal with drawing custom elements on top of a game. This will require us to intercept calls to the graphics API used by the game(OpenGL or DirectX); in other words, we will have to modify the respective dynamic libraries.

Introduction to DLLs

You may be familiar with static libraries. For C++ programs, they have the .lib or .a extension. They allow us to put reusable code in a single entity (the static library) which can be linked to by any application which needs to use that functionality. This reused code becomes part of the application. This means that programs that link to the same library will end up having the same copies of functions from the static library, resulting in wasted memory. This is where dynamic libraries come in. The same library module can be mapped into the address spaces of multiple programs, saving memory (the data is still maintained on a per-process basis).

Implicit linking: For implicit linking, you need to link to the import library(.lib) associated with the .dll. The generated code will replace any calls to library functions in the executable with code that looks up the location of the function in the import table of your PE file. The import table has entries for all dynamic library functions used by your application . This table is initialized with the correct function addresses when the dynamic libraries are loaded at run time.

Explicit linking: If you want to link explicitly, you need to call the "LoadLibrary" function located in "kernel32.dll", followed by "GetProcAddress", which gives you the address of the function you were looking for in the dynamic library.

That's a gist of dynamic libraries. Lets move on to intercepting DLL calls.

IAT Hooking:

As mentioned above, implicitly linking to a dynamic library involves the use of an Import Address Table (IAT). One way to intercept calls to a libraries functions would be to modify the value in the IAT and make it point to a user defined function. Once we locate the IAT table in the PE header file we can iterate through the function names and change the ones we need (Check out this article to learn more about the PE header file layout). The wikipedia article on hooking provides a nice example, I'll post it here for convenience.

It finds the "MessageBoxA" function pointer in the IAT and changes it to point to the user defined "NewMessageBoxA". We use "VirtualProtect" to make sure we have write permissions to that section of memory. The above code assumes that the hooking is done in the context of the process being hooked. In order to hook from an external process, you will need to use "WriteProcessMemory"

DLL injections+Hooks:

DLL injections are a nifty way to get a target application to execute code in its own context. This involves tricking the target application into loading a user defined DLL, which in turn calls the "DLLMain" function for it, where we can execute any necessary code. There are a number of ways to load your .dll in a target application, listed here. Once we've gained access to the target application, we could overwrite the function pointers in the virtual function table for an object, redirecting any future calls to our custom functions instead.

Here's a practical example of injecting a DLL and overwriting the virtual function table entries for a few functions in DirectX . I've borrowed the injecting code from here,

The steps involved are:

  • Open Process

  • Allocate memory in the process using "VirtualAllocEx"

  • Write the name of the DLL to be loaded to this allocated memory

  • Get the address for "LoadLibrary" in "kernel32.dll"

  • Create a thread in the target process using "CreateRemoteThread" which will start execution at "LoadLibrary" and load the specified DLL into the target process

Note that this works only because the base address of "kernel32.dll" is the same for all processes, so we can use the address returned from "GetProcAddress" in the above function for the remote thread as well.

Once our DLL has been loaded, we can overwrite the virtual function table as described here.

The code is a little too big to fit in an image so I'm just going to post the meat of it. We call the following function from "DLLMain"

We create a Direct3D interface and store the pointer to its virtual function table in "Direct3D_VMTable" (The virtual function table pointer is the first element in any object that has "virtual" functions). We then store the original values of the functions and overwrite the entries in the virtual function table with pointers to our own functions. These functions call the original function and then execute our custom code (or vice versa).

I did not implement these on my own (apologies!), since I didn't want to meddle with Dota2 on such an intimate level and try to hide my attempts at manipulating the game from Valve's anti-cheat system (which is a whole different subject). Similar techniques are used by applications like FRAPS to draw overlays on top of your game, so you probably won't get banned for this, but I'm not sure where Valve draws the line. They will almost certainly know that something is interfering with the application, but I don't know how they decide the severity of the intrusion. Anyway, these techniques should be good for single player games.

DLL Wrappers:

Windows uses a certain search order to look for a DLL that is linked to by an application (found here). When the application is loaded, the current directory of the application is searched for the DLLs it links to. By placing a DLL which exports the same functions as the one we want to proxy, we can trick the application into loading our DLL. Thats it! We can intercept all the calls we care about, and forward the ones we don't need to the original DLL. We will look at a DirectX 9 wrapper in the next post.


Comments


bottom of page