#include #include #include #include #include #include #include #include #include extern void cat(int fd, long sz); #ifndef __FreeBSD__ #include #define SYSCT_FBSD 588 uint8_t sel = SYSCALL_DISPATCH_FILTER_ALLOW; uint16_t scmap[SYSCT_FBSD] = { -1, // SYS_syscall needs args shifted SYS_exit, -1, // SYS_fork needs sud reset SYS_read, SYS_write, SYS_open, SYS_close, -1, // wait4 -1, // [old] creat SYS_link, SYS_unlink, -1, // [obsolete] execv SYS_chdir, SYS_fchdir, -1, // [freebsd11] mknod SYS_chmod, SYS_chown, -1, // break (no manual) -1, // [freebsd4] getfsstat -1, // [old] lseek SYS_getpid, }; // TODO also create trampoline for freebsd native signals void systrap(int n, siginfo_t* s, ucontext_t* c) { sel = SYSCALL_DISPATCH_FILTER_ALLOW; if(s->si_code != /* SYS_USER_DISPATCH - value from */ 2) { // TODO chain old syscall handler } else if(s->si_syscall > SYSCT_FBSD-1) { // TODO fail - check how freebsd does this, esp. with nosys entries } else if(scmap[s->si_syscall] == -1) { switch(s->si_syscall) { default: abort(); break; } } // TODO find max arg ct. and check stack if needed c->uc_mcontext.gregs[13] = syscall( scmap[s->si_syscall], c->uc_mcontext.gregs[8], c->uc_mcontext.gregs[9], c->uc_mcontext.gregs[12] ); //for(int i = 0; i < 23; i++) printf("%i: %lX\n", i, c->uc_mcontext.gregs[i]); sel = SYSCALL_DISPATCH_FILTER_BLOCK; } #endif typedef struct { uint8_t magic[4]; uint8_t bits; uint8_t endian; uint8_t hdrver; uint8_t abi; uint8_t pad[8]; uint16_t type; uint16_t isa; uint32_t ver; uint64_t ep; uint64_t phtable; uint64_t shtable; uint32_t flags; uint16_t hsz; uint16_t phtesz; uint16_t phtct; uint16_t shtesz; uint16_t shtct; uint16_t nameind; } __attribute__((packed)) elf; #ifndef __FreeBSD__ char** getmaps(int* tsz) { int fd = open("/proc/self/maps", O_RDONLY); char c; *tsz = 0; int p = 0, s = 128; char** t = malloc(sizeof(char*)); t[0] = malloc(s); while(read(fd, &c, 1)) { if(c == '\n') c = 0; t[*tsz][p++] = c; if(p >= s) t[*tsz] = realloc(t[*tsz], s += 8); if(!c) { t = realloc(t, ((++(*tsz)) + 1) * sizeof(char*)); t[*tsz] = malloc(s = 128); p = 0; } } (*tsz)++; close(fd); return t; } typedef struct { uint64_t start; uint64_t len; uint8_t rwx; char* name; } map; void stomap(char* s, map* m) { m->start = 0; m->len = 0; m->rwx = 0; while(*s != '-') { m->start <<= 4; if(*s >= '0' && *s <= '9') m->start |= *s - '0'; else m->start |= *s - 'a' + 10; s++; } s++; while(*s != ' ') { m->len <<= 4; if(*s >= '0' && *s <= '9') m->len |= *s - '0'; else m->len |= *s - 'a' + 10; s++; } s++; for(int i = 0; i < 3; i++) { m->rwx <<= 1; m->rwx |= (*(s++) != '-'); } s += 2; while(*(s++) != ':'); while(*(s++) != ' '); while(*s >= '0' && *s <= '9') s++; while(*(++s) == ' '); int d = strlen(s) + 1; m->name = memcpy(malloc(d), s, d); m->len -= m->start; } #endif int main(int argc, char** argv) { #ifndef __FreeBSD__ struct sigaction a, oa; sigemptyset(&a.sa_mask); a.sa_flags = SA_SIGINFO; a.sa_sigaction = (void(*)(int, siginfo_t*, void*))systrap; int nm; char** smaps = getmaps(&nm); for(int i = 0; i < nm-1; i++) if(strstr(smaps[i], "libc")) { map rmap; stomap(smaps[i], &rmap); if(rmap.rwx & 1) prctl(PR_SET_SYSCALL_USER_DISPATCH, PR_SYS_DISPATCH_ON, rmap.start, rmap.len, &sel); } for(int i = 0; i < nm; i++) free(smaps[i]); free(smaps); #endif if(argc < 2) return printf("no file provided\n"); int fd = open(argv[1], O_RDONLY); struct stat s; fstat(fd, &s); #ifndef __FreeBSD__ sigaction(SIGSYS, &a, &oa); sel = SYSCALL_DISPATCH_FILTER_BLOCK; #endif cat(fd, s.st_size); }