Windows内核实验001 中断提权
文章目錄
- 實驗環境
- 內核提權
- IDT的基本知識
- 什么是中斷
- 什么是IDT表
- 在PC Hunter中查看IDT表
- 中斷提權的基本原理
- 寫一個三環的小程序
- 修改IDT表
- 提權測試
本篇文章基于周壑老師的講解,感謝周壑老師。
實驗環境
內核提權
內核態的程序擁有一切權限,在Windows操作系統上,沒有任何其他軟件可以限制內核態的程序。如果讓一個用戶層的小程序,提升至內核權限,那么就可以操作系統上的一切資源,做任何想做的事。今天我們借助一個內核實驗來完成用戶層到內核層的提權。
IDT的基本知識
什么是中斷
當出現需要時,CPU暫時停止當前程序的執行轉而執行處理新情況的程序和執行過程。即在程序運行過程中,系統出現了一個必須由CPU立即處理的情況。此時,CPU暫時終止程序的運行轉而去處理這個情況的過程就叫中斷
什么是IDT表
常見的中斷有 除零(0號中斷)、斷點(3號中斷)、系統調用(2e號中斷), 每一種中斷對應一個中斷號。每一個中斷號都有對應的中斷處理函數。
這樣操作系統就會用數據結構來維護這些中斷處理函數,這個數據結構就是IDT 表。
IDT表全稱:Interrupt Descriptor Table,中斷描述符表。
當CPU產生中斷時,就會去查IDT表,然后執行IDT表中對應的中斷處理函數
在PC Hunter中查看IDT表
打開PC Hunter,點擊內核鉤子->系統中斷表
我們可以看到當前系統的IDT表,其中序號代表的是中斷號 函數名稱指的是產生該序號中斷時會執行的函數,后面則是對應的函數地址。
例如當CPU遇到除零異常時,就會拋出0號中斷,此時查IDT表,找到對應的處理函數Divide error,然后跳轉到函數地址處理除零異常。
中斷提權的基本原理
IDT表是系統用于處理中斷的,自然就有最高的內核權限。中斷提權的基本原理實際上就是將我們自己的函數地址,去替換掉IDT表中的函數地址。進而拋出一個中斷,讓系統跳轉到我們自己的函數。
那么替換掉哪個函數呢?還是回到PC Hunter,IDT表的位置往下拉
從序號0x20開始有一部分未被使用的IDT表,我們就將自己的函數地址替換到0x20的位置即可
寫一個三環的小程序
基本代碼如下
#include "pch.h" #include <iostream> #include <stdio.h> #include <stdlib.h> #include <windows.h>void __declspec(naked) IdtEntry() {__asm{iretd;} }int main() {//0x401040為IdtEntry的函數地址if ((DWORD)IdtEntry!=0x401040){printf("wrong addr:%p", IdtEntry);exit(-1);}printf("%p", IdtEntry);system("pause"); }我們自己寫一個裸函數,然后將地址打印出來。為了方便后面的調試
需要將屬性設置為release,并且去除隨機基址,改用固定基址。
修改IDT表
在配置好雙機調試環境以后,用windbg查看IDT表的基址,IDT表的基址保存在idtr寄存器中
接著用dq命令查看IDT表,每8位對應一個IDT表的處理函數
對比PC Hunter中的函數地址可以發現,IDT表中的函數地址實際上是由IDT地址表中的前四位和后四位拼接而成。
接著我們找到第一個值為00000000的位置,也就是序號為0x20的位置寫入我們自己的函數
kd> eq 80b95500 00408e00`00081040接著將8e修改為ee(8e對應的是DPL描述符特權級 修改以后就能讓用戶層的程序訪問了)
kd> eq 80b95500 0040ee00`00081040提權測試
現在我們還需要讓程序產生一個中斷序號為0x20的中斷,從而跳轉到我們的函數中。那么這個怎么實現呢。只需要加上這樣一條代碼
void go() {__asm int 0x20; }任何一個中斷都能用int [index]的方式進入。
為了觀察是否提權成功,我們在函數中讀取一個內核的地址,我選擇的是IDT表的基址
mov eax,dword ptr ds: [0x80b95400]; mov g_tmp, eax;最后在主函數中將這個地址打印出來。最后編譯exe,在虛擬機中運行
可以看到程序已經打印出了IDT表的基址后半部分0x8CFC0
此時刷新一下PC Hunter,在0x20的位置 函數地址也顯示為我們自己設置的0x401040。
到此,本次實驗結束。最后附上完整代碼
#include "pch.h" #include <iostream> #include <stdio.h> #include <stdlib.h> #include <windows.h>DWORD g_tmp;void __declspec(naked) IdtEntry() {__asm{mov eax,dword ptr ds: [0x80b95400];mov g_tmp, eax;iretd;} }void go() {__asm int 0x20; }int main() {if ((DWORD)IdtEntry != 0x401040){printf("wrong addr:%p", IdtEntry);exit(-1);}go();printf("%p", g_tmp);system("pause"); }總結
以上是生活随笔為你收集整理的Windows内核实验001 中断提权的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: CVE-2012-1876 Intern
- 下一篇: Windows内核实验002 中断现场