On 2018-08-14, VMWare released both VMware Workstation 14.1.13 and VMware Fusion 10.1.3. In the same day, it was released the advisory VMSA-2018-0022, that claims this new version contains a fix to an out-of-bounds write vulnerability in the e1000 device. The CVE-2018-6973 was assigned to this vulnerability. As I have been doing some research with VMWare Fusion in the last months, I’ve decided to take a look at this vulnerability.
By performing a binary diffing between the vmware-vmx binary of the VMWare Fusion 10.1.2 and 10.1.3, I’ve found two interesting new validations, see Figure 1 and Figure 2.


It seems it is checking whether the MSS size and/or Payload length of a packet is equal to zero. Further analysis showed that these new validations were implemented inside the VMWare’s e1000 virtual device TCP Segmentation Offload engine. By tracking these values through the code we reach the following snippet of code:

In order to execute the code inside the if statement the MSS value must be different of zero, but what happens when payload length is equal to zero? The number of segments will be always equal to zero. Some instructions below the calculation of the number of segments we see an interesting call:

This snippet of code seems to be allocating space for the new packets that will be generate by the segmentation of the original packet. Whenever the number of segments is equal to zero, the result of the multiplication will be equal to zero, this way the call to malloc(0) will return a pointer to a buffer with size equal to zero.
In order to play with this vulnerability I’ve obtained the kernel sources for the GNU/Linux used as the guest. And then, I’ve made some modifications with the original e1000 device driver to force the payload to be equal to zero when the driver ask the e1000 TSO implementation to segment the packet. To this, I’ve just added the following lines (packet dump code from https://gist.github.com/smihir/b67abc4299c888a31c34) in the e1000_main.c source file, function e1000_xmit_frame():

In order to trigger the vulnerability, I’ve loaded the modified driver and just navigated to some of my favorites websites and as expected, the virtual machine has crashed. After some debugging, I’ve found that the first attempt to write to the buffer is a call to memcpy() that copies some data to the position buffer + 10 with the size of 34 bytes. The data copied is the original headers (Ethernet + IP) of the packet with the fields Total Length and Header Checksum equal to zero, meaning we can control most of the data that corrupts the adjacent heap chunk. Nice, now how can we exploit it? It is left as an exercise to the astute reader, or maybe in a next post. Thank You.