Skip to content

Instantly share code, notes, and snippets.

@hashbrowncipher
Created August 21, 2021 22:35
Show Gist options
  • Save hashbrowncipher/cbd50a376473779059264cb6d309cf35 to your computer and use it in GitHub Desktop.
Save hashbrowncipher/cbd50a376473779059264cb6d309cf35 to your computer and use it in GitHub Desktop.
A little x86-64 loader for Linux's binfmt_misc.
/*
* 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