#include <stdio.h> #include <stdlib.h> #include <sys/mman.h> struct env { int x; }; struct __attribute__((packed)) thunk { unsigned char push; struct env * env_addr; unsigned char call; signed long call_offset; unsigned char add_esp[3]; unsigned char ret; }; struct thunk default_thunk = {0x68, 0, 0xe8, 0, {0x83, 0xc4, 0x04}, 0xc3}; typedef void (* cfunc)(); struct thunk * make_thunk(struct env * env, void * code) { struct thunk * thunk = (struct thunk *)mmap(0,sizeof(struct thunk), PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); *thunk = default_thunk; thunk->env_addr = env; thunk->call_offset = code - (void *)&thunk->add_esp[0]; // Pretty! mprotect(thunk,sizeof(struct thunk), PROT_EXEC); return thunk; } void block(struct env * env) { env->x += 1; printf ("block: x is %d\n", env->x); } cfunc foo (int x) { struct env * env = (struct env *)malloc(sizeof(struct env)); env->x = x; printf ("x is %d\n",env->x); return (cfunc)make_thunk(env,(void *)&block); } int main() { cfunc c = foo(5); c(); c(); }