Thursday, January 9, 2020

Remote iPhone Exploitation Part 2: Bringing Light into cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Darkness -- a Remote ASLR Bypass

Posted by Samuel Groß, Project Zero

This post is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 second in a series about a remote, interactionless iPhone exploit over iMessage.The first blog post, which introduced cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 exploited vulnerability, can be found here.

The initial primitive gained from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 vulnerability is an absolute address dereference in which cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 read value is afterwards used as an ObjC object. As such, some knowledge of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 target address space is required in order to exploit this vulnerability for remote code execution. This blog post describes a way to defeat ASLR remotely without any additional information disclosure vulnerabilities. 

First off, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 effectiveness of an old technique, heap spraying, is evaluated. Afterwards, a technique is described through which it is possible to infer 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 dyld shared cache region given only a memory corruption bug. The released code implements cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 presented attack and can infer cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 shared cache base address remotely on vulnerable devices within a couple of minutes.

Heap Spraying on iOS


The goal of heap spraying is to put data of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 attacker’s choosing at a known address so that it can be referenced during cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 exploitation process. Heap spraying should be less effective today than it was 15 years ago due to ASLR and a 64-bit address space. However, it turns out that on iOS cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 technique is still fairly usable. In fact, only about 256MB of data need to be sprayed to put controlled data at a known address. This can easily be demonstrated with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following code snippet:

    const size_t size = 0x4000;
    const size_t count = (256 * 1024 * 1024) / size;
    for (int i = 0; i < count; i++) {
        int* chunk = malloc(size);
        *chunk = 0x41414141;
    }
   // Now look at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 memory at 0x110000000

Running this in on iOS (e.g. as part of a custom App) will put 0x41414141 at address 0x110000000:
(lldb) x/gx 0x110000000
0x110000000: 0x0000000041414141

Heap Spraying via iMessage

The next question cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n is how to best spray a few hundred megabytes of data remotely over iMessage. Basically, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re are two ways to do that:

  1. By abusing a memory leak (not an information leak!), a bug in which a chunk of memory is “forgotten” and never freed, and triggering it multiple times until cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 desired amount of memory has been leaked.
  2. By finding and abusing an “amplification gadget”: a piece of code that takes an existing chunk of data and copies it, potentially multiple times, thus allowing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 attacker to spray a large amount of memory by only sending a relatively small number of bytes.

As it turns out, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 NSKeyedUnarchiver API provides both primitives and this exploit actually combines cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 two: it sends messages of around 100kB, which seems to be cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 maximum size of inline data, and with that sprays around 32MB of heap data. It cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n leaks those 32MB and repeats cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 procedure a couple of times to perform cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 full heap spray.

However, it is likely possible to perform cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 entire spray in a single message by using downloaded attachments (cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 pbdi key). That way cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 memory leak wouldn’t be necessary and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 bug could be triggered multiple times if necessary. This is left as an exercise for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 reader.

There are many places in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 NSKeyedUnarchiver subsystem where memory is leaked. One example are cyclic object graphs, which will never be cleaned up as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y keep each ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r alive - a reference cycle. There is also anocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r way: __NSKeyedCoderOldStyleArrays, which are used during decoding of NSValues, and can, due to a quirk in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 NSKeyedUnarchiver, always be deserialized regardless of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 set of allowed classes. A  __NSKeyedCoderOldStyleArray stores its size and a pointer to a malloced chunk containing a number of same-type values, e.g. integers, c-strings, or ObjC objects. Interestingly, when cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 __NSKeyedCoderOldStyleArray is destroyed, it only frees its backing memory but does not recursively free cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 objects contained in it. As such, if cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 array contains pointers to ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r memory chunks, such as ObjC objects, memory is leaked. This is normally fine, as a __NSKeyedCoderOldStyleArray is only used to temporarily decode cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 array values of an NSValue. However, as it can also be decoded as a standalone object, it becomes possible to leak a large number of ObjC objects with it.

As for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 amplification gadget, ACZeroingString instances appear to be cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 perfect candidate, having already been (ab)used in Natalie’s exploit for CVE-2019-8646. As part of its initWithCoder, an ACZeroingString will take an existing NSData object and copy its content into a newly malloc’ed memory chunk.

With that, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 object graph to spray around 32MB of heap data looks like this:



Here, each ACZeroingString instance copies cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 NSData’s content into a new malloc buffer and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 __NSKeyedCoderOldStyleArray keeps all those ACZeroingString instances alive even after cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 current message has been fully processed. After sending around 8 of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365se messages, controlled data will be located at 0x110000000.

Having controlled data at a known address is a first step, but likely not enough. Given cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 existing exploit primitive, it would now be possible to create fake ObjC objects in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 heapspray region and have cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m be used in [NSSharedKeySet indexForKey:]. However, as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 heapspray content is not executable, it is necessary to know cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 address of code pages before faking objects really becomes possible. How this can be achieved will be discussed next, after a short introduction to some ObjC internals.

Objective-C for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ASLR Bypasser


Shown next is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 relevant code snippet  from [NSSharedKeySet indexForKey:] in which cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 read from a controlled address happens:

// index is fully controlled, _keys is nullptr
      id candidate = self->_keys[index];
      if (candidate != null) {
        if ([key isEqual:candidate]) {
          return prevLength + index;
        }
      }

The id type that is used here represents a reference to an ObjC object for which no more type information is available, not unlike a void* in C. However, unlike C, ObjC has runtime type information, so it is always possible to determine cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 exact type of an object at runtime, for example through cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 isKindOfClass method. 
Furcá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r, ObjC supports pointer tagging and so a pointer to an ObjC object, for example an id, can generally be one of two things:
  1. An actual pointer to an ObjC object
  2. A pointer-sized value containing both cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 type and value information

The  layout of objects will be discussed in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 next post, where it will be relevant for gaining code execution. However, for this blog post it is already necessary to take a closer look at ObjC tagged pointers.

NSNumbers and very short NSStrings are examples for tagged pointers. On Arm64, an id is considered a tagged pointer if its MSB is set. In that case, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 corresponding class is stored in a global table to which an index is encoded in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 tagged pointer. With that, an NSNumber instance storing a 32-bit integer (in ObjC: `NSNumber* n = @42`) would roughly be represented as

0xb0000000000002a2
(1 011 00...001010100010)

Where cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 MSB is 1, indicating a tagged pointer and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following 3 bits identify cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 index of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 class, in this case 3, corresponding to __NSCFNumber. In cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 case of __NSCFNumber, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 32bit value is stored in bits 8..40 while cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 lowest byte indicates cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 specific number type, in this case kCFNumberSInt32Type.

The APIs operating on ObjC id’s (objc_msgSend, objc_retain, objc_xyz) will usually first check cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 tag bit and proceed accordingly:

    if (arg & 0x8000000000000000) {
        // handle tagged pointer
    } else {
       // handle real pointer
    }

Likely in order to break exploit techniques that abuse tagged pointers, tagged pointer values are now also XORed with a per-process random value. As such, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 actual value used at runtime would now be

0xb0000000000002a2 ^ objc_debug_taggedpointer_obfuscator

Where objc_debug_taggedpointer_obfuscator seems to be a fully random number except for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 MSB, which must be zero (to preserve cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 pointer tagging bit). The following experiment with lldb and a simple iOS app demonstrates this:

(lldb) p n
(__NSCFNumber *) $0 = 0xf460034a00975a82 (int)42
(lldb) p objc_debug_taggedpointer_obfuscator
(void *) $1 = 0x4460034a00975820
(lldb) p/x (uintptr_t)n ^ (uintptr_t)objc_debug_taggedpointer_obfuscator
(unsigned long) $9 = 0xb0000000000002a2

The Dyld Shared Cache

On iOS (as well as on macOS), most system libraries are prelinked into one giant binary blob, called cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 dyld_shared_cache. Amongst ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r benefits, this improves program load times as it reduces cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 runtime overhead of symbol resolution. One security relevant aspect of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 shared cache is that it is mapped at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same address in every process, with its exact location only being randomized once during device boot. This is likely due to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 shared cache being mapped into all userspace processes (thus reducing overall system memory usage) but also containing absolute pointers to itself, making it not position independent. As such, once 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 shared cache is known, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 addresses of pretty much all libraries in any userspace process on that device, including thousands of ROP gadgets, all ObjC Classes, various strings, and much more, are also known. This is sufficient for an RCE exploit.

On cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 latest iOS versions, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 dyld_shared_cache will be mapped somewhere in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 address range 0x180000000 to 0x280000000, providing for roughly 200000 possible base addresses as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 cache itself is around 1GB in size and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 page size (cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 smallest granularity for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ASLR shift) is 0x4000 bytes. As such, it would be possible to find cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 base address by sheer brute force. However, as every wrong guess would likely cause a crash, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 targeted imagent process would soon be subject to restart limiting enforced by launchd if a service crashes too quickly. This can be avoided by only crashing once roughly every 10 seconds. With that, a full brute force attack would cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n take around 3-4 weeks. While such an attack is not completely impossible given that mobile devices are rarely rebooted, it is probably not a realistic one eicá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r. The remaining part of this blog post describes how cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 base address can be inferred within 5 minutes instead.

Defeating ASLR with a Crash Oracle


One outstanding aspect of CVE-2019-8646 is that it creates an additional communication channel between cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 victim device and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 attacker. It appears that this is a rare situation which should also be mitigatable to a large degree by properly sandboxing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 process in question to prevent it from doing any kind of network activity. As such, one of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 main questions motivating this research was cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following: given only a remote memory corruption vulnerability, would it be possible to infer 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 shared cache somehow? To achieve this, some kind of communication channel had to first be found, which exists in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 form of iMessage receipts.

iMessage supports two different types of message receipts: delivery receipts and read receipts. The latter one can be disabled in Settings while cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 former will always be sent. The following screenshot from an iMessage chat shows how cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365se receipts are used.



Here, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 sender received a delivery receipt and a read receipt for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 message “Foo”, a delivery receipt for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 message “Bar”, and no receipt at all for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 message “Baz”. Delivery receipts are interesting as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y are sent automatically without any user interaction. Even more interesting is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 time cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y are sent out by imagent, as shown in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following pseudocode snippet of imagent’s logic for processing incoming iMessages:

processIncomingMessage(message):
    msgPlist = decodeIntoPlist(message)
    # extract some values from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 plist ...
    atiData = msgPlist['ATI']
    ati = NSKeyedUnarchive(atiData)              [1]
    # more stuff ...
    sendDeliveryReceipt()
    # yet more stuff ...

Any bug in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 NSKeyedUnarchiver API will trigger at [1]. With that it is possible to build a “crash oracle”: if a crash is triggered during cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 NSKeyedUnarchiving, no delivery receipt will be sent, ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365rwise one will be sent. This in turn allows cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 sender to infer whecá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r or not cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 payload caused a crash in imagent on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 remote device. What remains now is to turn cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 bug into an oracle function so that a useful bit of information can be extracted from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 outcome of each oracle query. 

The ideal oracle would be 

def oracle(addr): 
    if isMapped(addr):
        nocrash()
    else
        crash()

Given that, breaking ASLR remotely would be racá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r straightforward:
  1. Perform a linear search between 0x180000000 and 0x280000000 in ~500MB steps, which would take at most 8 oracle queries
  2. Perform a binary search between cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 found address and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 found address minus cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 step size. This would again only take a few queries as it runs in logarithmic time.

This could take as little as 10 iMessages to break ASLR and likely no more than 20. 

In practice, however, it is unlikely that a memory corruption vulnerability will yield this perfect oracle function, so a more general version of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 above algorithm is necessary. In any case, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 vulnerability likely first needs a bit of exploit engineering to result in a usable oracle function. This is also cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 case for CVE-2019-8641.

First off, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 bug trigger given in part 1 of this series unfortunately crashes regardless of whecá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 given address is valid or not: (line numbers reference cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 code snippets from part 1) cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ObjC id that is read from an attacker controlled address is afterwards compared to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 key that is currently being looked up (line 13 in -[NSSharedKeySet indexForKey:]). As it most likely does not match, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 lookup will fail and -[NSSharedKeySet initWithCoder:] will attempt to recreate cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 NSSharedKeySet from scratch (lines 20 through 23). For that it will call [NSSharedKeySet allKeys] on its subKeySet (line 22). Unfortunately, as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 subKeySet is not yet fully initialized (this is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 bug), cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 allKeys method will definitely crash when accessing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 _keys array as that is still nullptr. Luckily, it is possible to work around this with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following object graph:



The trick here is to add a new tail KeySet (SharedKeySet3) which will always be able to look up cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 second key (“k2”). However, as this KeySet is now cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 subKeySet of SharedKeySet1, SharedKeySet2 must be unarchived in some ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r way. This is only possible by unarchiving a new SharedKeyDictionary first, which in turn is only possible through cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 _keys array of SharedKeySet1. Unfortunately, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 class whitelist used to unarchive _keys does not include NSDictionary. Fortunately though, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 __NSLocalizedString class (itself an NSString and as such allowed) has cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following piece of code in its initWithCoder implementation to decode its config dictionary:

NSSet* classes = [NSSet setWithObjects:[NSDictionary class], ...];
NSDictionary* configDict = [coder decodeObjectOfClasses:classes 
                                  forKey:@"NS.configDict"]

As such, a NSSharedKeyDictionary can be decoded during unarchiving of _keys by “wrapping” it into a __NSLocalizedString.

With that, unarchiving cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 shown payload will only crash in one of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following two cases:
  1. if cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 address (in this case 0x41414140 as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 index read from _rankTable is multiplied by 8) is not readable (i.e. not mapped)
  2. if calling [key isEqual:candidate] with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 value read from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 address crashes

If cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 value is zero, [key isEqual:] will not be called (line 11). Ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365rwise, if cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 value does not have cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 MSB set, it will be treated as a pointer to an ObjC object and methods will be called on it, surely leading to a crash unless cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 value pointed to is in fact an ObjC object. Finally, if cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 value has cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 MSB set, it will be treated as a tagged pointer and will likely have its class fetched. This happens by first XORing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 tagged pointer with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 random obfuscator value, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n extracting an index into cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 class table from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 upper bits and using that. As not all entries of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 class table are populated, this step can cause a crash if cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 index is invalid. As cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 obfuscator value is unknown, it is not normally possible to predict in advance whecá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r a given value will cause a crash. However, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re is a situation in which even invalid tagged pointer values will not cause a crash: in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 implementation of [NSCFString isEqual:], which is used when cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 key that is looked up is a string (as is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 case in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 previous object graph examples). That implementation has cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following special casing for tagged pointer values:

if (a3 & 0x8000000000000000) {
  // Extract class index from tagged pointer
  v5 = ((a3 ^ objc_debug_taggedpointer_obfuscator) >> 60) & 7;
  if ( v5 == 7 )
    // Use extended class index in bits 52 - 60
    v5 = (((a3 ^ objc_debug_taggedpointer_obfuscator) >> 52) & 0xFF) + 8;

  // Check class index equals cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 one for NSString
  if ( v5 == 2 )
    // If yes, extract string content from lower bits and compare
    return _NSTaggedPointerStringEqualCFString(a3, self);

  // If not, just return false directly
  return 0;
}

Given this isEqual method, any value that has cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 MSB set can now be used as argument without causing a crash.

Finally, with all that, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 resulting oracle function is now roughly

oracle(addr):
  if isMapped(addr) and 
     (isZero(*addr) or hasMSBSet(*addr) or pointsToObjCObject(*addr)):
    nocrash()
  else:
    crash()

Given this oracle, it is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n necessary to build a “profile” of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 target device’s shared cache, which is essentially a bitmap where a zero indicates that an access would crash and a one indicates that it would not. As cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 shared cache binary is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same on all iPhones of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same hardware model and iOS version, this can simply be done by running a custom app on a device similar to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 target device and scanning over cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 shared cache region in memory. In practice,  cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 profile should also support a third, “unknown” state in which both outcomes are possible. This would for example be used for writable memory regions in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 shared cache as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365ir runtime content is unknown. However, For simplicity, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following explanation will assume a two-state profile. Adopting cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 algorithm to work with three state profiles is straightforward and is implemented in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 released source code.

A bitmap for a two-state profile might look as follows:



The next step is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n to use cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 oracle to again perform a linear search between 0x180000000 and 0x280000000 until no crash is observed. Afterwards, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 set of all possible shared cache base addresses can be computed simply by iterating over cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 profile in pagesized steps and computing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 base address for any offset that would not yield a crash when probed. In practice, this step will result in roughly 30000-40000 different base addresses (candidates).

Next, a search algorithm has to be used to efficiently determine cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 correct base address with minimal number of additional oracle queries (as each oracle query takes around 10s so as to not crash imagent too quickly, which would soon cause launchd to delay restarting cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 service). The following picture shows cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 shared cache (hypocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365tically) mapped at each of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 possible base addresses (in this case 5) in memory:



The goal is now to find a new address that, when probed through cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 crash oracle, will allow roughly half of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 remaining candidates to be discarded. In cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 above picture that would, for example, be cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 address 0x19020c028 (green line). If a crash occurs when querying cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 oracle for that address, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n only cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 first and last candidate remain, ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365rwise cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 middle three candidates are kept. Given cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 candidates and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 address to probe, it is also possible to compute cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 probability of a crash (⅖ in this case), and with that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 expected number of remaining candidates (E) after cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 oracle query, in this case:

E = ⅗ * 3 + ⅖ * 2 = 2.6
   
To efficiently find cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 correct base address, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 algorithm will now greedily pick cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 address with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 smallest value for E in every iteration. Ideally, if cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ones and zeroes in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 profile are roughly balanced (which is more or less cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 case here), this will be half cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 current number of candidates. In that case cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 correct base address will be found in logarithmic time, or roughly 2-5 minutes.

When implementing this algorithm, a slight performance problem occurs as a full search for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ideal candidates would take shared_cache_size/8 * num_candidates operations, easily reaching one trillion (1012) operations. However, in practice it is good enough to approximate cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ideal solution by randomly testing 100 different addresses. Anocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r minor complication that arises when using three-state profiles as discussed above is that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 algorithm is conservative and will treat writable memory pages as both potentially crashing and not crashing (as it is unknown what value will be cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re at runtime). As such, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 probability of a crash can only be approximated from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 read-only pages. However, again, this approximation of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 real probability works just fine in practice as it does not affect cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 correctness of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 algorithm.

Pseudocode for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 final algorithm is shown next.

candidates = [...]
while len(candidates) > 1:
  best_address = 0x0
  best_E = len(candidates)
  remaining_candidates_on_crash = None
  remaining_candidates_on_nocrash = None

  for _ in range(0, 100):
    addr = random.randrange(minbase, maxbase, 8)
    crashset = []
    nocrashset = []
    for profile in candidates:
      if profile.addr_will_crash(addr):
        crashset.append(profile)
      if profile.addr_will_not_crash(addr):
        nocrashset.append(profile)

    crash_prob = len(crashset) / len(candidates)
    nocrash_prob = 1.0 - crash_prob 
    E = crash_prob * len(crashset) + nocrash_prob * len(nocrashset)
    if E < best_E:
      best_E = E
      best_address = addr
      remaining_candidates_on_crash = crashset
      remaining_candidates_on_nocrash = nocrashset

  if oracle(best_address):
    candidates = remaining_candidates_on_nocrash
  else:
    candidates = remaining_candidates_on_crash

The following snippet shows cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 output of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 part of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 exploit that infers cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 shared cache’s base address on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 target device. The printed “score” value corresponds to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 computed expected number of remaining candidates after cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 displayed address is queried.

> ./aslrbreaker.py
[!] Note: this exploit *deliberately* displays notifications to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 target
[*] Trying to find a valid address...
[*] Testing address 0x180000000...
[*] Testing address 0x188000000...
[*] Testing address 0x190000000...
[*] Testing address 0x198000000...
[*] Testing address 0x1a0000000...
[*] Testing address 0x1a8000000...
[*] Testing address 0x1b0000000...
[*] Testing address 0x1b8000000...
[*] Testing address 0x1c0000000...
[+] 0x1c0000000 is valid!
[*] Have 34353 potential candidates for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 dyld_shared_cache slide
[*] Shared cache is mapped somewhere between 0x181948000 and 0x203d64000
[*] Now determining exact base address of shared cache...
[*] 34353 candidates remaining...
[*] Best (approximated) address to probe is 0x1b12070d0 with a score of 17208.40
[*] 17906 candidates remaining...
[*] Best (approximated) address to probe is 0x1b8a353d8 with a score of 9144.48
[*] 9656 candidates remaining...
[*] Best (approximated) address to probe is 0x1bcb23de0 with a score of 5093.02
[*] 5104 candidates remaining...
[*] Best (approximated) address to probe is 0x1e172e3f8 with a score of 2754.83
[*] 2682 candidates remaining...
[*] Best (approximated) address to probe is 0x1b363c658 with a score of 1454.06
[*] 1728 candidates remaining...
[*] Best (approximated) address to probe is 0x1e0301200 with a score of 929.21
[*] 915 candidates remaining...
[*] Best (approximated) address to probe is 0x1b0c04368 with a score of 497.63
[*] 593 candidates remaining...
[*] Best (approximated) address to probe is 0x1e0263068 with a score of 319.15
[*] 326 candidates remaining...
[*] Best (approximated) address to probe is 0x1bec43868 with a score of 163.84
[*] 156 candidates remaining...
[*] Best (approximated) address to probe is 0x1c15ab0e8 with a score of 78.21
[*] 82 candidates remaining...
[*] Best (approximated) address to probe is 0x1c49efe90 with a score of 41.02
[*] 40 candidates remaining...
[*] Best (approximated) address to probe is 0x1befd60f8 with a score of 20.00
[*] 20 candidates remaining...
[*] Best (approximated) address to probe is 0x1c14089d0 with a score of 10.00
[*] 10 candidates remaining...
[*] Best (approximated) address to probe is 0x1c428d450 with a score of 5.00
[*] 5 candidates remaining...
[*] Best (approximated) address to probe is 0x1df0939f0 with a score of 2.60
[*] 2 candidates remaining...
[*] Best (approximated) address to probe is 0x1c3d255f8 with a score of 1.00
[+] Shared cache is mapped at 0x1bf2b4000

As a final note, it seems likely that a similar oracle function can be constructed from different memory corruption vulnerabilities. As an example, any vulnerability that allows cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 attacker to corrupt or fake an ObjC object (e.g. through an OOB read such as CVE-2019-8641 or a use-after-free like CVE-2019-8647 and CVE-2019-8662) could potentially be turned into a similar oracle in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following way: whenever a reference to an ObjC object is dropped, objc_release is called with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 object as argument. This function will, amongst ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365rs, perform cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following steps: it first checks if cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 object has “custom retain release” functionality by checking a bit in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Class object associated with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 released object (every ObjC object references its Class object through a pointer stored at offset zero, called cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 “ISA” (Is-a) pointer). If cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 object has no custom retain release, an inline refcount will be decremented and, if cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 result is not zero, nothing more happens. Ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365rwise cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 object’s destructor is invoked and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 memory chunk freed.

As such, if cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Class pointer of an object can be corrupted to point into cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 shared cache region, and at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same time cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 object’s inline refcount is > 1, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n objc_release will only crash if a specific bit is set at an offset from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 pointed to value. With that, a crash oracle can again be constructed.

Supporting Different iOS versions and Hardware Models


One seeming limitation of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 presented technique is that it requires up-front knowledge of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 target device’s hardware model and iOS version to build cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 correct shared cache profile. However, this is not necessarily cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 case: if cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 model number or version are unknown, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 attacker can build shared cache profiles for all possible combinations of hardware model and iOS version that could be used. This would cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n likely result in a few million candidates after cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 initial linear scan is finished. However, due to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 magic of logarithms, even with millions of candidates this attack will still only require sending a few dozen messages to determine cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 correct base address and with it cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 correct shared cache, model number, and version. This has, however, not been implemented during this research.

A Note about Noisiness 


Anocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r seeming limitation is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 inherent noisiness of this attack. While crashing imagent dozens of times is not noticeable to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 user, it would send crash reports to Apple if “Share iPhone Analytics” is enabled on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 device. As such, this technique might seem less useful for a real-world attacker as it could cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365oretically inform Apple of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 vulnerability that is being exploited. However, it appears that iOS stops collecting crash logs for a process after 25 crashes. This can be observed by repeatedly crashing an iOS process (e.g. imagent) and monitoring cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 device log using Console.app on a Mac connected to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 device. Eventually cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following messages should appear:

default 14:54:42.957547 +0200 ReportCrash Formulating report for corpse[597] imagent
default 14:54:42.977891 +0200 ReportCrash Report of type '109()' not saved because cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 limit of 25 logs has been reached

As such, it should be possible to first use a seperate, unexploitable DoS bug (e.g. an ObjC exception or a stack overflow due to too much recursion) to crash imagent around 25 times so that no more crashlogs are collected for it and only cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n start cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 actual exploitation procedure. This has, however, also not been verified in practice.

The Issue with Automatic Delivery Receipts


As was demonstrated in this blog post, it is possible to bypass ASLR by creating a side channel that abuses automatic delivery receipts sent by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 target device to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 attacker. The fix for this at first appears simple: send cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 delivery receipt before doing any complex message parsing so that it will be sent regardless of whecá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 payload causes a crash. However, this is not sufficient, as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following attack likely still works:

  1. send cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 “oracle query” message (cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 one that might cause a crash) 2-3 times in a row
  2. send a "normal" message that will never cause a crash
  3. measure cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 time it takes for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 last delivery receipt to arrive. If that is longer than a few seconds, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n imagent likely crashed repeatedly during step 1 and is now subject to a restart delay by launchd

This attack now exploits cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 restart delay enforced by launchd on iOS. A similar mechanism might exist on ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r platforms as well though. With that, it appears that any kind of automatic message sent from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 recipient side (or any ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r action that could be observable by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 attacker, for example accessing a website) is potentially dangerous as it can be exploited in a similar way. As such, ideally, no automatic messages should be sent out at all, or at least not to senders with which cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 user never had any previous interaction.

This concludes cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 second part of this blog post series. The third and final part of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 series will detail how, even in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 presence of pointer aucá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365ntication (PAC) on A12 and newer devices, remote code execution can now be achieved.

No comments:

Post a Comment