Skip to content

Instantly share code, notes, and snippets.

@RealNeGate
Last active July 28, 2023 02:26
Show Gist options
  • Save RealNeGate/eb5bfd32c31183951a3f201089f0070b to your computer and use it in GitHub Desktop.
Save RealNeGate/eb5bfd32c31183951a3f201089f0070b to your computer and use it in GitHub Desktop.
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
typedef struct __attribute__((__packed__)) {
// lea RCX, [next]
// or lea RDI, [next]
uint8_t rex; // 0x48
uint8_t lea_op; // 0x8D
uint8_t modrm; // 0x0D for RCX, 0x3D for RDI
int32_t next_rel; // rel32 into the data
// jmp qword [rip]
uint8_t jmp_op; // 0xFF
uint8_t jmp_op2; // 0x25
int32_t target; // rel32
uint64_t function_ptr;
// payload
char data[];
} Closure;
enum {
CLOSURE_ALIGNED_SIZE = (sizeof(Closure) + 15ull) & ~15ull,
CLOSURE_OFFSETOF_DATA = CLOSURE_ALIGNED_SIZE - sizeof(Closure),
};
typedef void(*Closure_Func)(void);
// lovely accessors
void* closure_as_data(Closure* c) { return c->data + CLOSURE_OFFSETOF_DATA; }
Closure_Func closure_as_fn(Closure* c) { return (Closure_Func) c; }
// generate closure
Closure* closure_create(Closure_Func fn, size_t size) {
Closure* c = VirtualAlloc(
0,
CLOSURE_ALIGNED_SIZE + size,
MEM_COMMIT | MEM_RESERVE,
PAGE_EXECUTE_READWRITE
);
*c = (Closure){
// lea rcx, [data]
0x48, 0x8D, 0x0D, CLOSURE_ALIGNED_SIZE - offsetof(Closure, jmp_op),
// jmp qword [target]
0xFF, 0x25, 0,
// target
(uintptr_t) fn,
};
return c;
}
void closure_destroy(Closure* c) {
VirtualFree(c, 0, MEM_RELEASE);
}
typedef struct {
int x, y;
} Foo;
static void foo(Foo* f) {
printf("Woah! %d\n", f->x + f->y);
f->x += 16;
}
int main() {
Closure* c = closure_create((Closure_Func) foo, sizeof(Foo));
Foo* f = closure_as_data(c);
f->x = 16;
f->y = 3;
closure_as_fn(c)();
closure_as_fn(c)();
closure_destroy(c);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment