Created
January 11, 2021 18:03
-
-
Save kristianlm/5a1c150d9c90dfabca6f16cd18948dd9 to your computer and use it in GitHub Desktop.
how to execute self-generated x86 machine code on Linux
This file contains hidden or 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
#include <stdio.h> | |
#include <stdint.h> | |
#include <stdlib.h> | |
#include <unistd.h> | |
#include <string.h> | |
#include <errno.h> | |
#include <sys/mman.h> | |
int main(int argc, char *argv[]) { | |
unsigned int pagesize; | |
pagesize = sysconf(_SC_PAGE_SIZE); | |
if (pagesize == -1) { perror("sysconf"); } | |
size_t bufsize = 4 * pagesize; | |
uint8_t *buf = aligned_alloc(pagesize, bufsize); | |
if (buf == 0) { perror("memalign"); } | |
// write x86 opcodes directly into memory. this is almost always a | |
// very bad idea. | |
memcpy(buf, | |
"\xB8\x00\x11\x22\x33" // literal => eax | |
"\xC3" // => retn (return from near procedure) | |
, 6); | |
// then write-protect and make executable | |
if (mprotect(buf, bufsize, PROT_EXEC|PROT_READ ) < 0) { | |
fprintf(stderr, "mprotect failed: %s\n", strerror(errno)); | |
return 1; | |
} | |
int (*ptr)(int) = (int (*)(int)) buf; | |
printf("returns: 0x%X\n", ptr(42)); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
$ gcc x86-codegen-at-runtime.c -o x86-codegen-at-runtime && ./x86-codegen-at-runtime returns: 0x33221100