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!

Exploiting a Single Instruction Race Condition in Binder- 346

Maxime Peterlin & et al - Longterm SecurityPosted 5 Years Ago
  • In Android, interprocess communication is handling by Binder. Because this is a kernel-level feature that is accessible to the user, it is a very attractive attack surface.
  • The bug is a use-after-free (UAF) while the todo list elements are being processed. Essentially, another thread could come in and free this object, while it is being processed. The patch inlines the function in order to make this happen in a single step.
  • In order to trigger this bug, the following things have to happen in a very specific order in a very fast timeframe:
    1. A call to binder_release_work from the senders thread. This is the clean up routine for when a task is done under binder.
    2. A binder_work structure to dequeue from the sender thread's todo list
    3. A free on the binder_work structure from the receiver thread
  • The timeline for this vulnerability is fairly tight. But, if done properly, it is possible to replace the binder node with another object to take control of binder itself!
  • Android uses the SLUB heap allocator. This is important for triggering the UAF properly. In essence, they end up spraying 128 byte objects to eventually overlap with our vulnerable binder node. This is done by a technique described in a Project Zero post.
  • Once the UAF has been successfully triggered, are we done? No, a few more steps must be taken in order to actually exploit this. Using the UAF, there is only one interesting path that can be triggered: freeing the object again (double free). Using this, the SLUB allocator will have the same heap chunk available for allocation twice. After dealing with a few specifics of handling the double free, it is time to overlap some chunks.
  • The technique for spraying is super interesting! They solve the how do you know when the spraying has worked? By sending a bunch of signalfd (the P0 technique above), we can KNOW if the spray worked if the value is different than before. That is pretty nifty! They even have a straight forward diagram for explaining how this works for the overlapping process.
  • With two signalfd's overlapping, it can now be used to leak KASLR, when another object is tied to the signalfd. With the KASLR leak, it is time to create the arbitrary read/write primitive. On Pixel devices, the Android OS has CFI, meaning that overwriting a single pointer is not enough to take control of the kernel.
  • The authors use a technique known as Kernel Space Mirroring Attack (KSMA). This attack add an entry to the kernel's page global directory to mirror kernel code at another location that is accessible from userland. Pretty damn interesting!
  • To actually overwrite the page global directory a heap corruption (from the previous bug) is used. The technique overlaps a signalfd onto another freed object. Then, overwriting the free-list pointer (similar to the fd overwrite in GLibC Malloc) to point to our page global directory. Once this pointer is there, we can set this to whatever we like.
  • The mirror turned on, escalating to Root and taking the over the device is claimed to be fairly trivial. There is a read/write primitive in kernel memory; so, of course it is! The main thing is to set selinux_enforcing to 0 and set the credentials of the current process to the inits process.
  • Overall, this was a very good article that went into the nitty-gritty details of binder and Android. This technique used a bag of interesting tricks to eventually gain control of the device, from a single instruction race condition.