Created
August 21, 2021 22:35
-
-
Save hashbrowncipher/cbd50a376473779059264cb6d309cf35 to your computer and use it in GitHub Desktop.
A little x86-64 loader for Linux's binfmt_misc.
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
/* | |
* A little x86-64 loader for Linux's binfmt_misc. | |
* | |
* Compile with: gcc -O3 -static -nostdlib -o loader loader.c | |
* | |
* Register as: | |
* mount -t binfmt_misc none /proc/sys/fs/binfmt_misc | |
* echo ':amd64:E::amd64::/path/to/loader:O' > /proc/sys/fs/binfmt_misc/register | |
* | |
* Then just run your favorite shellcode. Sample: | |
* $ echo McAx///PdfwEPA8F | base64 -d > loop.amd64 | |
* $ chmod +x loop.amd64 | |
* $ ./loop.amd64 | |
*/ | |
#include <stdint.h> | |
#include <syscall.h> | |
#include <sys/types.h> | |
#define NULL 0 | |
#define PROT_READ 0x1 | |
#define PROT_EXEC 0x4 | |
#define MAP_PRIVATE 0x02 | |
#define SEEK_END 0x02 | |
#define AT_EXECFD 0x02 | |
#define SIGSTOP 19 | |
static pid_t getpid() | |
{ | |
pid_t ret; | |
asm volatile | |
( | |
"syscall" | |
: "=a" (ret) | |
: "0"(SYS_getpid) | |
: "rcx", "r11", "memory" | |
); | |
return ret; | |
} | |
static int kill(pid_t pid, int sig) | |
{ | |
register long rsi asm("rsi") = sig; | |
register long rdi asm("rdi") = pid; | |
int ret; | |
asm volatile | |
( | |
"syscall" | |
: "=a" (ret) | |
: "0"(SYS_kill), "r"(rdi), "r"(rsi) | |
: "rcx", "r11", "memory" | |
); | |
return ret; | |
} | |
static void stop() | |
{ | |
pid_t pid = getpid(); | |
kill(pid, SIGSTOP); | |
} | |
static void * mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset) | |
{ | |
register long r9 asm("r9") = offset; | |
register long r8 asm("r8") = fd; | |
register long r10 asm("r10") = flags; | |
register long rdx asm("rdx") = prot; | |
register long rsi asm("rsi") = length; | |
register void * rdi asm("rdi") = addr; | |
void * ret; | |
asm volatile | |
( | |
"syscall" | |
: "=a" (ret) | |
: "0"(SYS_mmap), "r"(rdi), "r"(rsi), "r"(rdx), "r"(r10), "r"(r8), "r"(r9) | |
: "rcx", "r11", "memory" | |
); | |
return ret; | |
} | |
static inline off_t lseek(int fd, off_t offset, int whence) { | |
register long rdx asm("rdx") = whence; | |
register long rsi asm("rsi") = offset; | |
register long rdi asm("rdi") = fd; | |
off_t ret; | |
asm volatile | |
( | |
"syscall" | |
: "=a" (ret) | |
: "0"(SYS_lseek), "r"(rdi), "r"(rsi), "r"(rdx) | |
: "rcx", "r11", "memory" | |
); | |
return ret; | |
} | |
static inline int close(int fd) { | |
register long rdi asm("rdi") = fd; | |
int ret; | |
asm volatile | |
( | |
"syscall" | |
: "=a" (ret) | |
: "0"(SYS_close), "r"(rdi) | |
: "rcx", "r11", "memory" | |
); | |
return ret; | |
} | |
static inline void __attribute__ ((noreturn)) _exit(int code) { | |
register long rdi asm("rdi") = code; | |
int ret; | |
asm volatile | |
( | |
"syscall" | |
: "=a" (ret) | |
: "0"(SYS_exit), "r"(rdi) | |
: "rcx", "r11", "memory" | |
); | |
} | |
struct auxv_entry { | |
uint64_t key; | |
uint64_t value; | |
} auxv_entry; | |
static uint64_t get_execfd(char * envp[]) { | |
char **evp = envp; | |
while (*evp++ != NULL); | |
struct auxv_entry * av = (struct auxv_entry *) evp; | |
for(; av->key != 0; av++) { | |
if(av->key == AT_EXECFD) { | |
return av->value; | |
} | |
} | |
_exit(1); | |
} | |
void __attribute__ ((noreturn)) _start() { | |
register long argc; | |
register char ** envp; | |
asm volatile | |
( | |
"movq (%%rsp), %0\n" | |
"lea 16(%%rsp, %0, 8), %1\n" | |
: "=r"(argc), "=r"(envp) | |
); | |
int fd = get_execfd(envp); | |
off_t len = lseek(fd, 0, SEEK_END); | |
int (*fn)() = mmap(0, len, PROT_EXEC|PROT_READ, MAP_PRIVATE, fd, 0); | |
asm volatile("jmp *%0" : : "r" (fn)); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment