a ctf style escape journey on vmware workstation
play

A CTF-Style Escape Journey on VMware Workstation f1yyy@Chaitin.Tech - PowerPoint PPT Presentation

A CTF-Style Escape Journey on VMware Workstation f1yyy@Chaitin.Tech About us Beijing Chaitin Tech Co., Ltd(@ChaitinTech) https://chaitin.cn/en https://realworldctf.com/ Chaitin Security Research Lab Pwn2Own 2017 3 rd place


  1. A CTF-Style Escape Journey on VMware Workstation f1yyy@Chaitin.Tech

  2. About us ● Beijing Chaitin Tech Co., Ltd(@ChaitinTech) ○ https://chaitin.cn/en ○ https://realworldctf.com/ ● Chaitin Security Research Lab Pwn2Own 2017 3 rd place ○ ○ GeekPwn 2015/2016/2018/2019 awardees ■ PS4 Jailbreak, Android rooting, IoT Offensive Research, ESXi Escape ○ CTF players from team b1o0p, Tea Deliverers 2 nd place at DEFCON 2016 ■ 3 rd place at DEFCON 2019 ■ 1 st place at HITCON 2019 ■

  3. Before we start ● VMM(Hypervisor) : Virtual Machine Monitor ● Guest OS ● Host OS

  4. What is Virtual Machine Escape ... Guest OS Guest OS ... Guest OS 0 1 N VMM Host OS Normally, all of the sensitive behaviors of guest OS will be sanitized by the hypervisor

  5. What is Virtual Machine Escape ... Guest OS Guest OS ... Guest OS 0 1 N VMM Host OS

  6. What is Virtual Machine Escape ... Guest OS Guest OS ... Guest OS 0 1 N exploitation VMM Host OS

  7. What is Virtual Machine Escape ... Guest OS Guest OS ... Guest OS 0 1 N exploitation VMM Execute arbitrary codes network connection on the host Host OS

  8. Introduction of VMware Workstation

  9. Architecture User mode Host OS Physical Hardware

  10. Architecture after vmware runs Host World VM World User mode VM VM VM vmware-vmx vmmon Host OS VM Monitor Physical Hardware

  11. Architecture after vmware runs Host World VM World User mode VM VM VM vmware-vmx vmmon Host OS VM Monitor Physical Hardware

  12. Architecture after vmware runs Host World VM World User mode VM VM VM vmware-vmx vmmon Host OS VM Monitor Physical Hardware

  13. Attack Surface Graphic Ethernet USB SATA SCSI COM

  14. Attack in Recent Years (Pwn2Own 2017) Graphic Ethernet (TianfuCup 2018) USB (Pwn2Own 2019) SATA SCSI COM

  15. Our Target (Pwn2Own 2017) Graphic Ethernet (TianfuCup 2018) USB (Pwn2Own 2019) SATA SCSI COM

  16. CVE-2019-5541 Analysis

  17. How e1000e works? e1000e virtual network card registers TDT TDH Guest OS TDBAL TDBAH

  18. How e1000e works? e1000e virtual network card registers write TDT TDH Guest OS TDBAL TDBAH

  19. How e1000e works? e1000e virtual network card registers packet transfer write TDT mem = registers[TDBAH]<<32|registers[TDBAL]; mem = mem + registers[TDH]*sizeof(transfer); ReadGuestMem(mem,&transfer); TDH //Handle transfer struct ... Guest OS ... registers[TDH]++; TDBAL if(registers[TDH]==registers[TDT]) return; else TDBAH loop;

  20. How e1000e works? e1000e virtual network card union{ packet transfer struct{ uint64_t buf_addr; mem = registers[TDBAH]<<32|registers[TDBAL]; uint64_t size; mem = mem + registers[TDH]*sizeof(transfer); }transfer_data; ReadGuestMem(mem,&transfer); struct{ //Handle transfer struct uint8_t ipcss; //IP checsum start ... uint8_t ipcso; //IP checsum offset ... uint16_t ipcse; //IP checsum end registers[TDH]++; uint8_t tucss; //TCP checsum start if(registers[TDH]==registers[TDT]) uint8_t tucso; //TCP checsum offset return; uint16_t tucse; //TCP checsum end else uint32_t cmd_and_length; loop; uint8_t status; //Descriptor status uint8_t hdr_len; //Header length uint16_t mss; //Maximum segment size }prop_desc; }tranfer;

  21. How e1000e works? e1000e virtual network card packet transfer mem = registers[TDBAH]<<32|registers[TDBAL]; if(transfer.length & E1000_TXD_CMD_DEXT) mem = mem + registers[TDH]*sizeof(transfer); e1000_process_TXD_CMD_DEXT(...); ReadGuestMem(mem,&transfer); else //Handle transfer struct //init e1000e property ... prop = &e1000e->prop; ... prop->ipcss = transfer.prop_desc.ipcss; registers[TDH]++; ... if(registers[TDH]==registers[TDT]) return; else loop;

  22. How e1000e works? e1000e virtual network card packet transfer mem = registers[TDBAH]<<32|registers[TDBAL]; if(transfer.length & E1000_TXD_CMD_DEXT) mem = mem + registers[TDH]*sizeof(transfer); e1000_process_TXD_CMD_DEXT(...); ReadGuestMem(mem,&transfer); else //Handle transfer struct //init e1000e property ... prop = &e1000e->prop; ... prop->ipcss = transfer.prop_desc.ipcss; registers[TDH]++; ... if(registers[TDH]==registers[TDT]) return; else loop;

  23. CVE-2019-5541 void __usercall e1000_process_TXD_CMD_DEXT() { ... packet = e1000_init_packet(...); if(packet){ ... e1000_send_packet(...,packet); } ... }

  24. CVE-2019-5541 void __usercall e1000_init_packet(...) { ... if(flag_if_not_ipv6_GSO){ ip_checsum_start = ipcss; if(ipcss > hdr_size || ipcso > hdr_size || ipcse > hdr_size-ipcse || hdr_size - ipcso < 2) goto error ) } else{ ip_checksum_start = ipcss; } ... }

  25. CVE-2019-5541 void __usercall e1000_init_packet(...) { ... if(flag_if_not_ipv6_GSO){ flag_if_not_ipv6_GSO will be false when guest is sending ip_checsum_start = ipcss; IPv6 Large Segmentation Offload packets if(ipcss > hdr_size || ipcso > hdr_size || ipcse > hdr_size-ipcse || hdr_size - ipcso < 2) goto error ) } else{ ip_checksum_start = ipcss; } ... }

  26. CVE-2019-5541 void __usercall e1000_init_packet(...) { ... if(flag_if_not_ipv6_GSO){ ip_checsum_start = ipcss; if(ipcss > hdr_size || ipcso > hdr_size || ipcse > hdr_size-ipcse || hdr_size - ipcso < 2) goto error ) } else{ No check of ipcss anymore! ip_checksum_start = ipcss; } ... }

  27. CVE-2019-5541 e1000e virtual network card packet transfer mem = registers[TDBAH]<<32|registers[TDBAL]; if(transfer.length & E1000_TXD_CMD_DEXT) mem = mem + registers[TDH]*sizeof(transfer); e1000_process_TXD_CMD_DEXT(...); ReadGuestMem(mem,&transfer); else //Handle transfer struct //init e1000e property ... prop = &e1000e->prop; ... prop->ipcss = transfer.prop_desc.ipcss; registers[TDH]++; ... if(registers[TDH]==registers[TDT]) return; else loop; where does ipcss come from

  28. Preliminary Exploit Primitive void __usercall e1000_init_packet(...) { ... hdr_size = hdr_len + vlan_size; //vlan_size will be 4 or 0 sigment_num = (mss + pay_size - 1) / mss; ... simple_segment_size = (mss+hdr_size+0x11)&0xfffffff8; packet = malloc(sigment_num * simple_segment_size); ... if(mss){ buf = &packet[ipcss+10]; data = hdr + mss - ipcss; if(flag_0) *(buf+2) = htons(data); } ... }

  29. Preliminary Exploit Primitive void __usercall e1000_init_packet(...) { ... hdr_size = hdr_len + vlan_size; //vlan_size will be 4 or 0 sigment_num = (mss + pay_size - 1) / mss; ... simple_segment_size = (mss+hdr_size+0x11)&0xfffffff8; packet = malloc(sigment_num * simple_segment_size); ... if(mss){ buf = &packet[ipcss+10]; data = hdr + mss - ipcss; if(flag_0) *(buf+2) = htons(data);//heap overflow write happens! } ... }

  30. Preliminary Exploit Primitive void __usercall e1000_init_packet(...) { ... ... cur_buffer = packet; transfer_pay_size = pay_size; while(idx < sigment_num){ ... //copy data from guest into packet ... cur_buffer = cur_buffer + simple_segment_size; transfer_pay_size = transfer_pay_size - mss; ... if(transfer_pay_size <= mss){ change_ip_head(cur_buffer+ipcss+10, mss - transfer_pay_size, flag_if_not_ipv6_GSO); ...

  31. Preliminary Exploit Primitive void __usercall e1000_init_packet(...) { ... ... cur_buffer = packet; transfer_pay_size = pay_size; while(idx < sigment_num){ ... //copy data from guest into packet ... cur_buffer = cur_buffer + simple_segment_size; transfer_pay_size = transfer_pay_size - mss; ... if(transfer_pay_size <= mss){ change_ip_head(cur_buffer+ipcss+10, mss - transfer_pay_size, flag_if_not_ipv6_GSO);//heap out-of-bounds write happens ...

  32. Preliminary Exploit Primitive void __usercall e1000_init_packet(...) { void __usercall change_ip_head( ... ... uint16_t *buf,int size,int flag ) { cur_buffer = packet; ... transfer_pay_size = pay_size; if(flag){ while(idx < sigment_num){ ... ... } //copy data from guest into packet else{ ... tmp = ntohs(buf[2]); cur_buffer = cur_buffer + simple_segment_size; buf[2] = htons(tmp - size); transfer_pay_size = transfer_pay_size - mss; ... ... if(transfer_pay_size <= mss){ change_ip_head(cur_buffer+ipcss+10, mss - transfer_pay_size, flag_if_not_ipv6_GSO);//heap out-of-bounds write happens ...

  33. Preliminary Exploit Primitive void __usercall e1000_init_packet(...) { void __usercall change_ip_head( ... ... uint16_t *buf,int size,int flag ) { cur_buffer = packet; ... transfer_pay_size = pay_size; if(flag){ while(idx < sigment_num){ ... ... } //copy data from guest into packet else{ ... tmp = ntohs(buf[2]); cur_buffer = cur_buffer + simple_segment_size; buf[2] = htons(tmp - size); transfer_pay_size = transfer_pay_size - mss; ... ... if(transfer_pay_size <= mss){ change_ip_head(cur_buffer+ipcss+10, mss - transfer_pay_size, flag_if_not_ipv6_GSO);//heap out-of-bounds write happens ... We can do “special” heap out-of-bounds subtraction

Download Presentation
Download Policy: The content available on the website is offered to you 'AS IS' for your personal information and use only. It cannot be commercialized, licensed, or distributed on other websites without prior consent from the author. To download a presentation, simply click this link. If you encounter any difficulties during the download process, it's possible that the publisher has removed the file from their server.

Recommend


More recommend