Automating VMware RPC Request Sniffing

January 19, 2018 | Abdul-Aziz Hariri

Last year, my colleagues and I spoke about different VMware topics at various conferences. One of the topics we covered was RPC tooling, as we detailed writing tools to interact with the RPC interface. We also briefly discussed how to sniff the RPC requests to help with exploit development, debugging RPC requests, or even fuzzing. Since RPC was only briefly covered in our previous presentations, I decided to blog about it here.

This small bit of research was triggered by my frustration with VMware tooling. At the time, I was learning how to exploit a VMware vulnerability, and I needed to see how my RPC requests were being sent to the host. Not finding a tool available, I decided to write my own.

In this blog, I will discuss how I was able to write a PyKD script to sniff RPC requests that helped me tremendously while writing VMware RPC exploits.

Details

RPC requests can be sent from the guest to the host in different ways: backdoor channel, vsockets, etc. This blog covers the GuestRPC requests sent from the backdoor channel. I’m not going to dive into how the backdoor channel works. What’s important to know for now is that the backdoor function responsible for sending GuestRPC messages is BDOOR_CMD_MESSAGE with opcode 0x1E. A full list of the backdoor channel functions can be found in backdoor_def.h in the open-vm-tools git repo.

One of my main objectives was to find where the RPC requests were being parsed. An approach that helped was finding where one of the RPC functions was located, then debugging where that function was being called by sending the RPC request. Sending a test RPC request is quite easy using the rpctool.exe shipped with VMware tools.

In IDA, if we string-search for “vmx.capability.copypaste_version” and follow the hit, we will end up in an rdata section:

If we follow that XREF, we will end up in the following chunk of code:

If we take a closer look at sub_140084230, we will notice that it’s where vmx.capability.copypaste_version is implemented:

The next step is to set a breakpoint at that function and check where it was called from to determine where the requests are being initially parsed.

In this case, the breakpoint should be set at vmware_vmx+0x84230 (for VMware Workstation 12.5.8).

If we take a closer look at the function at vmware_vmx+0x69486, we find that it’s actually the function that parses the request before dispatching it to the matching RPC function. In this instance, that’s vmx.capability.copypaste_version.

The logic of this function is simpler than it seems. In a nutshell, the RPC request is passed as an argument. The function first checks whether the RPC request contains a valid RPC function to call. That’s accomplished by looping over the built-in functions and strncmp’ing the function in the request. If the function is found, it then checks whether or not there are sufficient permissions for it to execute. If there are sufficient permissions, it will execute the RPC function.

We can start dumping the RPC requests from WinDBG using the following breakpoint:

      bp vmware_vmx+OFFSET “.echo;db r8 r8+r9;g;”

Tooling

Since we now have all the ingredients, we can go further and write a PyKD script to automate all the work for us. The logic of script is pretty simple:

  1. Attach to vmware_vmx.exe
  2. Set a breakpoint at the function that parses the RPC request
  3. The breakpoint callback function should dump r9 bytes from r8, since r8 holds the request and r9 is the size of the request
  4. Continue

First we will have to initialize then attach to the process using the initialize and attachProcess API’s:

Breakpoints are set using the setBp function, which takes the address of the function where the breakpoint should be set and a callback function:

The callback function uses loadBytes to read the bytes from r8:

Here’s a demonstration of the sniffer in action:

Conclusion

Now that we’re able to sniff this traffic in real time, we can understand how certain requests are being sent that would ease exploit development or even fuzzing. Bugs in VMware – and other virtualization software – are an interesting field of study. The impact of these bugs can be far reaching, as these programs are generally considered required tools for information security practitioners. We at the ZDI would like to see additional public research in these products to help close off the security gaps, and the ability to sniff these communications is a good start. If you haven’t already, check out these other recent posts about VMware bugs for more inspiration. Happy (bug)hunting!

You can find me on Twitter at @AbdHariri, and follow the team for the latest in exploit techniques and security patches.