http://exploit-db.com/docs/39527.pdf
在本文中,我們研究了如何利用安卓系統上最臭名昭著的漏洞之一Stagefright
。在此之前,我們一直認為這個漏洞是很難被利用的。在研究中,我們大量參考了Google公布的文章-exploit-38226和研究報告Google Project Zero: Stagefrightened。
本文中呈現了我們的研究結果,詳細的介紹了這個漏洞的局限性,提供了一種繞過ASLR的途徑,并為后繼者提出了一些研究建議。
NorthBit團隊利用的這個漏洞,能夠影響到 Android 2.2-4.0和5.0-5.1版本,同時,還能夠繞過Android 5.0-5.1上的ASLR技術(Android 2.2-4.0版本上沒有實現ASLR)。
Stagefright是Android系統中的一個多媒體庫。直到2015年7月27日,幾個關鍵堆溢出漏洞的曝光,人們才開始注意到了Stagefright。這個漏洞最初是由Zimperium的Joshua Drake發現的,Android版本包括從1.0到5.1都受到了影響。
在下面的部分中,我們會用“libstagefright”代指Stagefright媒體庫,用“stagefright”代指相應的bug。
雖然,多個Android版本的系統中都存在這個bug(接近1,000,000,000臺設備),但是,很多人都認為這個漏洞無法被利用,主要是因為新版的Android實現了ASLR保護技術。
Metaphor代指的是我們對Stagefright的利用過程。在文中,我們詳細的研究了libstagefright,并提出了一種可以繞過ASLR的新技術。和Google團隊一樣,我們利用了CVE20153864,因為相較于Joshua Drake發現的CVE20151538漏洞,這個漏洞更容易實現。
我們之所以會持續研究這個媒體庫,是因為其已經被證明了確實存在漏洞(bug和壞代碼太多),受影響的設備成千上萬,潛在的攻擊途徑也多種多樣:mms(秘密進行),短信(自動進行),web瀏覽器(很少或幾乎不需要用戶交互)等等。
相比于前人的努力,我們希望實現一種更具普適性和可行性的利用方式,而可行性指的就是快速,可靠并且難以發現-理想情況下,只利用現有的漏洞。
總而言之,我們的目標是繞過ASLR。
要想理解這個漏洞,首先要理解MPEG-4文件格式。還好不難:這種文件就是TLV(類型-長度-值TypeLengthValue)數據塊的集合。在這種編碼方式中,會有一個“type”值指定數據塊類型,一個“length”值指定數據長度,一個“chunk”值指定數據本身。
以MPEG-4為例,首先編碼“length”,然后是“type”,最后是“value”。下面的pseudo-C描述的就是MPEG-4的數據塊格式:
當長度為0時,數據會一直持續到文件末尾。atom字段是一個短字符串(也叫作FourCC),描述的是數據塊類型。
對于需要超過2^32個字節的類型,使用的格式也稍有不同:
在采用了樹結構的類型中,子數據塊存在于父數據塊的數據中。
下圖中描述了一個媒體文件:
Bug-CVE20153864
因為已經有很多文章都介紹過這個bug,所以這里就不多說了。我們使用了Android 5.1.0的源代碼,如果有特殊情況,我們還會再做說明。
libstagefright中的這個bug出現在解析MPEG-4文件的過程中,或更具體的說,是解析tx3g atom字段,這個字段的作用是向媒體中嵌入字幕。
首先,我們看看這段代碼的作用:
相當簡單-這段代碼會收集所有的字幕數據塊,并將其附到一個長緩沖區中。
檢查了size和chunk_size,并且在我們的控制下,允許我們在這里造成了一個整數緩沖區溢出:
要想實現堆溢出,我們需要至少一個合法的tx3g數據塊,在整數溢出部分和堆溢出中都需要用到:
無論緩沖區實際分配的大小是多少,最終會導致data部分中的size字節被寫到緩沖區中。
在構造堆時要注意,我們能夠:
考慮到這里,既然我們能夠控制堆溢出的大小和數據,那么漏洞利用應該很容易實現。但是,實際中的限制很多,復雜化了漏洞的利用過程。
在這一部分,我們介紹了漏洞的利用原理和限制,以及一些與漏洞利用相關的發現。
這個漏洞存在于媒體解析過程中,也就是說,受害者的設備甚至不需要播放媒體,而只需要解析即可。媒體解析過程是為了獲取其元數據,比如視頻長度,藝術家名稱,標題,字幕,注釋等等。
最后,我們選擇的攻擊途徑是通過web瀏覽器,因為需要執行JavaScript,這樣做的優缺點也很明顯。可以使用下面的這些方法來誘使受害者訪問我們的惡意網頁:
<script>
或<iframe>
標簽下面的這些攻擊途徑不適用于我們的方法:
受害者需要在攻擊性網頁上駐留一會兒。社會工程可能會增加這一漏洞的有效性-或其他針對受害者的長期攻擊方法,比如更改主頁。
再次查看存在漏洞的代碼:
最簡單的利用方法是構建堆,這樣的話,mDataSource對象會在緩沖區溢出后立刻被分配,然后利用這個bug,用我們的vtable(虛擬表)覆蓋mDataSource的vtable,并設置對應的readAt入口點指向我們自己的內存。這就是exploit-38226的實現方式。
要想更好地理解Metaphor,以及如何繞過ASLR,需要了解Android堆分配器-jemalloc的工作原理。
目前,你只需要知道jemalloc會將大小相似的對象分配到同一個run中。同一個run中會包含多個大小相同的緩沖區,這些緩沖區就叫做regions。稍小于region固定大小的對象會被向上舍入。
具體參見下圖:
Heap Spraying
Heap Spraying是使用pssh atom完成的。當解析器遇到一個pssh數據塊時,解析器會分配一個緩沖區,并將其附到一個緩沖區列表中:
我們控制其大小,我們就可以提供較大的值。這種方法的局限性在于,媒體文件中必須要有相應大小的數據,不過接下來我們會說明如何克服這一限制。
Heap Grooming不同于Heap Spraying簡單地分配大量的對象。通過控制分配和釋放順序,我們可以采用一種可預見的方式來設計堆對象的順序。在exploit-38226中,這是利用avcC和hvcC數據塊實現的:
(hvcC基本上是一致的)
解析器分配一個可控大小的緩沖區,然后將其傳遞給MetaData::setData。MetaData::setData會將數據復制到一個新的緩沖區,然后刪除先前的緩沖區,當然其大小也在我們的控制下。
這種方法不一定能在所有設備上應用,或許是因為jemalloc的配置不同,并且需要分配兩個大小相同的緩沖區-其中一個是MPEG4Extractor::p arse3GPPMetaData中的臨時緩沖區,另一個用于內部的MetaData對象。
一種更具普適性的Heap Grooming方法是使用MPEG-4 atoms,pref,auth和gnre。這些字段都是在MPEG4Extractor::parse3GPPMetaData: 的內部進行解析:
MetaData::setCString復制了一個從緩沖區+6開始的空終止(null-terminated)字符串:
我們可以通過chunk_size控制臨時緩沖區的大小,通過null字節的位置來控制實際復制哪個緩沖區,這樣我們就可以將臨時對象分配到另一個的run中,并提高漏洞利用的靈活性。
注意,一旦我們向MetaData中添加一個已有的項目,舊項目就會被替換。前面提到的MPEG-4 atoms為我們提供了4個相同的基元素(primitives)用于對堆進行控制。
為了覆蓋mDataSource,我們需要將其移動到堆底的一個位置,在這個位置上我們就可以預測到堆的位置。這一過程和exploit-38226一樣,都使用了stbl atom來重新分配mDataSource:
注意,stbl atom分配了一個新的MPEG4DataSource-因為我們的攻擊途徑是通過web瀏覽器,所以,mDataSource的類型是NuCachedSource2,NuCachedSource2::flags是:
下圖中描述的是通過Heap Grooming讓堆溢出mDataSource的過程:
ssh atoms用于Heap Spraying,這樣新的堆就會按照預定順序運行。然后,使用titl和gnre atoms作為占位符-首先分配titl,然后分配gnre,釋放了gnre后,我們再使用stbl atom分配一個MPEG4DataSource。
當我們釋放了titl后,這個數據塊就會被釋放,因為在下一次分配時,tx3g atom會替代其位置。
我們稍微修改了谷歌在exploit-38226中提出的ROP鏈。例如,mmap和memcpy被用于了分配shellcode-而實際上,已經有一個緩沖區的地址是已知的了:
我們可以簡單地用mprotect來替換這兩個gadgets。
(注意,并不是所有設備上都是這一個地址)
Google使用了很復雜的gadgets從棧中彈出大量不必要的參數,導致復雜化了ROP鏈。而我們只是簡單地使用了pop {pc} 和pop {r0, r1, r2, pc} 指令。
和Google Project Zero: Stagefrightened一樣,我們使用了相同的stack pivot gadget:
“這樣可以加載大部分寄存器,包括在r0上的棧指針,這個指針指向了我們控制的數據。此時,可以很簡單地通過利用ROP鏈來分配RWX內存,將其復制到shellcode中,然后使用libc.so中的函數和gadgets來跳轉。”(Google Project Zero)
我們的遠程代碼執行漏洞需要知道下面的四個地址:
Call void函數:
pop{pc}
最多有3個參數的Call 函數:
pop{r0,r1,r2,pc}
替換棧并調用shellcode:
add r2,r0,#76;0x4c
ldm r2,{r4,r5,r6,r7,r8,r9,r10,r11,r12,sp,lr}
...
...
bx lr
使用mprotect將一個區域標記為可執行,然后返回:
...
...
bx lr
我們已經知道了mDataSource的確切大小-在溢出時,其類型是MPEG4DataSource:
IDA中顯示,readAt在vtable中的偏移是7:
readAt在字節中的偏移是:
在所有測試過的設備中,MPEG4DataSource的大小和readAt的偏移都是相同的。
最后的ROP鏈在棧中看起來是這樣的,從中可以看出是哪個寄存器復制了該項目:
其他的代碼指定漏洞都類似于exploit-38226。
破解ASLR需要一些設備信息,因為不同的設備會使用不同的配置-可能會修改一些偏移位置或可預測的地址位置。
利用同一個漏洞,也可能獲取到任意的指針讀取,導致web瀏覽器泄露,從而收集破解ASLR需要的信息。但是,我們讀取內存的能力有限,因為這個漏洞存在諸多限制。
因為是通過web瀏覽器來攻擊,所以我們假設能夠執行JavaScript。編碼在媒體文件中的元數據可以通過JavaScript使用某些<video>
標簽屬性來訪問,比如videoWidth,videoHeight和duration。
我們可以利用堆溢出漏洞用一個指針覆蓋這個元數據到任意的內存位置,這樣,任意的內存都可以被發送回瀏覽器,然后通過JavaScript讀取。
所有的元數據都儲存在MetaData類中。這類媒體具有自己的元數據,叫做mFileMetaData:
并且每個Track都有自己的meta字段:
只有把mInitCheck設置為OK,元數據才可以返回到瀏覽器:
只有在解析moov atom時,才可以設置mInitCheck:
今早將“moov”數據塊整合到媒體文件中,能夠保證元數據可以返回到web瀏覽器。
注意:這種方法不適用于Android 4.4.4及更低版本。這些版本上的代碼似乎只會接收包含整個文件部分的moov數據塊。否則,只要“moov”數據塊結束,則會返回NKNOWN_ERROR,因為缺少DRM內容,MPEG4的“sidx”和“moof” atoms都會終止解析:
所以,這種方法只能適用于Android 5.0-5.1。
我們無法重復使用同一個媒體文件來執行多次溢出-在觸發了tx3g bug后,無法避免ERROR_IO從MPEG4Extractor::parseChunk返回:
返回值會轉換成size_t(32位)并與chunk_size(對比)對比-要想實現整數溢出,這個值要遠遠大于2^32
。
MPEG4Extractor::parseChunk會接收一個數據塊offset和數據塊depth。這種方法可以解析數據塊并處理超前偏移。
對于某些MPEG-4 atoms,還會遞歸解析內部的數據塊。如果解析成功,偏移會前進到數據塊末尾。
在使用較大的值造成溢出后,我們從tx3g解析返回到這里:
我們得到了:
所以,如果返回了ERROR_IO,所有的解析都會停止:
也就是說,我們無法使用同一個媒體文件來執行多次溢出。
在使用HTTP來處理視頻流時,mDataSource的類型是NuCachedSource2.mDataSource>readAt
指定的NuCachedSource2::readAt會觸發調用NuCachedSource2::readInternal,如果size過大,mediaserver就會被終止:
在失敗時,CHECK_LE會終止進程,因為要想利用成功,size的值需要很大,每當我們嘗試利用bug時,NuCachedSource2::readInternal檢查總是會失敗。
要想避免進程終止,我們需要繞過NuCachedSource2::readInternal調用。通過使用XMLHttpRequest和responseType=‘blob’
從JavaScript加載媒體,瀏覽器會把視頻緩存到文件系統。使用URL.createObjectURL
,我們可以這樣來引用緩存文件:
URL.createObjectURL
函數會創建一個URL來引用xhr.response中的data數據塊。
下面是一個對象URL示例:
當Chrome 嘗試讀取“ blob” URLs時,實際是作為本地資源訪問。我們可以看到Chrome緩存中的文件:(“ls -a
”顯示隱藏文件)
mediaserver中確實有一個描述符指向了這里:(“ls -l
”后是鏈接)
因為這個URL指向了文件系統,mediaserver把數據來源(在我們這里是mDataSource)設置到了一個FileSource類的對象,而不是NuCachedSource2 類。這兩個類之間有差別,NuCachedSource2處理的是HTTP流和在線媒體緩存,而FileSource能夠在本地文件上執行查找和讀取操作。 FileSource::readAt 并沒有使用任何CHECK_xx宏-也就是說我們繞過了進程終止的問題。
我們前面提到過,mediaserver會解析媒體文件中的元數據并將其發送給web瀏覽器。元數據儲存在MetaData對象中,所有的數據都儲存在MetaData對象的mltems字段中,這些字段實際上是MetaData::typed_data值所對應的FourCC(4字符代碼)秘鑰:
typed_data也在同一個文件中:
如果mSize大于4,ext_data會指向內存中儲存數據的位置。否則,數據會儲存在儲存器中。注意,這兩者是一個并集,也就是說,ext_data和儲存器共用同一個地址。
KeyedVector對象的數據儲存在mStorage字段中(由VectorImpl類繼承):
mStorage的內容是一系列的秘鑰和MetaData::typed_data 元素。在GDB中看起來是這樣的:
例如:
通過覆蓋mStorage的內容,我們可以覆蓋元數據指針,從而指向內存中的任意位置,這樣,信息就可以泄露給web瀏覽器!
注意,只要size大于4,就是一個指針,但是我們可以控制size的大小-我們可以將元數據字段的大小設置為4或更小,避免不必要的元數據字段使用指針。即使是強制的mime型字段,我們也可以將其設置成一個size不大于4的空終止字符串(null-terminated)。
因為mSize必須大于4,我們只能通過duration字段來實現內存泄露-因為duration是8字節長度,所以也是一個指針。videoWidth和videoHeight字段只有4字節,所以無法用來泄露內存。如果把這些字段設置大于4,那么就會導致進程終止。
KeyedVector<key, value>
使用SortedVector<key_value_pair_t<key,value>>
儲存其數據。當一個新的值添加到KeyedVector
時,這個值會被插入到排序向量,這樣,元素順序仍然會根據秘鑰排序。
下面是一些原始的KeyedVector
數據,來自一個具有多組元數據的媒體文件,其順序就是按照秘鑰排序:
我們需要在崩潰之前,知道插入了多少個元數據元素。這點做起來不難,因為我們控制了媒體文件,也就能預測其狀態。在覆蓋元素時,不需要使用相同類型的元素,只需要保證元素順序是根據秘鑰來排序(如上)。
總的來說,我們需要用排序元素覆蓋一些16字節的機構。
這些元素的類型是:
如上所示。
Heap Grooming也是采用類似的方式完成的,使用相同的MPEG-4 atoms(itl,gnre,auth,pref)溢出mDataSource;并利用同一個堆溢出漏洞CVE20153864來實現覆蓋。
在元數據返回給瀏覽器之前,duration最終會作為字符串返回。下面是最長的duration字段:
最終,其時長從百分之一秒轉換成了千分之一秒,會造成數據丟失。接著,我們就可以把一個8字節的整數泄露給瀏覽器,準確率在±500
。
值得注意的是瀏覽器過濾的最高位會設置為負值,無窮大或NaNs(這些數值還有很多表示方式)。這些值會被忽略掉,而duration字段會設置為0。
注意,PRId64 是一個有簽名的64位整數。考慮到整個轉換過程,可能的最大有效值是:
更高的值會溢出到簽名位,而瀏覽器則會過濾到這個值,因為負值長度(無窮大/NaN)是沒有意義的。
只要23個最高位填充的都是0,并且由于向上舍入到1000,造成了幾個位的丟失,我們最終可以泄露8個字節。而根據這個值,我們能獲取到32~35個可用的位。
32位ARM Linux系統上的ASLR算法很簡單-ASLR會將所有的模塊隨機向下移動幾頁,范圍在0~255頁。移動的頁面數量叫做ASLR slide,這個值是在進程啟動是生成的,并且會持續整個進程周期。
然后,這個值會被傳遞到mmap_base:
每個模塊都會加載到其首選基址,然后再按照ASLR slide移動。為了進行驗證,我們運行了mediaserver上百次-記錄下了所有模塊的可能地址范圍。與ASLR隨機化一致,總共的地址范圍有256頁,與其他模塊的距離保持不變。所以說,所有模塊的ASLR slide都是一樣的。
因為所有模塊都使用同一個ASLR slide,我們只需要知道一個模塊的基址就能夠知道所有其他模塊的內存布局,和上面提到的一樣,只有256個選項。
我們可以使用先前創建的設備版本查詢表來獲取gadget的偏移。只要我們知道了一個模塊的基址,我們就能夠把這些gadget偏移翻譯成絕對地址。
比較方便的是,所有必須的gadget都貯存在libc.so中。由于不同設備使用不同版本的libc.so,所以gadget偏移也會變化。但是,在很多情況下,你可以只根據User-Agent HTTP標頭來獲取設備指紋-因為標頭中可能會有設備創建版本和Android版本。
通過構建設備版本查詢表來獲取gadget偏移,我們省去了執行一些高成本操作的需要。最后,要想執行遠程代碼,還需要先知道libc.so在運行時的基址。
通過研究/proc/pid/maps
,我們發現模塊位置基本上是可以預測的,其最大距離是256頁。假設,有一個可讀內存部分大于256頁(1MB),我們可以確定模塊的首選基址可能的最大偏移是255頁。
下圖是對這種概念的解釋:
libicui18n.so模塊能夠運行,因為其代碼部分是可讀的,并且大于1MB:
注意,有些模塊的相鄰部分(例如,text,data)之間有保護頁面,但是,我們只需要足夠大的連續內存區域。在這種情況下,text部分就足夠大了,因為其大小有1,388頁。
ASLR slide是模塊首選基址和運行時基址之間的距離:
所以:
(注意,ASLR向下移動)
我們知道ELF標頭必須是頁面對其,很奇怪的是,ELF標頭位于可執行部分的開頭:
從首選基址開始,每次向下移動一頁,我們最后停在了ELF標頭上。但是,我們無法泄露ELF標頭,因為這種方法的最大限制就是8字節。ELF標頭的前8個字節是:
下面是泄露限制,最大不超過:
其中有一個字段很特殊,因為這個字段的最高位總是0,所以我們可以泄露這個字段-位于偏移0x88上,第三個程序標頭表的p_memsz和p_flags:
ELF標頭的0x34字節+前兩個程序標頭表的0x20字節+字段偏移的0x14字節。
下圖中顯示的是ELF文件格式和感興趣的字段:
第三個程序標頭表中的memsz(p_memsz) 字段符合我們的標準-可讀,模塊是唯一的,位置固定。
下面的命令可以轉儲ELF標頭值,這樣我們就能夠找到前面提到的值了:
(注意,這個8字節值同樣有p_flags,但是,這個值看起來很小,不會超過最大值限制)
現在,我們可以創建一個libicui8n.so p_memsz字段查詢表,每個設備對應一個項目。
通過這種方法,每當受害者解析一個媒體文件時,一些信息就會通過這些字段泄露。要想找到ELF標頭,修復gadget偏移到絕對地址,受害者必須要下載和解析256個媒體文件。由于heap spray,用于執行代碼的媒體文件可能會比較大才能讓heap spray落在預測地址-大約32MB或更大。
HTTP支持GZIP壓縮的內容。對于一個32MB的媒體文件而言,其中大多數填充是0,我們總共可以得到33kB的網絡流量-小了接近1000倍-這樣漏洞利用才能夠可行。
我們的漏洞由幾個模塊組成,用于實現自動化和實時生成漏洞。這些模塊包括:
生成小的通用媒體文件
造成mediaserver崩潰,從而重置其狀態
在自動測試和創建查詢表時,檢查是否存在漏洞
根據特定的設備,生成一個媒體文件,用于在mediaserver中執行shellcode
查詢表提供了gadget偏移和libc.so首選基址
接收運行時的ASLR slide作為一個參數,并將gadget偏移翻譯成絕對地址
根據特定設備,生成一個媒體文件,用于從mediaserver進程中泄露內存
接收一個地址作為參數,從這個地址中泄露數據-這個地址可以是ummapped或保護頁面-導致崩潰
需要通過<video>
標簽的duration字段返回信息
需要web瀏覽器支持blob響應類型的XmlHttpRequest
舊版瀏覽器不支持
從Chrome19開始支持
三星SBrowser基于Chromium-最早版本基于Chromium 18
與ROM關系不大,舊版瀏覽器可能沒有實現ASLR
下面是完整的漏洞利用流程:
本文中提出的這些方法都需要提前了解受害者的設備。即使能觀察到受害者的User-Agent標頭,但是,僅僅憑借這一點也無法了解關鍵的設備信息,比如gadget偏移或可預測地址。
查詢表使用了設備創建版本來查找漏洞利用所需要的相關信息。要想創建查詢表,你需要:
提取首選基址
提取4個必要gadget(在ROP Chain Gadgets 章節提到過)
pop {pc}
pop {r0,r1,r2,pc}
stack pivot gadget地址
mprotect地址
提取首選基址
計算與libc.so之間的距離
ELF標頭模塊標示符
jemalloc區域的大小
可以從libc.so提取
可以在設備上運行測試程序來獲取這些值
不同設備上的最優heap spray地址是不同的,在現實中,不同設備可能使用同一個地址
最佳選擇是多次測試設備
通過進一步的研究,有可能可以不使用查詢表,從而讓漏洞利用更有普適性。
注意,要想找到某些值,最好通過真實的設備來獲取。libc.so和libicui8n.so模塊,以及jemalloc配置都可以從ROM的系統鏡像中提取,而可以猜測可預測的heap spray地址-但是對于某些設備來說,這不是最佳做法。
這次研究證明了這個漏洞是可以被利用的。但是,首先要提前了解相關的設備信息,因為需要根據不同的ROM構建查詢表。
我們的漏洞在使用舊版ROM的Nexus 5上發揮最好。另外,我們還測試了HTC One,LG G3和Samsung S5,但是,在針對不同的廠商時,漏洞利用也稍有不同,需要作出一些修改。
很重要的一點是,這是一個遠程代碼執行漏洞,可能還需要提升mediaserver進程的權限,因為不同的廠商會賦予mediaserver不同的權限(參考/init.rc)。
通過libicui8n.so模塊實現利用時,利用時間最少幾秒鐘,最多2分鐘。
在下一章節,我們提出了一種更復雜的方法,這種方法能夠減少利用時間-差不多下降了4倍。
注意:
但是舊設備上已經存在了大量的漏洞
通過觀察這些數字,很難確定有多少臺設備是面臨威脅的。
這些數字中包括了大量的Android平板,TV和手表,但是,所有這些設備上都存在這些漏洞。
在exploit-38226中,通過使用stbl atom來封裝spray數據,可以成倍加強heap spray的效果。在NCC Group文章中,也提到了進一步改善其效果的方法。利用這種方法,可以大幅縮小遠程代碼執行漏洞的體積。
通過從ELF標頭中泄露不同的信息,可以從很大程度上減少需要的泄露次數。除了泄露ELF標頭,我們可以從任意一個包含多個模塊的內存區域中選擇任意一個地址來泄露。
下面的例子是一個728頁的內存區域,包含有24個ELF標頭,只有5個不可訪問的漏洞。
(在不同設備上,這些值也是不同的-這里只是一個例子)
我們可以從這個區域中隨機選擇地址:
對比來看,如果靠猜測的話,要想從256頁中猜到正確的ASLR,只有0.39%的概率。
在這種方法下,利用耗時在250毫秒和30秒之間,平均5到10秒,取決于標示符數量,不同的設備,運行負擔,網絡穩定性,最重要是嘗試的泄露次數。
這里提到的信息泄露方法無法應用在SBrowser-這一瀏覽器似乎能阻止響應類型是blob的XmlHttpRequest對象加載視頻;我們不清楚這是一種安全機制,還是瀏覽器不支持這種功能。
你可以繞過NuCachedSource2::readInternal method CHECK_LE macro:
通過x-cache-config HTTP 標頭來提供比較大的HighwaterThresholdBytes 值:
要想利用Android 4.4.4上的泄露方法,需要研究DRM內容。