// Andy Friesen --

Ghetto Closures in C++

2009-02-08 00:00:00 +0000

One of the more annoying gaps in C++ is that there is no sort of “method reference” concept in the language. However, with just a bit of ingenuity and some knowledge of assembly and particular bits of win32, we can dynamically generate a bit of shim code that adds an extra argument into a function call.

The particular example I am going to go through only works for stdcall functions, which limits its usefulness somewhat, but it is still very useful when creating callbacks for particular Win32 functions. The first time I need it, for instance, was to subclass a window for which I did not have the source code. (that window was already using GWL_USERDATA to store its own ‘this’ pointer, so I needed to find another place for it, you see)

For reference, I am using Visual Studio 2008 as my C++ compiler. This code might violently explode if you try to use it on GCC, but you never know! You might get lucky!

First, a bit about how stdcall works. I am leaving out some details, but the important bits boil down to just a few simple things:

  1. Function arguments are pushed onto the stack in reverse order,
  2. The callee (the function you call) is on the hook for popping those arguments off the stack when it is through, and
  3. The return value lives in EAX, or EAX:EDX if it is 64 bits, or ST0 if it’s a double, or someplace in memory if it is, say, an object. Wherever the return value goes, it is not on the stack.

Given all of these things, it is possible to craft a bit of assembly code on the fly that pops off the return address, pushes our “extra” argument onto the stack, making it the “new” first parameter that will go to our real function, pushes the return address back, then jumps to the real function.

Thus armed, we are now ready to get ourselves into trouble. First, the setup!

#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <cstdio>
using std::printf;

typedef void (__stdcall *Function1)(int x);
typedef void (__stdcall *Function0)();

void __stdcall the_func(int x) {
    printf("Hello!  x = %in", x);
}

void main() {
}

Next, we need to get the bytes of the code we want to generate. I couldn’t think of a clever way to do this automatically, so I just added a do-nothing function to my code and used Visual Studio’s disassembler view to tell me how the bytes fell out:

void nothing() {
    __asm {
        pop eax                 // 58
        push 0x12345678         // 68 78 56 34 12
        push eax                // 50
        mov eax, 0x87654321     // B8 21 43 65 87
        jmp eax                 // FF E0
    }
}

You could also try doing it by hand the Intel Manual, but that is a lot more work.

That was totally tedious and retarded. But that’s ok! Now we just have to stuff it into a block of memory, and tell Windows that we are okay if EIP somehow finds its way there:

char code[] = {
    0x58,               // pop eax
    0x68, 0, 0, 0, 0,   // push 0
    0x50,               // push eax
    0xB8, 0, 0, 0, 0,   // mov eax, 0
    0xFF, 0xE0          // jmp eax
};

// YEEHAW
*((int*)(code + 2)) = 31337;
*((Function1*)(code + 8)) = the_func;

void* buffer = VirtualAlloc(0, sizeof(code), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
memcpy(buffer, &code, sizeof(code));

Also, we need to let the CPU know that we have just done Crazy Things with executable code:

FlushInstructionCache(GetCurrentProcess(), buffer, sizeof(code));

Now we whip out our big fat reinterpret_cast, and savor the thrill of the impossible:

Function0 f0 = reinterpret_cast<Function0>(buffer);
f0();

To let go of this memory once we are through, we use VirtualFree()

VirtualFree(buffer, 0, MEM_RELEASE);

Next time, I will either demonstrate the same technique for the __thiscall calling convention, or go into awful details about abusing C++ templates to build a sweet interface. I have yet to decide which, so it will be a surprise!!!