Last active
July 28, 2023 02:26
-
-
Save RealNeGate/eb5bfd32c31183951a3f201089f0070b to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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