Thursday, December 1, 2016

BitUnmap: Attacking Android Ashmem

Posted by Gal Beniamini, Project Zero

The law of leaky abstractions states that “all non-trivial abstractions, to some degree, are leaky”. In this blog post we’ll explore cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ashmem shared memory interface provided by Android and see how false assumptions about its internal operation can result in security vulnerabilities affecting core system code.

We’ll walk through cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 process of discovering and exploiting a vulnerability resulting from this leaky abstraction, which will allow us to elevate our privileges from any Android application to a multitude of privileged contexts, including cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 highly-privileged “system_server”. This vulnerability has been present in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 core Android platform code for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Marshmallow and Nougat versions. It has now been fixed in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 recent Android bulletin. For a detailed disclosure timeline, see cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 “Timeline” section below.

One Device to Bind Them


As you know, Android applications can perform inter-process communication (for example, in order to communicate with various Android services), by using cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Android binder. Initially, each Android service registers itself with a central daemon; cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 “service manager”. Subsequently, applications may contact cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 daemon in order to request “handles” with which cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 registered services may be contacted.

In keeping with good IPC design, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 interface provided by binder itself is racá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r simplified. In fact, binder transactions are capped to a size of at-most 1MB. Well cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n, what about scenarios in which we need to transfer a large amount of data to a system service? For example, what if we want to modify cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 phone’s wallpaper? What about playing a media file? Surely we wouldn’t need to “re-invent” a mechanism through which memory can be shared in larger quantities between processes using binder transactions.

Indeed, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re’s no need to worry. You see, binder transactions support cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 transfer of more than just binary data. In fact, binder transactions can be used to transfer file descriptors and even ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r binder handles. For instance, this is how cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 “service manager” is able to provide processes with handles through which cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y may communicate with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 requested services.

binder.png

Great, so we have a means of communicating with ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r processes - even in large volumes. But what about cases where we’d like to share (racá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r than simply transfer) large quantities of memory? Once again - no need to worry! For this purpose, Android has introduced a means of sharing memory, called “ashmem” (Android Shared Memory).

Sharing (memory) is Caring


So what exactly is ashmem? In short, each ashmem file descriptor acts as a handle to a shared memory region. The device also allows cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 user to perform several memory-sharing operations via a set of supported ioctls. These allow cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 user to set cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 size of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 shared memory region referred to by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ashmem file descriptor, modify cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 name of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 shared region and even control cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 protection mask with which this descriptor may be mmap-ed.

Let’s take a closer look at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 actual implementation of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ashmem device, starting with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ioctl used to control cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 size of a shared memory region - ASHMEM_SET_SIZE:

static long ashmem_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
   struct ashmem_area *asma = file->private_data;
   long ret = -ENOTTY;
   switch (cmd) {
       

     ...
   }
   return ret;
}

As we can see above, this ioctl simply allows cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 user to pass in any size. As long as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 shared memory region has not been mapped yet, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 device will happily record cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 passed-in size as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 underlying size corresponding to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 memory region. Not only that, but cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 recorded size can cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n be queried by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 user by issuing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 corresponding ioctl - ASHMEM_GET_SIZE.

So… this looks racá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r suspicious. What exactly does “setting cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 size” actually mean? Recall that ashmem regions are mapped-in by calling mmap, and, as we know, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 mmap syscall receives an argument denoting cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 size of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 mapping to be created.

This begs cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 question: what if cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 size of a created mapping does not match cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 size of an ashmem region? Perhaps cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 implementation of mmap will simply ignore cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 passed in size argument and use cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 size provided in ASHMEM_SET_SIZE? Perhaps, instead, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 implementation of mmap will simply ignore cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 underlying size and use cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 size argument instead? There’s only one way to find out:

static int ashmem_mmap(struct file *file, struct vm_area_struct *vma)
{
   struct ashmem_area *asma = file->private_data;
    ...
   if (!asma->file) {
       ...
       vmfile = shmem_file_setup(name, asma->size, vma->vm_flags);
       ...
       asma->file = vmfile;
   }
   ...
   vma->vm_file = asma->file;
   mutex_unlock(&ashmem_mutex);
   return ret;
}

As we can see above, while cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 actual shared memory file is created using cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 size of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 shared memory region (using “shmem_file_setup”), cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 memory mapping itself is created using cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 size in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 virtual memory area (vma) - that is, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 size passed in to mmap.

Let’s take a step back and reflect on this decision.

Essentially, this means that developers who attempt to use an ashmem region must take special care to always call mmap using cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same size of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 underlying shared memory region. Failing to do so will not return any visible error code to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 developer, but will instead create a mapping with potentially dangerous consequences.

For starters, if a developer mmap-s a region with a size larger than cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 actual underlying region’s size, any attempt to access memory beyond cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 bounds of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 underlying region will result in a illegal access, sending cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 SIGBUS signal to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 process (which will cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n probably subsequently terminate).

But cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re’s anocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r, more interesting, potential pitfall. What if cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 developer erroneously assumes that size of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 underlying shared memory region and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 mmap-ed size must be equal to one anocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r? To try and answer this question, I’ve audited all instances of Android services which use ashmem to share memory with a user. From here on, we’ll focus on one such case - Bitmaps.

Mismatching Assumptions


As we mentioned earlier, one operation which requires cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 transfer of potentially large quantities of memory from one process to anocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 exchange of images. For this purpose, Android exposes cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Bitmap class, which can be easily serialized into a binder parcel.

As Bitmaps may be larger than cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 1MB limit for binder transactions, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 image’s data must be transferred via ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r means - such as ashmem. Indeed, for bitmaps above a certain size, this is exactly how this data is transferred. We can see that by looking at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 “unflattening” function, “Bitmap_createFromParcel”:


   android::Parcel* p = android::parcelForJavaObject(env, parcel);
   const SkColorType colorType = (SkColorType)p->readInt32();
   const SkAlphaType alphaType = (SkAlphaType)p->readInt32();
   const int width = p->readInt32();
   const int height = p->readInt32();
   const int rowBytes = p->readInt32();
   …
   std::unique_ptr<SkBitmap> bitmap(new SkBitmap);
   if (!bitmap->setInfo(SkImageInfo::Make(width, height, colorType, alphaType), rowBytes)) {
       return NULL;
   }
   …
   …
}

First, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 image’s metadata is extracted from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 parcel and is used to construct an SkBitmap instance to hold this information. Next, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 function proceeds to reads cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 actual bitmap’s data by calling Parcel::readBlob.

However, this looks potentially dangerous! First of all, note that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 function uses cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 SkBitmap instance (i.e., cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 one holding all cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 metadata we read earlier on) in order to calculate cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 “size” of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 resulting bitmap’s data. Then, it calls Parcel::readBlob in order to actually read cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 transferred data, while using cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 previously calculated size as an input argument.

Finally, let’s take a look at how Parcel::readBlob actually reads cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 enclosed Bitmap’s data:

   …
   int fd = readFileDescriptor();
   ...
   void* ptr = ::mmap(NULL, len,
                                   isMutable ? PROT_READ | PROT_WRITE : PROT_READ,
                                   MAP_SHARED, fd, 0);
   ...
   return NO_ERROR;
}

Aha! This is exactly what we were looking for. Instead of using cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 underlying size of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 memory region, Parcel::readBlob performs an mmap operation using our own controlled length argument (i.e., cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 size computed from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 bitmap’s metadata).

In and of itself, this is already a bad practice; cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 user could pass in an ashmem descriptor with any arbitrary size, resulting in an “invalid” memory mapping of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 type we discussed earlier. This, in turn, would trigger a SIGBUS if cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 receiving application attempts to access cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 mmap-ed memory region.

But perhaps we can do better than just creating an invalid mapping? We’ve seen how cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 memory is mapped-in when creating a Bitmap, but how is it unmapped?

Well, after reading in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 bitmap’s data, Bitmap_createFromParcel proceeds to store cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 information about cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 mapped data in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 constructed Bitmap instance:

Bitmap::Bitmap(void* address, int fd,
                           const SkImageInfo& info, size_t rowBytes, SkColorTable* ctable)
                               : mPixelStorageType(PixelStorageType::Ashmem) {
   mPixelStorage.ashmem.address = address;
   mPixelStorage.ashmem.fd = fd;
   mPixelStorage.ashmem.size = ashmem_get_size_region(fd);
   mPixelRef.reset(new WrappedPixelRef(this, address, info, rowBytes, ctable));
   // Note: this will trigger a call to onStrongRefDestroyed(), but
   // we want cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 pixel ref to have a ref count of 0 at this point
   mPixelRef->unref();
}

However, instead of using cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 size of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 previously created mapping, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 constructor simply retrieves cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 size of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 mapping using cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ASHMEM_GET_SIZE ioctl (using cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 thin-wrapper ashmem_get_size_region). This is, once more, a false assumption - namely, that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 underlying ashmem size and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 size of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 mmap-ed region must be equal to one anocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r. Finally, once cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 bitmap is freed, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 area is unmapped by calling:

void Bitmap::doFreePixels() {
   switch (mPixelStorageType) {
       ...
       case PixelStorageType::Ashmem:
           munmap(mPixelStorage.ashmem.address, mPixelStorage.ashmem.size);
           close(mPixelStorage.ashmem.fd);
           break;
       ...
   }
}

Putting it all togecá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r, this means that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 mmap and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 munmap calls are performed with potentially different length arguments, both of which are fully controllable by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 attacker:

  • The length of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 mmap operation is calculated from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 bitmap’s metadata
  • The length of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 munmap operation is calculated from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ashmem’s size

The mismatch between cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 mmap-ed and munmap-ed length provides us with a great exploitation primitive! Specifically, we could supply a short length for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 mmap operation and a longer length for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 munmap operation - thus resulting in deletion of an arbitrarily large range of virtual memory following our bitmap object. Moreover, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re’s no need for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 deleted range to contain one continuous memory mapping, since cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 range supplied in munmap simply ignores unmapped pages.

Once we delete a range of memory, we can cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n attempt to “re-capture” that memory region with controlled data, by causing anocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r allocation in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 remote process. By doing so, we can forcibly “free” a data structure and replace its contents with our own chosen data -- effectively forcing a use-after-free condition.

From here on, we’ll refer to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365se crafted bitmaps with mismatching lengths as “BitUnmap”s.

bitunmap.png

Thinking of an Exploit Strategy

Finding a Target Service


Okay - now that we finally have a good exploitation primitive, how can we use it in order to write a stable exploit that will allow us to gain code execution in system_server? First of all, we’ll need to find a binder call in system_server which un-flattens a Bitmap object (or unparcels a Bundle containing a Bitmap) from a binder transaction. Moreover, it would be advantageous if we were able to access this call from any context, requiring no permissions.

Luckily, system_server houses many different binder services, increasing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 odds of finding a comfortably exploitable endpoint.

One such candidate is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 “notification” service, which provides an interface for interaction with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 notification bar. Among cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 operations supported by this service, any application (even those running in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 isolated_app SELinux context and those requiring no permissions whatsoever) may attempt to add a notification object which is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n handled by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 notification service. Moreover, Notification objects are complex, and may contain images (bitmaps) along with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 presented text.

Notification.png

Using notifications is also advantageous for a completely different reason - cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365ir lifetime is controlled by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 attacker. Remember that after we free a memory range in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 remote process, we’d like to re-capture that memory region with our own controlled data. Well, as we’ve already seen, Bitmap objects are mmap-ed into cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 remote address-space, and contain completely controlled data. What’s more, once a notification is added to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 notification bar, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Notification object will remain referenced in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 remote process (until cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 notification is removed). This effectively means we can use notifications for a dual purpose:

  • Sending crafted BitUnmaps to delete memory ranges in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 remote process
  • Sending regular Bitmaps with controlled data in order to reclaim freed regions

Finding a Target Data Structure


After we’ve established our ability to unmap arbitrarily large memory regions in system_server by crafting our own Notification objects containing BitUnmap instances, we still need to think of a method with which we’ll be able to reliably hijack control flow in system_server. That is, we need to decide which data structure to unmap using our primitive.

First, consider cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 fact that our BitUnmap objects are allocated by calling mmap. Due to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 behaviour of mmap, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y will simply inhabit cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 highest memory address between mm->mmap_base and TASK_SIZE which contains a sufficiently large contiguous hole. This means that, for example, attacking single C++ or Java objects would be racá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r difficult, as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y are located in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 heap and are surrounded by ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r data structures which we would have to “repair”.

Moreover, even if we were able to hijack such data structures, we would still need to craft cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365ir content in a way which would allow us to eventually hijack cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 control flow. For example, exploiting use-after-free vulnerabilities in C++ objects normally includes hijacking cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365ir vtable and replacing it with a structure pointing to ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r executable memory locations. With modern exploit mitigation techniques, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 amount of steps required to bypass XN-bit protection and ASLR could be quite substantial.

Perhaps cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re’s a cleaner way to get code execution?

Optimally, we’re looking to replace a data structure that has cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following properties:

  • Is allocated directly using mmap (i.e., not “on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 heap”)
    • Therefore we don’t need to “repair” adjacent data structures
  • Allows direct control over code execution
    • Saves us cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 need to craft a complex chain to bypass mitigation techniques
  • Does not require address-space dependant information unique to system_server
    • Saves us cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 need to find (or create) an information leak to bypass ASLR

In order to find this magical structure, I’ve written a small gdb script to monitor and log all calls to mmap coupled with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365ir origins and sizes. This helped me group cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 “families” of mmap-ed objects which could be useful for exploitation. After producing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 list, one such candidate stood out as having all cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 above properties - Threads.

Hanging by a Thread


As we know, all threads in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same process share cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same address space. Moreover, system_server, being cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 large process that it is, contains many code paths which handle long-running or periodic tasks. Naturally, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365se code paths are handled by creating additional threads in system_server. When threads are created, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y require two data structures which are unique to each thread: cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 thread metadata (pthread_internal_t) and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 thread’s stack.

Looking at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 code in Android’s bionic, we can see that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365se two regions are, in fact, carved from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same memory region, which is allocated using mmap:

                                              pthread_internal_t** threadp,
                                              void** child_stack) {
   if (attr->stack_base == NULL) {
       // The caller didn't provide a stack, so allocate one.
       // Make sure cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 stack size and guard size are multiples of PAGE_SIZE.
       mmap_size = BIONIC_ALIGN(attr->stack_size + sizeof(pthread_internal_t),    
                                                        PAGE_SIZE);
       attr->guard_size = BIONIC_ALIGN(attr->guard_size, PAGE_SIZE);
       //Calls mmap to create cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 mapped space, and mprotect to create a guard page
       attr->stack_base = __create_thread_mapped_space(mmap_size, attr->guard_size);
       …
       stack_top = reinterpret_cast<uint8_t*>(attr->stack_base) + mmap_size;
       …
   }
   ...
   pthread_internal_t* thread = reinterpret_cast<pthread_internal_t*>(stack_top);
   ...
}

So, if we are able to deallocate a thread’s stack and immediately reclaim it as our own, we should be able to directly achieve code execution simply by virtue of already having prepared a stack which performs whichever operation we’d like to execute within system_server.

Regardless, before we can start scheming about hijacking a thread, we need to think of a way to spawn a thread in system_server on-demand.

Going through cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 available binder calls terminating in system_server reveals one such comfortably accessible code-path: AudioService::loadSoundEffects. This binder command can be called without requiring any permissions, and causes cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 AudioService to load a predefined set of sound effects in its internal “sound pool”. Creating such a pool causes system_server to spawn several threads:

soundpool.png

In this exploit we’ll hijack cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 “SoundPoolThread”, for a variety of reasons:

  1. It is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 first thread created when creating a new sound pool. This fact will come in handy later, when we try and force it to be allocated in a controlled memory region.
  2. After initializing a sound pool, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 “SoundPoolThread” awaits furcá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r commands by waiting on a condition variable. Until cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 condition variable is signaled, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 “futex” system-call will not return. As cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 thread will not access its stack while it is waiting for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 system-call to return, this allows us to replace cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 thread’s stack with our own, leaving cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 thread none cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 wiser. Once we’ve performed our switch, we can trigger a chain of events (such as closing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 sound pool by calling unloadSoundEffects) which will signal cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 condition variable and cause cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 system-call to return.
  3. Once cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 sound pool is closed, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 SoundPoolThread is no longer needed and simply terminates anyway. This means we can safely hijack it without causing any adverse effects in system_server.

A Short ROP Chain


Once we hijack cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 SoundPoolThread’s stack, we’ll need to replace it with our own ROP stack. So, what should we run cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re? Well, for versions of Android prior to 7.0, we could simply write a short ROP chain which mmap-s one of our ashmem file descriptors with executable access-permissions, and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n jumps directly to it. Indeed, this would allow us to simply place executable code at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 base of an ashmem descriptor and send it along to system_server.

However, as of Android 7.0, this solution would no longer work. This is because starting from Android 7.0, a new set of mitigations have begun to roll out which aim to prevent unauthorised code execution within system_server (and ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r privileged processes). A small subset of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365se rules can be seen here:

# system_server should never use JIT functionality
neverallow system_server self:process execmem;
neverallow system_server ashmem_device:chr_file execute;
neverallow system_server system_server_tmpfs:file execute;

Specifically, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 second rule prevents ashmem file descriptors from being mapped as executable within system_server. Moreover, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 use of execmem (in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 first rule) prevents system_server from mapping “new” executable memory regions within cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 process.

So… we could still write a large ROP chain to perform whichever set of commands we’d like within system_server. Due to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 breadth of system_server, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ROP gadgets could conceivably even be turing-complete. However, this seems incredibly complex to do manually, and quite time consuming to automate.

Instead, we could look for a way to directly bypass cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 mitigation mentioned above. We’ll do so by looking for SELinux contexts which can be executed within system_server. After a short search, we stumble upon cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following SELinux rule:

# system_server should never execute anything from /data except for /data/dalvik-cache files.
neverallow system_server {
   data_file_type
   -dalvikcache_data_file #mapping with PROT_EXEC
}:file no_x_file_perms;

Okay, so files with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 SELinux context dalvikcache_data_file may be freely mapped as executable. This makes sense as when Android applications are installed cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y go through an “optimization” process, resulting in new files which may be executed more quickly. As system_server loads many of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365se optimized files, it needs to be able to map cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m in as executable to use cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m.

While system_server may use cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365se files, it cannot directly create cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m. In fact, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 only process which is allowed to create files with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365se contexts is installd - cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 installer daemon.

The distinction, however, is purely semantic. This is due to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 fact that system_server can directly issue commands to installd using a special socket. One such command can be issued to cause installd to start such an optimization process (resulting in a file with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 dalvikcache_data_file context) from any chosen file and to any chosen destination. Thus, all our ROP chain would need to do is to open cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 installd socket, issue this command to create our wanted executable chunk, and finally map that new file as executable.

We could even go one step furcá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r - since we are launching our attack from an Android application, we could simply embed cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 executable shellcode within cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 source code of our application (for example, within a static byte array). Once our application is installed, it will be optimized, resulting in a new file of type dalvikcache_data_file). As luck would have it, this optimization process does not garble static byte arrays, meaning our shellcode will now reside in this new executable file. Finally, all we need to do is to simply locate this optimised file on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 disk and map it in as executable.

dalvikcache.png

Lastly, when crafting our ROP stack we’ll need to know where to start writing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 gadgets relative to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 stack’s base address. That is, we need to know cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 accurate position in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 stack at which cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 stack pointer will be placed when cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 SoundPoolThread enters cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 command loop.

Luckily, we can avoid cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 need to “guess” cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 top of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 stack (and place a ROP-slide) by using additional trick; we can simply start up such a thread in our own process (by creating a sound pool object), and wait for it to enter cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 command loop. Once cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 thread settles, we can read cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 /proc/$pid/stat for that task and measure cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 value of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 “SP” token against cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 base address of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 stack for that thread.

Bypassing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 need to Bypass ASLR


Up to now we’ve been avoiding cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 question of ASLR. This has been no mistake, but racá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r a happy accident. In order to allow for fast application startup times, Android applications are forked from a single process, appropriately named zygote. This process preloads many commonly used shared libraries and resources, thus saving applications cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 need to do so on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365ir own when cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y are launched.

Among cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 processes forked from zygote is our target for exploitation - system_server.

This essentially means that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 portion of our address space which are inherited from zygote are shared with system_server, including a multitude of shared libraries which are available at our disposal.

As such, once we manage to hijack a running thread, we can create an entire valid ROP stack using gadget addresses located in our own address space (so long as we stick only to zygote-loaded shared libraries). Doing so allows us to ignore ASLR for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 purpose of this exploit, as all cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r stages of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 exploit are address-independent anyway.

zygote_aslr.png

Shaping cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Address Space


Lastly, before we can put togecá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r a complete exploit, we still lack cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ability to shape cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 remote address space. Specifically, we need to reach a state that will cause cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 targeted objects that we would like to delete to be placed in controlled memory regions, which could cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n be freed and subsequently reclaimed.

Recall that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 behaviour of mmap dictates that for every allocation, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 chosen memory address will always be cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 highest address in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 range of mm->mmap_base to TASK_SIZE which contains a sufficiently large contiguous unmapped region.

This makes mmap an optimal allocator to use when attempting to shape cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 address space - most ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r allocators require special conditions in order to revert to contiguous allocations.

In our case, we already know that we would like to replace cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 memory region reserved for a thread’s stack. We’ll denote cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 size of this region by “thread_size”.

First, we’ll send over a large amount of notification objects to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 remote service, each of which containing a bitmap of size thread_size. This will allow us to fill in any “holes” in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 remote address space which may have been opened up during cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 lifetime of system_server. After doing so, we are guaranteed that any subsequent allocation of size thread_size will be contiguous and placed at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 top of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 current mmap-ed region.

shape_fill.png
Next, we allocate many consecutive bitmap objects of size thread_size, each of which referenced by a single Notification object. After doing so, we intentionally remove a single notification from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 consecutively allocated set. Then, we proceed bombard cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 system_server process with many small binder transactions triggering a remote garbage collection to occur. This, in turn, frees up cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 space previously held by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 bitmap object in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 removed notification, creating a thread_size sized hole, like so:

hole.png

Now, we can re-load cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 audio effects, causing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 SoundPoolThread to be spawned in system_server. As this is a thread_size-d allocation and all previous holes of that size have already been filled (by our bitmap objects), it will have to populate cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 vacant hole that we just created amidst our chunk of contiguous bitmaps.

Now, we can remove cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 notification directly in front of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 SoundPoolThread’s stack and once again trigger a remote garbage collection. This will cause anocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r hole to open up, bringing us to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following state:

hole2.png

Once we’ve strategically opened up a hole in front of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 SoundPoolThread, we can send our crafted BitUnmap object. We’ll create it so that its metadata size (i.e., cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 size used in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 mmap) will be equal to thread_size. However, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 size of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ashmem descriptor will actually be twice that size! This means cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 once our BitUnmap is freed in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 remote process, it will unmap itself, along with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 SoundPoolThread.

unmap.png

Finally, now that we’ve freed up cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 SoundPoolThread’s stack, we can send one more notification - this time of size 2*thread_size, which will fill in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 last created hole, effectively replacing both cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 region held by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 BitUnmap, and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 region containing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 SoundPoolThread’s stack.

remap.png

Putting it All Togecá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r


At long last, we have all cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 steps needed to create a complete working exploit. Here’s a short run-down of all cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 steps we discussed, which allow us to hijack a thread within cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 system_server process using our own crafted ROP stack:

  1. Build a ROP stack using gadgets in zygote-originating shared libraries
  2. Unload all sound effects (closing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 current SoundPoolThread, if present)
  3. Allocate many bitmaps of size thread_size to force consecutive allocations
  4. Open up a hole in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 middle of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 consecutively allocated bitmaps
  5. Reload cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 sound effects to create a new SoundPoolThread within cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 created hole
  6. Open up a new hole directly in front of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 previous hole
  7. Send a BitUnmap object to fit in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 newly created hole
  8. Force a remote GC to cause cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 BitUnmap to free itself and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 SoundPoolThread
  9. Allocate a new bitmap to occupy cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 space previously held by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 SoundPoolThread
  10. Unload all sound effects - causing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 condition variable to be signalled, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365reby triggering cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 SoundPoolThread to start executing using our own crafted stack!

Afterword


Although this blog post is quite lengthy, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re are many smaller details that I neglected to mention here (in favour of some brevity). I’d encourage anyone who’s interested to dig into cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 full source code of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 exploit to discover any such “missing” pieces.

Along with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 source code for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 exploit itself, I’m also releasing a project which can be used to easily create shellcode for use in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 exploit itself. Specifically, this project contains a small assembly stub which fixed up cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 freed pthread_internal_t structure at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 top of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 stack and corrects cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 thread-local storage AARCH64 registers to point to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365ir new location. After performing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 needed fixups, it simply jumps to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 shellcode’s main function.

In order to allow for easy shellcode creation in a high-level language (such as C) racá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r than hand-coding it all in assembly, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 shellcode wrapper uses a custom linker script to prepend cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 small fixup stub to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 shellcode, and compiles cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 shellcode itself as position independent.

You can find cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 source code for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 shellcoder here.

Timeline


  • 07.09.2016 - Vulnerability reported
  • 07.09.2016 - Initial response from Android security, assigned Android-ID
  • 23.09.2016 - Exploit submitted to Android security
  • 26.09.2016 - Android notify that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 fix will be present in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 next partner bulletin
  • 27.09.2016 - CVE-2016-6707 assigned
  • 01.11.2016 - Vulnerability fixed and released in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 November bulletin

Tuesday, November 29, 2016

Breaking cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Chain

Posted by James Forshaw, Wielder of Bolt Cutters.

Much as we’d like it to be true, it seems undeniable that we’ll never fix all security bugs just by looking for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m. One of most productive ways to dealing with this fact is to implement exploit mitigations. Project Zero considers mitigation work just as important as finding vulnerabilities. Sometimes we can get our hands dirty, such as helping out Adobe and Microsoft in Flash mitigations. Sometimes we can only help indirectly via publishing our research and giving vendors an incentive to add cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365ir own mitigations.

This blog post is about an important exploit mitigation I developed for Chrome on Windows. It will detail many of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 challenges I faced when trying to get this mitigation released to protect end-users of Chrome. It’s recently shipped to users of Chrome on Windows 10 (in M54), and ended up blocking cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 sandbox escape of an exploit chain being used in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 wild.

For information on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Chromium bug that contains cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 list of things we implemented in order to get this mitigation working, look here.

The Problem with Win32k

It’s possible to lockdown a sandbox such as Chrome’s pretty comprehensively using Restricted Tokens. However one of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 big problems on Windows is locking down access to system calls. On Windows you have both cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 normal NT system calls and Win32k system calls for accessing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 GUI which combined represents a significant attack surface.

System Calls (1).png
While cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 NT system calls do have exploitable vulnerabilities now and again (for example issue 865) it’s nothing compared to Win32k. From just one research project alone 31 issues were discovered, and this isn’t counting cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 many font issues Mateusz has found and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 hundreds of ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r issues found by ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r researchers.

Much of Win32k’s problems come from history. In cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 first versions of Windows NT almost all cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 code responsible for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 windowing system existed in user-mode. Unfortunately for 90’s era computers this wasn’t exactly good for performance so for NT 4 Microsoft moved a significant portion of what was user-mode code into cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 kernel (becoming cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 driver, win32k.sys). This was a time before Slammer, before Blaster, before cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 infamous Trustworthy Computing Memo which focussed Microsoft to think about security first. Perhaps some lone voice spoke for security that day, but was overwhelmed by performance considerations. We’ll never know for sure, however what it did do was make Win32k a large fragile mess which seems to have persisted to this day. And cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 attack surface this large fragile mess exposed could not be removed from any sandboxed process.

That all changed with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 release of Windows 8. Microsoft introduced cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 System Call Disable Policy, which allows a developer to completely block access to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Win32k system call table. While it doesn’t do anything for normal system calls cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 fact that you could eliminate over a thousand win32k system calls, many of which have had serious security issues, would be a crucial reduction in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 attack surface.

However no application in a default Windows installation used this policy (it’s said to have been introduced for non-GUI applications such as on Azure) and using it for something as complex as Chrome wasn’t going to be easy. The process of shipping Win32k lockdown required a number of architectural changes to be made to Chrome. This included replacing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 GDI-based font code with Microsoft’s DirectWrite library. After around two years of effort Win32k lockdown was shipping by default.

The Problems with Flash in Chrome

Chrome uses a multi-process model, in which web page content is parsed inside Renderer processes, which are covered by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Win32k Lockdown policy for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Chrome sandbox. Plugins such as Flash and PDFium load into a different type of process, a PPAPI process, and due to circumstance cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365se could not have cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 lockdown policy enabled. This would seem a pretty large weak point. Flash has not had cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 best security track record (relevant), making cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 likelihood of Flash being an RCE vector very high. Combine that with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 relative ease of finding and exploiting Win32k vulnerabilities and you’ve got a perfect storm.

It would seem reasonable to assume that real attackers are finding Win32k vulnerabilities and using cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m to break out of restrictive sandboxes including Chrome’s using Flash as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 RCE vector. The question was whecá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r that was true. The first real confirmation that this was true came from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Hacking Team breach, which occurred in July 2015. In cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 dumped files was an unfixed Chrome exploit which used Flash as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 RCE vector and a Win32k exploit to escape cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 sandbox. While both vulnerabilities were quickly fixed I came upon cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 idea that perhaps I could spend some time to implement cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 lockdown policy for PPAPI and eliminate this entire attack chain.

Analysing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Problem

The first thing I needed to do was to determine what Win32k APIs were used by a plugin such as Flash. There are actually 3 main system DLLs that can be called by an application which end up issuing system calls to Win32k: USER32, GDI32 and IMM32. Each has slightly different responsibilities. The aim would be to enumerate all calls to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365se DLLs and replace cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m with APIs which didn’t rely on Win32k. Still it wasn’t just Flash that might call Win32k API but also cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Pepper APIs implemented in Chrome.

Win32k Dependencies.png

I decided to take two approaches to finding out what code I needed to remove, import inspection and dynamic analysis. Import inspection is fairly simple, I just dumped any imports for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 plugins such as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Pepper Flash plugin DLL and identified anything which came from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 core windowing DLLs.

I cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n ran Flash and PDFium with a number of different files to try and exercise cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 code paths which used Win32k system calls. I attached WinDBG to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 process and set breakpoints on all functions starting with NtUser and NtGdi which I could find. These are cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 system call stubs used to call Win32k from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 various DLLs. This allowed me to catch functions which were in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 PPAPI layer or not directly imported.

Win32k system call using code in Flash and PDFium was almost entirely to enumerate font information, eicá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r directly or via cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 PPAPI. There was some OpenSSL code in Flash which uses cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 desktop window as a source of entropy, but as this could never work in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Chrome sandbox it’s clear that this was vestigial (or Flash’s SSL random number generator is broken, chose one or cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r).

Getting rid of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 font enumeration code used through PPAPI was easy. Chrome already supported replacing GDI based font rendering and enumeration with DirectWrite which does all cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 rendering in User Mode.  Most of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 actual rendering in Flash and PDFium is done using cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365ir own TrueType font implementations (such as FreeType). Enabling DirectWrite for PPAPI processes was implemented in a number of stages, with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 final enabling of DirectWrite in this commit.

Now I just needed to get rid of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 GDI font code in Flash and PDFium itself. For PDFium I was able to repurpose existing font code used for Linux and macOS. After much testing to ensure cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 font rendering didn’t regress from GDI I was able to put cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 patch into PDFium. Now cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 only problem was Flash. As a prototype I implemented shims for all cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 font APIs used by Flash and emulated cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m using DirectWrite.

For a better, more robust solution I needed to get changes made to Flash. I don’t have access to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Flash source code, however Google does have a good working relationship with Adobe and I used this to get cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 necessary changes implemented. It turned out that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re was a Pepper API which did all that was needed to replace cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 GDI font handling, pp::flash::FontFile. Unfortunately that was only implemented on Linux, however I was able to put togecá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r a proof-of-concept Windows implementation of pp::flash::FontFile and through Xing Zhang of Adobe we got a full implementation in Chrome and Flash.

Doomed Rights Management

From this point I could enable Win32k lockdown for plugins and after much testing everything seemed to be working, until I tried to test some DRM protected video. While encrypted video worked, any Flash video file which required output protection (such as High-bandwidth Digital Content Protection (HDCP)) would not. HDCP works by encrypting cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 video data between cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 graphics output and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 display, designed to prevent people capturing a digital video.

Still this presents a problem, as video along with games are some of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 only residual uses of Flash. In testing, this also affected cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Widevine plugin that implements cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Encrypted Media Extensions for Chrome. Widevine uses PPAPI under cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 hood; not fixing this issue would break all HD content playback.

Enabling HDCP on Windows requires cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 use of a small number of Win32k APIs. I’d not discovered this during my initial analysis because, a) I didn’t run any protected content through cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Flash player and b) all functions were imported at runtime using LoadLibrary and GetProcAddress only when needed. The function Flash was accessing was OPMGetVideoOutputsFromHMONITOR which is exposed by dxva2.dll. This function in turn maps down to multiple Win32k calls such as NtGdiCreateOPMProtectedOutputs.

The ideal way of fixing this would be to implement a new API in Chrome which exposed enabling HDCP cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n get Adobe and Widevine to use that implementation. It turns out that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Adobe DRM and Widevine teams are under greater constraints than normal development teams. After discussion with my original contact at Adobe cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y didn’t have access to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 DRM code for Flash. I was able to have meetings with Widevine (cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y’re part of Google) and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Adobe DRM team but in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 end I decided to go it alone and implement redirection of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365se APIs as part of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 sandbox code.

Fortunately this doesn’t compromise cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 security guarantees of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 original API because of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 way Microsoft designed it. To prevent a MitM attack against cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 API calls (i.e. you hook cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 API and return cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 answer cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 caller expects, such as HDCP is enabled) cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 call is secured between cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 caller and graphics driver using a X.509 certificate chain returned during initialization.

drive_certs.PNG

Once cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 application such as Flash verifies this certificate chain is valid it will send back a session key to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 graphics driver encrypted using cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 end certificate’s public key. The driver cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n decrypts cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 session key and all communication from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n on is encrypted and hashed using variants of this key. Of course this means that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 driver must contain cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 private key corresponding to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 public key in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 end certificate, though at least in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 case on my workstation that shouldn’t be a major issue as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 end certificate has a special Key Usage OID (1.3.6.1.4.1.311.10.5.8) and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 root “Microsoft Digital Media Authority” certificate isn’t in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 trusted certificate store so cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 chain wouldn’t be trusted anyway. Users of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 API can embed cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 root certificate directly in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365ir code and verify its trust before continuing.

root_cert.PNG

As cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 APIs assume that it’s already been brokered (at minimum via Win32k.sys) cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n adding anocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r broker, in this case one which brokers from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 PPAPI process to anocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r process in Chrome without cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Win32k lockdown policy in place, doesn’t affect cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 security guarantees of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 API. Of course I made best efforts to verify cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 data being brokered to limit cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 potential attack surface, though I’ll admit something about sending binary blobs to a graphics driver gives me cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 chills.
OPM Apis (1).png

This solved cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 issue with enabling output protection for DRM’ed content and finally cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 mitigation could be enabled by default. The commit for this code can be found here.

Avoiding #yolosec

Implementation wise it turned out to be not too complex once I’d found all cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 different possible places that Win32k functions could be called. Much of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 groundwork was already in place with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 original Win32k Renderer lockdown, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 implementation of DirectWrite and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 way cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Pepper APIs were structured. So ship it already!

Well not so fast, this is where reality kicks in. Chrome on Windows is relied upon by millions upon millions of users worldwide and Win32k lockdown for PPAPI would affect not only Flash, but PDFium (which is used in things like cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Print Preview window) and Widevine. It’s imperative that this code is tested in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 real world but in such a way that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 impact on stability and functionality can be measured.

Chrome supports something called Variations which allow developers to selectively enable experimental features remotely and deploy cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m to a randomly selected group of users who’ve opted into returning usage and crash statistics to Google. For example you can do a simple A/B test with one proportion of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Chrome users left as a Control and anocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r with Win32k lockdown enabled. Statistical analysis can be performed on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 results of that test based on various metrics, such as number of crashes, hanging processes and startup performance to detect anomalous behaviour which is due to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 experimental code. To avoid impacting users of Stable this is typically only done on Beta, Dev and Canary users. Having cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365se early release versions of Chrome are really important for ensuring features work as expected and we appreciate anyone who takes cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 time to run cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m.

In cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 end this process of testing took longer than cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 implementation. Issues were discovered and fixed, stability measured until finally we were ready to ship. Unfortunately in that process cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re was a noticeable stability issue on Windows 8.1 and below which we couldn’t track down. The stability issues are likely down to interactions with third party code (such as AV) which inject cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365ir own code into Chrome processes. If this injected code relies on calling Win32k APIs for anything cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re’s a high chance of this causing a crash.

This stability issue led to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 hard decision to initially only allow cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 PPAPI Win32k lockdown to run on Windows 10 (where if anything stability improved). I hope to revisit this decision in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 future. As third party code is likely to be updated to support cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 now shipping Windows 10 lockdown it might improve stability on Windows 8/8.1.

As of M54 of Chrome, Win32k lockdown is enabled by default for users on Windows 10 (with an option to disable it remotely in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 unlikely event a problem surfaces). As of M56 (set for release approximately cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 end of January 2017) it can only be disabled with a command line switch to disable all Win32k lockdown including Renderer processes.

Wrap Up

From cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 first patch submitted in September 2015 to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 final patch in June it took almost 10 months of effort to come up with a shipping mitigation. The fact that it’s had its first public success (and who knows how many non-public ones) shows that it was worth implementing this mitigation.

In cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 latest version of Windows 10, Anniversary Edition, Microsoft have implemented a Win32k filter which makes it easier to reduce cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 attack surface without completely disabling all cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 system calls which might have sped up development. Microsoft are also taking pro-active effort to improve cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Win32k code base.

The Win32k filter is already used in Edge, however at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 moment only Microsoft can use it as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 executable signature is checked before allowing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 filter to be enabled. Also it’s not clear that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 filter even completely blocked cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 vulnerability in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 recent in-cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365-wild exploit chain. Microsoft would only state it would “stop all observed in-cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365-wild instances of this exploit”. Nuking cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Win32k system calls from orbit is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 only way to be sure that an attacker can’t find a bug which passes through cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 filter.

Hopefully this blog post demonstrates cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 time and effort required to implement what seems on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 face of it a fairly simple and clear mitigation policy for an application as complex as Chrome. We’ll continue to try and use cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 operating system provided sandboxing mechanisms to make all users on Chrome more secure.

Thanks

While I took on a large proportion of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 technical work it’s clear this mitigation could not have shipped without cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 help of ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365rs in Chrome and outside. I’d like to especially mention cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following:

  • Anantanarayanan Lyengar, for landing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 original Win32k mitigations for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Renderer processes on which all this is based.
  • Will Harris, for dealing with variations and crash reporting to ensure everything was stable.
  • Adobe Security Team and Xing Zhang for helping to remove GDI font code from Flash.
  • The Widevine team for advice on DRM issues.