Windows內核分析索引目錄:https://www.cnblogs.com/onetrainee/p/11675224.html
調用門
問題索引:
1. 調用門的"門"這字的含義。
2. 如果通過這扇門走?
3. 為什么需要調用門?
4. 為何構造call時數組前四位隨便寫?
5. 調用門構造實驗
6. 遠調用的特點?
7. 遠調用帶參數實驗
8. 遠調用提權實驗
9. 權限的CALL指令的門權限檢查
10.call調用門提權,iretd降權實驗
問題解答:
1. 調用門的"門"這字的含義。
門-通往另外一個世界的通道,同時也是一種控制的阻礙。2. 如果通過這扇門走?
Segment - 段選擇子,通過這個段選擇子來替換代碼段寄存器。
Offset in Segment - 段內偏移,段只能提供基地址,但怎么走還是要看在基地址基礎上計算偏移量的。
3. 為什么需要調用門?
方便權限控制,可以不改變R3層的調用方式的基礎上改變調用權限來實現控制效果(寫好的代碼不變,但我可以讓你不通過)。
4. 為何構造call時數組前四位隨便寫?
這四位應該本應該寫偏移量的,但是調用門中自帶着段內偏移,因此我們並不需要這四位,直接隨便填寫即可。
5. 調用門構造實驗
實驗原理:構造調用門,然后執行調用門中指向的函數。
#include "stdafx.h" #include <stdlib.h> __declspec(naked) void callgate(){ __asm{ int 3; retf; } } int main(int argc, char* argv[]) { char buf[6] = {0}; *(int*)&buf[0] = 0x12345678; *(short*)&buf[4] = 0x4b; printf("%x\r\n",callgate); getchar(); __asm{ call fword ptr buf; } system("pause"); return 0; }
windbg進行如下修改
eq 8003f090 00cf9b00`0000ffff (代碼段描述符)
eq 8003f048 0040ec00`00901005 (調用門,指向代碼段)
6. 遠調用的特點?
call far,當使用調用門時,就是遠程調用。
遠程調用即需要切換環境,至少保存四個值 ret,cs,ss,esp
只要執行遠call,其就會切換堆棧(下面實驗我們就可以看出)
7. 遠調用帶參數實驗
實驗思路:我們在0環讀取gdtr表,如果提權成功則可以讀取,否則不可以讀取。
#include "stdafx.h" #include <stdlib.h> __declspec(naked) void callgate(){ __asm{ int 3; retf 0x4; } } int main(int argc, char* argv[]) { char buf[6] = {0}; *(int*)&buf[0] = 0x12345678; *(short*)&buf[4] = 0x4b; printf("%x\r\n",callgate); getchar(); __asm{ push 0x12345678; call fword ptr buf; } system("pause"); return 0; }
windbg 修改 調用門參數 (承接上個實驗)
eq 8003f048 0040ec01`00901005 (添加一個參數)
堆棧如下:
從中我們可以看出,只要通過調用門,其會另其一套堆棧,同時還需要記住參數的壓棧順序,參數是在中間部分。
另外,retf 0x4, 不僅平衡三環的堆棧,也是平衡零環的堆棧。
8. 遠調用提權實驗
實驗思路:我們在0環讀取gdtr表,如果提權成功則可以讀取,否則不可以讀取。
// callgate.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include <stdlib.h> int value = 0; __declspec(naked) void callgate(){ __asm{ //int 3; pushad; pushfd; mov eax,dword ptr ds:[0x8003f008]; mov value,eax; popfd; popad; retf 0x4; } } int main(int argc, char* argv[]) { char buf[6] = {0}; *(int*)&buf[0] = 0x12345678; *(short*)&buf[4] = 0x48; printf("%x\r\n",callgate); getchar(); __asm{ push 0x12345678; call fword ptr buf; } printf("%x\n",value); system("pause"); return 0; }
實驗效果
9. 權限的CALL指令的門權限檢查
其需要經過兩關來檢查:
門檢查 max(CPL,RPL) <= DPL
CPL >= 代碼段的DPL
10.call調用門提權,iretd降權實驗
iretd用於其中斷返回的,注意其堆棧的變化。
#include "stdafx.h" #include <stdlib.h> int value = 0; __declspec(naked) void callgate(){ __asm{ //int 3; pushad; pushfd; mov eax,dword ptr ds:[0x8003f008]; mov value,eax; popfd; popad; pop eax; pop ebx; pushfd; push ebx; push eax; iretd; } } int main(int argc, char* argv[]) { char buf[6] = {0}; *(int*)&buf[0] = 0x12345678; *(short*)&buf[4] = 0x48; printf("%x\r\n",callgate); getchar(); __asm{ call fword ptr buf; } printf("%x\n",value); system("pause"); return 0; }