(10)调用门提权(无参数)
一、實驗步驟
本節實驗的目標是自己實現調用門提權,在低地址空間中執行代碼訪問高2G的內存。實驗步驟如下:
查看GDT表內容,8003f008是系統代碼段,8003f018是用戶代碼段。
為了使用調用門提權,需要在GDT表中創建一個調用門描述符
該調用門描述符的段偏移字段指向我們定義的裸函數,提權后在該函數內執行權限就能變成0環。調用門描述符中的段選擇子字段要設置成指向某個系統代碼段,比如8003f008,則段選擇子設置為00001000b = 0x08。DPL要設置成3,因為我們調用CALL FAR 時的CPL是3。P,DPL,S位設置成0xE,TYPE固定設置成0xC表示這是一個調用門。因為本實驗測試無參調用,所以高4字節的低8位全設置成0.至此,調用門描述符除了Offset in Seg段偏移還沒指定外,其他位已經全部確定。未確定的位暫定為0,調用門描述符的值是 0000EC00 00080000.
接下來,需要確定裸函數的地址,我們在VC6中編寫函數,代碼如下:
進入反匯編,查看裸函數的地址
將該地址填寫到調用門段選擇子中,0040EC00 00081020,至此,調用門段選擇子構造完畢.
將段選擇子寫入到GDT表某個全為0(沒有用)的位置,這里我選擇的是8003f048。
回到程序,開始調試,注意觀察CALL FAR前CS,SS,ESP的值
調用前,CS=1B,SS=23,ESP=12FF28
執行 CALL FAR 當執行到 INT 3 時,在windbg中斷下,觀察此時的寄存器
可以看到,CS=0x08,就是我們選擇的系統代碼段的段選擇子;SS=0x10,和剛才在3環中看到的0x23不同,說明提權會導致堆棧切換;EIP=401020,說明確實跳轉到了我們定義的裸函數內。
現在,打開windbg內存窗口,驗證我們之前畫的堆棧圖是否正確。
[ESP]存儲的0040d4a3就是 CALL FAR 調用處的地址;[ESP-4]是調用者CS也就是1B,沒有問題;[ESP-8]應該是3環的ESP,[ESP-C]是0x23,是原來的SS,都沒有問題,完全符合預期。
至此,我們成功地通過調用門,調用了我們定義的函數,接下來,我們要修改裸函數,讓它執行一些訪問高2G數據的操作,以證明裸函數內確實擁有0環權限。修改后代碼如下:
// 調用門提權.cpp : Defines the entry point for the console application. //#include "stdafx.h" #include <windows.h>DWORD dwH2GValue; // 存儲高2G的數據// 該函數通過 CALL FAR 調用,使用調用門提權,擁有0環權限 void __declspec(naked) FunctionHas0CPL() {__asm{ mov eax,0x8003f008mov ebx,[eax]mov dwH2GValue,ebxretf} }int main(int argc, char* argv[]) {char buff[6] = {0,0,0,0,0x48,0};__asm{call fword ptr [buff] // 長調用,使用調用門提權} printf("%08x\n",dwH2GValue);getchar();return 0; }如果函數地址發生變化,注意更新調用門描述符
執行程序,可以看到,我們成功讀取了GDT表第二項的低4字節。
至此,調用門提權(無參)實驗成功。
二、提權后通用寄存器有沒有發生變化?
通過實驗得知,沒有變化,0環和3環的寄存器數據是一樣的。
總結
以上是生活随笔為你收集整理的(10)调用门提权(无参数)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: (9)跨段跳转,短调用和长调用堆栈图
- 下一篇: (11)调用门提权(有参)