作者:Peterpan0927@360 nirvan team
博客:https://peterpan980927.cn
use two vul and heap srpay twice
0x00.漏洞挖掘
這算是我的一個小練手吧,寫的不是很好,主要是思路分享
queryCompletion in AVEBridge
由于com.apple.AVEBridge這個模塊中的函數比較少,于是我就寫了一個比較小的C語言腳本來Fuzz一下,這個比較簡單,所以一下子就找到了:
mov rdi, [rdi+rsi*8+168]
...
call qword ptr [rax+0x1c8]
這里rsi是我們可控的一個參數,這里相當于我們可以劫持控制流做ROP進行提權,但還需要一個信息泄漏作為配合。
ReadRegister32
這是我在另一個模塊AppleIntelFramebufferAzul中找到的一個漏洞,因為我的目的很明確,就是需要信息泄漏,所以我就從有類似特征的函數進行入手了,如函數名位Readxxx,有memcpy類似的函數。
這個函數也十分簡單:
__int64 __fastcall AppleIntelAzulController::ReadRegister32(...){
...
return *(a2 + a3);
}
通過逆向和調試我找到了這個函數的最上級調用是從IntelFBClientControl::actionWrapper函數開始的,通過調試我們發現傳到ReadRegister32的參數a3是用戶空間可控的,且沒有做任何邊界檢查,也就是說這個是一個越界讀,并且在它的上級函數中發現:
case 0x852:
*(a5+2) = AppleIntelAzulController::ReadRegister32(*(this+2), *a3);
而這個a5正好是IOConnectCallMethod中要傳回用戶空間的那個outputStruct的地址,也就是說這是一個信息泄漏
getDisplayPipeCapability
這也是一個信息泄漏的問題,同樣在AppleIntelFramebufferAzul中,首先來看看一部分代碼:
//a1是this指針
v5 = *(a1+ 8 * *a2 + 0xf60);
if ( v5 ){
if( *( v5 + 0x1dc ) && ( ! *(*(v5 + 0x3f70 ) + 0x100 ) ) ){
memcpy(a3, (v5 + 0x2170), 0x1d8);
*v3 = *v4
result = 0;
}
else{
...
}
}
else{
...
}
return result;
其中a2是我們可控數據且沒有做大小檢查,a3是outputStruct地址,也就是說如果我們進入memcpy分支,同樣可以做到一個信息泄漏。
0x01.漏洞利用
這里我用來做提權的有兩個漏洞,queryCompletion我們可以通過參數來控制越界call,這個的利用就比較簡單,直接通過堆噴構造數據然后泄漏kslide做ROP即可,但是我們在10.13上需要尋找新的gadget,上一次還用的是project-zero在pwn4fun上用的一個,一開始我的思路有問題,總想著有這樣一個pattern
...
push rax
...
...
;... is no pop
pop rsp
...
...
;... didn't change rsp
ret
但是這樣毫無疑問是自己把自己給框住了,事實上可以存在這樣的一種pattern
...
push rax
pop rsp
...
...
;... didn't change rsp
ret
而且我們的出發點可以放在二進制搜索上,直接從切入一段機器碼,不需要理會其上下文,比如我們可以在ida中搜索:
50 5c
然后通過ida的undefine和code來找到我們需要的gadget,這樣的話很快就能找到了,但是我因為思路問題卡了兩天。
接下來就是需要一個info leak來泄漏kslide了。
我一開始找到的一個infoleak是ReadRegister32,但是這個限制比較多,只能從一個很靠后的地址往后讀,后面基本沒有什么有效信息了,也不會有對象來給我們計算kslide。所以我在嘗試了一段時間后放棄了
后來我又找到了一個,這個的利用條件相對來說也比較苛刻(我們可以控制*a2):
//a1是this指針
v5 = *(a1+ 8 * *a2 + 0xf60);
if ( v5 ){
if( *( v5 + 0x1dc ) && ( ! *(*(v5 + 0x3f70 ) + 0x100 ) ) ){
memcpy(a3, (v5 + 0x2170), 0x1d8);
*v3 = *v4
result = 0;
}
else{
...
}
}
else{
...
}
return result;
從上面可以看到我們需要滿足以下幾個條件才可以進入memcpy的分支:
v5有效*(v5+0x1dc)不為0*(v5 + 0x3f70 )是一個有效內核地址*(*(v5 + 0x3f70 ) + 0x100 )為0
并且要想泄漏kslide還需要滿足一個條件,那就是從(v5 + 0x2170)到(v5 + 0x2170 + 0x1d8)的地址上存在著有效數據供我們使用。
我剛一看,就有兩個想法:
就地解決
在這個對象內部來找,看看有沒有合適的,這是最簡單的一種做法,后來我在一次實驗中在偏移0x1398處找到了符合條件的,當時十分高興:

后來想到一個問題,如果這個值超出了對象,那就是我們不可控的了,而且還有一個問題就是就算在對象內,有這么多次的解引用也不一定每次都能滿足,我重啟后果然失效了,我后來看了一下這個對象的大小就是0x1f60,果然不出所料
堆噴
另外一個就是做堆噴,來調偏移,這里我是通過mach_msg來實現的,泄漏分為兩步:
第一次先讀回來一個數據,里面泄漏了到底是哪一個消息 我們釋放這個消息,通過一個內核對象占住,第二次讀回來,泄漏對象虛表
target on MacOS 10.13 or 10.13.1

poc
具體的還有一些細節問題在poc的注釋中做了一些解釋
代碼放在我的github上了
0x02.參考鏈接
mac OS X internals 第九章
本文由 Seebug Paper 發布,如需轉載請注明來源。本文地址:http://www.bjnorthway.com/830/
暫無評論