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!

Zoom RCE from Pwn2Own 2021- 592

Thijs Alkemade & Daan Keuper - Sector7Posted 4 Years Ago
  • Most users will mainly know the video chat functionality, but there is also a quite full featured chat client included, with the ability to send images, create group chats, and many more. Within meetings, there’s of course audio and video, but also another way to chat, send files, share the screen, etc. We made a few premium accounts too, to make sure we saw as much as possible of the features.
  • When starting to reverse the application they found a large quantity of the libraries to be apart of an open source SDK. As a result, they decided to target these. Most of the Zoom code is written in C++, which has many nice foot-guns removed from C.
  • The authors noticed an interesting but benign issue when OpenSSL functions were being used. The size of the buffer being created for a base64 function should be 3/4 of the size. However, a buffer is created by shifting the size by 4. Although this is not a vulnerability, it is a code smell! Because of this code smell, they decided to look at all of the handling for OpenSSL integration.
  • The paid version of Zoom includes an Advanced Chat Encryption. When doing this, a handshake process takes place where some encryption is done. While decrypting, a fixed size buffer of 1024 bytes is used for AES However, there is no validation that the decryption result will fit into the buffer for AES, unlike RSA.
  • As a result, a heap-based buffer overflow could occur by sending a message that needed to be decrypted. This overflow is fairly ideal since we control the size and all of the bytes being sent over. But, exploiting bugs in real life is MUCH more complicated than in a CTF.
  • This article has extensive knowledge on how the Windows heap allocator works. I'll summarize a few points here:
    • Windows has two different heaps: Segment Heap for very specific applications and NT Heap for everything else. In the NT heap, there are the front-end/Low-Fragmentation Heap and the back-end allocator.
    • The back-end allocator is fully deterministic and functions like the GLibC malloc implementation. The LFH is used for sizes that are requested often and has a bit of randomization involved with it.
    • If more than 17 blocks of a specific size range are allocated and still in use, then the LFH will start handling that specific size from then on.
    • Each heap allocation (of less than 16 kB) has a header of eight bytes. The first four bytes are encoded, the next four are not. The encoding uses a XOR with a random key, which is used as a security measure against buffer overflows corrupting heap metadata.
  • Grooming the heap is just the right way took a significant amount of effort and testing to get properly. They needed to line up the proper object with a function pointer close enough to overwrite them in OpenSSL (no CFG on these functions). Additionally, they required an information leak to break ASLR.
  • For the information leak, they targeted a different part of the application. By finding a link that the authors could control, they would overwrite the URL that was being sent back for the connection. This overwrite would corrupt the NULLbyte, resulting in a bunch of extra data being sent. A little bit more groomer had to be done in order to put an OpenSSL object after our URL.
  • After hours upon hours of trying different TLS settings, orderings and things they got the leak to work! They found that using TLS renegotiation made the exploit much more stable by spraying the object we wanted to leak in the URL over and over again.
  • With the leak armed, they could go tackle the code execution problem. The class FileWrapperImpls had an insane amount of function pointers to overwrite. By lining this up next to our overflow, we can corrupt these values and jump to whatever we want!
  • To get code execution via a function pointer means we start with COP or call orientated programming. The next step is getting a stack pivot; but, we still need to know where to write to. The second problem was solved by sending a bunch of GIFs to file up the address space. If we fill up the address space we can make an educated guess of where the new stack will be at.
  • The COP chain starts by calling a gadget that allows us to control the RSP value afterwords. This gadget pushes value we control then pops it directly into RSP: how convenient! With control over the RSP, we can start a standard ROP chain.
  • The ROP chain calls VirtualProtect over the region where our GIF may be at after calling a different function to get the address of our region. Since we control all of the contents of the GIF, this is a perfect location to make executable. Finally, we have got arbitrary code execution!
  • Overall, this article has very good insights into competing in Pwn2Own. Additionally, the methodology and bugs found are amazing for learning how to make real exploits.