About function interposition
I was wondering how I could override dynamic library calls in Linux, and I came across this technique known as function interposition. It is a powerful technique that allows you to override dynamic library calls. It might sound dull, but it can be very, very useful. There are some memory trace tools that make use of this technique to work, but perhaps a cooler example is the OpenGL capture system which was created by nullkey: it can capture OpenGL frames by overriding certain OpenGL functions. Another example are cheat tools (wallhacks, aimbots) which also make use of this technique a lot.
Some background
While Googling (did I spell that right?) I came across this recent blog article which explains the background very well. I will quote it here:
First, some background. When a program that uses dynamic libraries is compiled, a list of undefined symbols is included in the binary, along with a list of libraries the program is linked with. There is no correspondence between the symbols and the libraries; the two lists just tell the loader which libraries to load and which symbols need to be resolved. At runtime, each symbol is resolved using the first library that provides it. This means that if we can get a library containing our wrapper functions to load before other libraries, the undefined symbols in the program will be resolved to our wrappers instead of the real functions.
So if we create a custom shared library which overrides some of the functions of the original library, our functions will be called instead of those of the original library.
How to do it
- Write new functions which override existing functions
- Compile the written code to a dynamic library that is linked to the dynamic linking interface library
- Use the LD_PRELOAD environment variable when running an application to preload your custom library before all other dynamic libraries
The article by Jay Conrod has an example which shows you the basic implementation of a simple memory allocation tracer.
I have also cooked up an example myself. Because I’ve been busy learning more about OpenGL, I thought that it shouldn’t be too hard to create a wallhack for one of my favourite games: Soldier of Fortune 2 running in Wine. Just for testing purposes of course! I am no cheater
It turned out to be relatively simple, although my first tries weren’t so very successful:
- Epic fail – At least I know my library is used now.
- Partial success – Disabling depth testing completely was only a partial success.
- Success – A debugger can tell that players are drawn using glDrawElements(). By knowing the number of elements for each character, we can disable depth testing selectively.

Soldier of Fortune 2 wallhack example
For those of you who are interested in the code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| /*
Simple wallhack example for Soldier of Fortune 2 (Wine) in Linux using function interposition
This code snippet was written by Wesley Stessens (wesley@ubuntu.com)
It is released in the Public Domain.
Compilation: gcc -Wall -ansi -pedantic -shared -ldl -fPIC glhack.c -o glhack.so
Usage: LD_PRELOAD=glhack.so wine game.exe
*/
#define _GNU_SOURCE
#include <dlfcn.h>
#include <stdio.h>
#include <stdint.h>
#include <GL/gl.h>
/* Override the glDrawElements function */
GLAPI void GLAPIENTRY glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices) {
/* Store the actual function in a static function pointer */
static void (*glDrawElements_)(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices) = NULL;
if (!glDrawElements_) {
glDrawElements_ = (void(*)())(intptr_t)dlsym(RTLD_NEXT, "glDrawElements");
puts("GLHack: glDrawElements call has been overridden");
}
/* Disable depth testing if the number of elements to draw is one of the following, which means a player is being drawn */
/* To avoid abuse of this code by cheaters, I have changed all count constants below to VALUEX */
if (count == VALUE1 || count == VALUE2 || count == VALUE3 || count == VALUE4)
glDisable(GL_DEPTH_TEST);
else
glEnable(GL_DEPTH_TEST);
glDrawElements_(mode, count, type, indices);
} |
Interesting thought about multiplayer cheats and Wine
If anti-cheat tools would perform a sanity check of the OpenGL or DirectX DLL, they would only find the virtual DLL’s when a game is run in Wine, right? I’m wondering whether this sort of cheats can be made undetectable then. In a way I hope not, because cheaters are very annoying when you’re playing a game, but on the other hand, it would be an amazing technological achievement. Anyway, anti-cheat tools like PunkBuster don’t even work with Wine at the moment, so it might be a non-issue. What are your thoughts?
VN:F [1.6.3_896]
Rating: +4 (from 4 votes)