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!

A deep dive into an NSO zero-click iMessage exploit: Remote Code Execution - 700

Ian Beer & Samuel Groß - Project Zero (P0)Posted 4 Years Ago
  • NSO Group is a access-as-a-service company. They will build full & weaponizable exploits to compromise computers and phones for companies. The entrypoint of choice is via text message. One weird trick is that iMeessage supports GIFs; by specifying .gif as the extension but sending another file type, it will parse this file format instead. Since file parsing is notoriously hard to do. NSO uses the "fake gif" trick to target a vulnerability in the CoreGraphics PDF parser.
  • The PDF parser appears to be Apple proprietary code. But, the JBIG2 implementation is from Xpdf, which is open source. JBIG2 format is a series of segments, which can be thought of as a series of drawing commands which are executed sequentially in a single pass. The vulnerability is an integer overflow when combining referenced segments. The overflow occurs within a loop that is continually adding the segments size together.
  • The size above is then used for a call to malloc. Since the overflow occurred, the buffer is undersized! This leads to a buffer overflow inside this buffer. This should lead to a crash though, right? 32GB of data looks would be a large overflow!
  • To avoid the crash, NSO group does a crazy trick to stop the overflow from being too large and causing a crash. By doing heap grooming, it is possible to write off the end to the GList backing buffer. This buffer stores segment information and is used to find the segments to use for the writing process. By using the overflowing write to corrupt the backing buffer pointer with pointers to bitmaps, we can cause this program not to crash! Even function pointers still work properly since the bitmap type inherits from the Segment type.
  • At this point, we have caused an overflow and the program has not crashed. So, now what? Get a more powerful primitive! By carefully lining up some other objects in memory, three more Bitmap pointers can be written to the GList buffer. By doing this, the VTable for the object and the expected size of the buffer have been altered. This gives an unbounded drawing canvas. This means that future segment commands can read and write outside of the expected buffer length!
  • This gives the attackers an relative read and a relative write in this process. You may be asking yourself "If this is a parser, then it's a single pass, right?" The JBIG2 refinement format is flexible with many different operations. By performing these operations (XOR, AND, OR and XNOR) on out of bounds elements, on the unbounded memory, you have a turing complete computer to cause all of the damage that you need.
  • What if rather than operating on glyph-sized sub-rectangles you instead operated on single bits? You can now provide as input a sequence of JBIG2 segment commands which implement a sequence of logical bit operations to apply to the page. And since the page buffer has been unbounded those bit operations can operate on arbitrary memory. Now, you have a Turing complete computer!
  • According to the author, there are over 70K segment commands defining logical bit operations to make a tiny computer. It even has registers, a 64-bit adder and a comparator to search and perform arithmetic operations. The author says "The bootstrapping operations for the sandbox escape exploit are written to run on this logic circuit and the whole thing runs in this weird, emulated environment created out of a single decompression pass through a JBIG2 stream. ". This is truly amazing and probably took this team an insane amount of time to write.
  • The author says that the sandbox escape (which will be detailed in another post), uses the mini-computer described above. This post really blew me away with what is possible with weird machines.