Resources

People often ask me "How did you learn how to hack?" The answer: by reading. This page is a collection of the blog posts and other articles that I have accumulated over the years of my journey. Enjoy!

CVE-2024-21115: An Oracle VirtualBox LPE Used to Win Pwn2Own - 1412

Cody Gallagher - ZDIPosted 1 Year Ago
  • Within the VGAState struct of VirtualBox there is a bitmap used for tracking dirty pages of a VRAM buffer. This bitmap is large enough to use the maximum vram allowed by vbox at 256MB. When clearing the dirty bits, the start_addr is incorrectly multiplied by 4! If the address is larger than 64MB, then leads to an out of bounds access.
  • What primitive does this give us? A heap based bit clear. Doesn't seem like a lot and seems inconsistent on the location. To trigger the bug, they set a bunch of setting within the ioport communication. How is this exploitable?
  • Within VGAState, there is a section called CritSect. This is a critical section that can only be used by one thread at a time for in and out instructions for each devices MMIO region. The cLockers variable is effectively a locking variable to ensure that other threads don't access it at the same time. By abusing a bit clear, it could be possible to create an artificial race condition here.
  • Using this race condition, there is a problem though: there is a secondary check on the ownership that will crash changing the owner . The flag RTCRITSECT_FLAGS_NOP determines whether locking operations are checked at all, which controls the check above. The idea is to use the original exploitation path to change the flag BEFORE the crash happens. Then, after that, we can continue using the race condition for other things.
  • With the protections removed on the race condition detection, corruption is much easier to cause. The primitive used for corrupting the flag with the function vbe_ioport_write_data can be used once again to corrupt the size of the buffer cScratchRegion. With the size corrupted, it creates an easy out of bounds read and write.
  • After the VGAState variable is PDMPCIDEV. Since this is part of the initial allocation, it's always in the same spot! It contains several function pointers, leading to easy code execution. Even with CFG turned on it doesn't matter because we control the pointer and two of the parameters being passed in.
  • It's crazy how such a little bug turned into such a large impact. Awesome post on exploit development!