101 lines
2.9 KiB
C
101 lines
2.9 KiB
C
#include <stdlib.h>
|
|
#include <stdint.h>
|
|
#include <stdio.h>
|
|
#include <fcntl.h>
|
|
#include <sys/syscall.h>
|
|
#include <unistd.h>
|
|
#include <stdbool.h>
|
|
|
|
void crimes_startup_run(uint8_t* frame) {
|
|
// we trash argv up to hack on ld.so arguments without needing malloc
|
|
// this is pad space to catch that and not explode uwu
|
|
volatile char _pad[(sizeof(char*) * 4)];
|
|
|
|
// XXX: assumes stack goes up
|
|
// big weh
|
|
size_t argc = *((size_t*) (frame + sizeof(size_t)));
|
|
char** argv = ((char**) (frame + sizeof(size_t) + sizeof(char*)));
|
|
char** envp = argv + argc + 1;
|
|
|
|
// fake usage of _pad
|
|
// also a barrier to ensure argc gets read
|
|
asm volatile("" :: "rm"(_pad) : "memory");
|
|
|
|
syscall(SYS_write, STDOUT_FILENO, "[crimes] detect maps\n", 21);
|
|
|
|
int fd = syscall(SYS_open, "/proc/self/maps", O_RDONLY);
|
|
if (fd < 0) {
|
|
syscall(SYS_write, STDOUT_FILENO, "[crimes] open failed\n", 21);
|
|
syscall(SYS_exit, -1);
|
|
}
|
|
char buf[32];
|
|
int state = 0;
|
|
while (true) {
|
|
ssize_t res = syscall(SYS_read, fd, buf, sizeof(buf));
|
|
if (res == 0) {
|
|
break;
|
|
} else if (res < 0) {
|
|
syscall(SYS_write, STDOUT_FILENO, "[crimes] read error\n", 20);
|
|
syscall(SYS_exit, -1);
|
|
}
|
|
|
|
for (ssize_t i = 0; i < res; i++) {
|
|
switch (state) {
|
|
case 0:
|
|
if (buf[i] == '/') { state++; }
|
|
else { state = 0; }
|
|
break;
|
|
case 1:
|
|
if (buf[i] == 'l') { state++; }
|
|
else { state = 0; }
|
|
break;
|
|
case 2:
|
|
if (buf[i] == 'd') { state++; }
|
|
else { state = 0; }
|
|
break;
|
|
case 3:
|
|
if (buf[i] == '-') { state++; }
|
|
else { state = 0; }
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
if (state > 3) {
|
|
break;
|
|
}
|
|
}
|
|
if (state > 3) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (state > 3) {
|
|
syscall(SYS_write, STDOUT_FILENO, "[crimes] detected libc. going back to startup\n", 46);
|
|
return;
|
|
}
|
|
|
|
syscall(SYS_write, STDOUT_FILENO, "[crimes] running ld.so\n", 23);
|
|
|
|
// XXX: currently we hardcode the glibc parameters
|
|
// detect glibc or musl at runtime and load the appropriate params
|
|
char* ld = "/usr/lib/ld-2.32.so";
|
|
char* pl = "--preload";
|
|
char* ldlp =
|
|
"/usr/lib/libm.so.6:/usr/lib/libpthread.so.0:/usr/lib/libdl.so.2:/usr/lib/libc.so.6";
|
|
uintptr_t args[4 + argc];
|
|
args[0] = (uintptr_t)ld;
|
|
args[1] = (uintptr_t)pl;
|
|
args[2] = (uintptr_t)ldlp;
|
|
|
|
for (size_t i = 0; i < argc; i++) {
|
|
args[3 + i] = (uintptr_t) argv[i];
|
|
}
|
|
|
|
args[3 + argc] = 0;
|
|
|
|
syscall(SYS_execve, ld, args, envp);
|
|
|
|
syscall(SYS_write, STDOUT_FILENO, "[crimes] exec failed!\n", 22);
|
|
syscall(SYS_exit, -1);
|
|
}
|