你們在聚安全挑戰賽正式賽第三題中,遇到android app 遠程控制的題目。咱們今天帶你一探究竟,如何攻破這道題目。html
購物應用pwn (6分)android
環境:web
要求在ARM 64位Android手機上攻擊成功,也可在模擬器(運行Google官方Android SDK提供的Google APIs ARM64 Android 7.0鏡像)中攻擊成功,其中鏡像會打包提供,參見題目下載連接。模擬器執行命令參考以下:(qemu-system-aarch64 -sysdir . -datadir . -kernel kernel-qemu -system system.img -ramdisk ramdisk.img -data userdata.img)chrome
包含bug的apk一個shell
必須在非root環境json
攻擊過程:瀏覽器
將apk裝入模擬器中。安全
打開chrome瀏覽器,訪問選手的惡意網頁的地址。(web服務由選手本身搭建)app
經過選手的惡意網頁,便可獲取此app的shell。ide
apk顯示「購買成功」
目標:Chrome瀏覽器點擊連接,致使遠程觸發app的購買邏輯,app界面上顯示「購買成功」。
評分標準:經過瀏覽器訪問網頁即達到控制app遠程任意代碼執行得6分,其中:
反彈shell控制app ,5分。
可以進一步讓app界面顯示「購買成功」分數進一步得1分 。
需提供遠程任意代碼執行的利用程序源代碼。
攻擊流程以下:
其中題目中要求「Chrome瀏覽器點擊連接」,Chrome的官方文檔規定了如何從連接發intent啓功app,官方文檔連接:https://developer.chrome.com/... 。反彙編ExamPwn.apk文件發現AndroidManifest.xml中果真有接受相關intent的內容。如圖:
類LoginActivity先接受這個intent解析出賬號密碼並匹配,賬號密碼直接以明文硬編碼在類LoginActivity中,反彙編直接能夠看見。匹配正確後將intent中的url丟給類MainActivity。也就是說攻擊者的網頁至少以下:
反彙編類MainActivity發現,它會把url指向的文件看成特定格式的json解析。根據json內容,它會執行上傳文件和下載解析顯示圖片的任務。不難發現上傳文件的路徑是攻擊者提供的,app沒有檢查是否合法,形成任意文件上傳,信息泄漏的漏洞。此時構造以下json能夠泄漏app的內存地址
想要拿到Android app遠程代碼執行權限,漏洞基本只能存在於Dex動態加載邏輯、訪問遠程數據的native代碼中。用工具androguard掃描發現,沒有dex動態加載問題,漏洞只可能在native代碼中。App有native代碼libHt5g.so用於解析和播放gif圖片。漏洞極可能就在其中,反彙編libHt5g.so發現有不少函數都有FrameSequence關鍵詞。實際上就是Google本身的gif顯示庫,2016年12月和2017年1月都曝出過漏洞。
詳情見:
https://source.android.com/in...
https://source.android.com/in...
但光看源代碼基本不能利用。因此說出題者應該放了其餘漏洞在裏面。
反彙編看到private static native long nativeGetFrame(long j, int i, Bitmap bitmap, int i2);的時候能夠發現,當gif一幀的大小小於等於1024字節的時候,buffer是分配在stack上而後再memcpy到原來的bitmap buffer中。不只畫蛇添足並且跟源代碼不一致,基本肯定出題者準備的是棧溢出。
到此爲止若是尚未發現有源代碼能夠本身編譯而後binary diff的話,能夠本身構造小於1024字節的gif,而後逐個字節替換爲0xff,最快幾十字節改就會發現crash,分析後發現Gif格式中,一幀圖片的Left變量被當成負數處理了,無符號整數被看成有符號整數處理。而知道用binary diff的同窗基本直接能夠定位到出題者修改的全部地方,包括解析Left出錯的地方。
光看源代碼基本不能利用是由於bitmap是RGBA格式,RGB能夠控制,而Alpha在源代碼裏直接被0xff填充,意爲不透明。這樣的話溢出的數據基本很難控制。因此做爲出題者的咱們按照gif格式添加了tag爲0x77的ExtentionBlock,裏面存放的數據做爲Alpha值。這樣就能徹底控制溢出的數據了。
因爲Left變成了負數,形成了向低地址的任意數據的棧溢出。
受影響彙編代碼
能夠看到此函數在棧上申請了0x480大小的字節。其中處於高地址的0x400(1024)個字節是將被溢出的buffer,處於低地址的0x80個字節是能夠做爲掩蓋目標。到此能夠任意代碼執行了。
因爲以前拿到/proc/self/maps,內存地址都泄露了,這裏說一下咱們的rop方法。
溢出後控制memcpy的dst參數,將準備好的數據拷貝到從/proc/self/maps裏找到的暫時不用的一塊內存。咱們在linker64裏找到兩個gadget
一、修改sp地址到新地址
二、把所在內存修改成可執行
三、跳轉到自定義的可執行內存