27 通過呼叫門實現提權

2021-09-24 19:34:41 字數 2970 閱讀 5839

參考資料:9-呼叫門(無參)

在之前的學習中,jmp far指令實現**跨段的本質是修改cs段暫存器,並不會改變程式的特權級別(即修改cpl的值),如果我們即想要實現**跨段和提權的話,就需要用到呼叫門。

呼叫門是cpu提供的乙個功能,它允許乙個3環(cpl=3)的程式通過這扇「門」來修改cs段暫存器並實現提權到0環(cpl=0),實際上呼叫門是乙個系統段描述符(段描述符的 s=0)。

如果乙個程式實現提權,該指令首先會切換堆疊,即改變ss段暫存器的值,就是cs 或 ss 段暫存器的最低 2 位的值。

如果程式發生提權,會把cs和ss的低2位變成0,換句話說,提權的時候會切換堆疊,這裡我們只關心call far 指令會在新棧 ss0 (表示0環棧):

執行call far指令之前cpu是處於3環的堆疊(cpl=3),當使用call far指令提權發生堆疊切換時,cpu會切換到0環的堆疊(cpl=0),首先會壓入3環的棧(ss)和棧指標(esp),3環的cs段選擇子,以及返回位址(eip)。有同學可能會奇怪為什麼要這麼做?

儲存3環的ss的目的是當呼叫門結束的時候還能回到3環的棧,同理,儲存3環的cs段選擇子是保證可以退回到原來的許可權(cpl=3)。

對於跨段不提權這種情況就簡單很多,不需要切換堆疊,也就不需要儲存3環棧段暫存器 ss 和 esp了,它只修改cs段暫存器。

之前我們說過呼叫門是一種系統段描述符,通常是只有當s位為0的時候,這個描述符才是系統描述符,上圖就是系統段描述符的結構,可以看到和**段資料段的段描述符還是有些區別的。

系統描述符中的低4位元組的16-31位是段選擇子,如果這個**段選擇子指定了dpl的值為0,那麼你在3環可以通過這扇門到達0環空間,這時候你的cpl=3就變成cpl=0從而實現提權了。

換句話說,在呼叫門描述符中儲存了另乙個**段的段選擇子(即低4位元組的16-31位),這個段選擇子指向的段就是作業系統指定的跳轉位置,然後使用 call + 呼叫門的段選擇子的方式實現跳轉並提權,可以讓3環程式進入0環,也就是由使用者態變成核心態,在此之前,我們需要先構造乙個"門描述符"(呼叫門)。

0040ec00`00081030是我們根據門描述符的結構來構造的乙個呼叫門描述符,有同學可能會問0040ec00`00081030這個門描述符是如何構造出來的呢?大家可以回憶一下門描述符的結構圖。

門描述符的高4位元組的16-31位和低4位元組的0-15位構成了要跳轉的位址,即00401030位址,8-15位是用於描述這是乙個有效的門描述符,所以是ec,0-4位是表示攜帶的引數,如果不攜帶引數這4位預設是0,5-7位預設也是0。

另外,在低4位元組的16-31位是乙個段選擇子,它指向了我們要執行的**段,如果你想在跳轉的時候實現提權的話,可以指定為該段選擇子的dpl=0,不想提權的話可以指定dpl=3,這裡我們希望提權,所以指定段選擇子為0008。

門描述符已經構造好了,通過eq 8003f048 0040ec00`00081030命令把它寫入到gdt表中:

呼叫門實驗的示例**如下:

#include #include __declspec(naked) void getdata() 

}int main(int argc, char* ar**) ; // 這裡的 eip被廢棄

__asm

getchar();

return 0;

}

開啟vc6,在main函式的第一行下斷點,按f5執行到斷點,檢視getdata函式的彙編和暫存器視窗,如下圖所示:

我們可以看到getdata的函式位址是00401030,這個跳轉的位址就是我們之前構造的門描述符指定的跳轉位置,然後再按f5,程式就會進入中斷並且中斷到0環偵錯程式,也就是windbg,有同學可能會奇怪為什麼不是中斷到vc偵錯程式而是windbg偵錯程式呢???  這是因為vc偵錯程式是3環的,而windbg是0環偵錯程式具有優先權,因此會先中斷到windbg。

注意:在暫存器視窗中cs斷暫存器的值是001b,ss段暫存器的值是0023,說明這是乙個3環的程式。

此時再檢視windbg偵錯程式的暫存器視窗:

windbg偵錯程式的暫存器視窗中的cs段暫存器的值是0008,它指向了乙個0環的**段,進行了許可權切換,這意味著一旦進行許可權切換,那麼ss短暫存器的值也會發生改變,當前ss的值變成了0010;還有esp暫存器,在許可權切換之後esp的值由0012ff28變成了b23e0dd0。

學過linux程序間通訊的同學肯定知道,4g記憶體空間,其中0-3g是使用者空間,3-4g是核心空間。也就是說0012ff28是使用者空間的記憶體位址,而b23e0dd0則是核心空間的位址(即所謂的0環的位址)。

換句話說,esp的值變化說明了一旦涉及到許可權切換,那麼程式相應的堆疊也會進行切換,我們可以檢視b23e0dd0位址的堆疊來驗證這點,如下圖所示:

重點關注以上4個值,00401163是最後壓入的乙個返回位址,0000001b是原來cs暫存器的值,0012ff28是原來esp的值,00000023是原來ss的值,這和跨段提權那一小節講的是一樣的。

Windows核心 (7)呼叫門提權 無參

對呼叫門的呼叫可以訪問與當前 特權相同或者特權更高的 段中的過程。指令格式 call cs eip eip是廢棄的 執行步驟 根據cs的值 查gdt表,找到對應的段描述符 這個描述符是乙個呼叫門.在呼叫門描述符中儲存另乙個 段段的選擇子.選擇子指向的段 段.base 偏移位址 就是真正要執行的位址....

18 5 通過設計器實現約束

約束 保證資料完整性 資料庫約束是為了保證資料的完整性 正確性 而實現的一套機制。非空約束 主鍵約束 pk primary key constraint 唯一且不為空 唯一約束 uq unigue constraint 唯一,允許為空,但只能出現一次 預設約束 df default constrai...

7 0通過Intent呼叫系統相機(包含動態許可權)

官方的解決方案 步驟1 在androidmanifest.xml的 包名是androidmanifest.xml開頭package的屬性 android name android.support.v4.content.fileprovider android authorities 包名.filep...