[保护模式]调用门
文章目錄
- 調用門
- 調用門執行流程
- 調用門描述符
- 調用門實驗
- 無參調用門
- 示例代碼
- 構造調用門
- 修改GDT表
- 執行流程
- 中斷現場
- 有參調用門
- 示例代碼
- 構造調用門
- 修改GDT表
- 中斷現場
- 總結
調用門
調用門執行流程
CALL FAR的指令格式:CALL CS:EIP(EIP是廢棄的)
執行步驟:
調用門描述符
調用門描述符如圖:
調用門實驗
無參調用門
示例代碼
#include <stdio.h> #include <stdlib.h> #include <windows.h>void __declspec(naked)GetRegister() {__asm{int 3;retf;} }int main() {__asm{int 3;}printf("%p", GetRegister);//構造call cs eip指令char buff[6];*(DWORD*)&buff[0] = 0x12345678; //廢棄的EIP*(WORD*)&buff[4] = 0x48; //段選擇子 __asm{call fword ptr[buff];}getchar();return 0; }構造調用門
首先查看函數地址
記錄下這個值:00401040
offset in segment 31:16:0040 P:1 DPL:11 S:0--->E Type:1100--->C Param Count:0 Segment Select:0008 offset in Segment 15:00:1040 #調用門描述符 0040EC00`00081040修改GDT表
查看GDT表
kd> dq gdtr 80b95000 00000000`00000000 00cf9b00`0000ffff 80b95010 00cf9300`0000ffff 00cffb00`0000ffff 80b95020 00cff300`0000ffff 80008b1e`400020ab 80b95030 834093f7`1c003748 0040f300`00000fff 80b95040 0000f200`0400ffff 00000000`00000000 80b95050 830089f6`f0000068 830089f6`f0680068 80b95060 00000000`00000000 00000000`00000000 80b95070 800092b9`500003ff 00000000`0000000080b95048這個位置并沒有用到,我們就將構造好的調用門放到這個位置,然后查看修改后的結果
kd> eq 80b95048 0040EC00`00081040 kd> dq gdtr 80b95000 00000000`00000000 00cf9b00`0000ffff 80b95010 00cf9300`0000ffff 00cffb00`0000ffff 80b95020 00cff300`0000ffff 80008b1e`400020ab 80b95030 834093f7`1c003748 0040f300`00000fff 80b95040 0000f200`0400ffff 0040ec00`00081040 80b95050 830089f6`f0000068 830089f6`f0680068 80b95060 00000000`00000000 00000000`00000000 80b95070 800092b9`500003ff 00000000`00000000執行流程
接下來捋一遍整個調用門的執行流程
char buff[6];*(DWORD*)&buff[0] = 0x12345678; //廢棄的EIP*(WORD*)&buff[4] = 0x48; //段選擇子 __asm{call fword ptr[buff];}當代碼執行到call fword ptr[buff];時,其實就相當于執行下面這句
call 0x48:0x12345678首先拆分0x48這個段選擇子
?01001000? index:9 TI:0 PRL:0接著查IDT表的第十項 也就是我們構造的調用門。
進行段權限檢查,檢查通過,切換CS段寄存器提升權限,并跳轉到段的Base+Offset的位置。
中斷現場
將程序編譯后放到虛擬機運行,此時windbg第一次產生中斷,這個時候中斷在用戶層
kd> g Break instruction exception - code 80000003 (first chance) 001b:00401056 cc int 3查看一下用戶層的寄存器環境
kd> r eax=00203340 ebx=7ffd9000 ecx=3d9c2800 edx=00000002 esi=74c62108 edi=002040b0 eip=00401056 esp=0012ff38 ebp=0012ff40 iopl=0 nv up ei pl nz ac po nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000212 001b:00401056 cc int 3- EIP=00401056
- esp=0012ff38
- cs=001b
- ss=0023
接著再次運行程序,此時windbg第二次產生中斷,這個時候中斷于內核層
kd> g Break instruction exception - code 80000003 (first chance) 00401040 cc int 3再次查看當前的寄存器環境
kd> r eax=00000048 ebx=7ffd9000 ecx=74c19a18 edx=74c610a4 esi=74c62108 edi=002040b0 eip=00401040 esp=a74ffca0 ebp=0012ff40 iopl=0 nv up ei pl nz na po nc cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00000202 00401040 cc int 3- eip=00401040 ->我們指定的偏移
- cs=0008->我們指定的零環的段選擇子
- ss=0010 ->零環的ss段寄存器
- esp=a74ffca0 ->零環的堆棧
接著再查看一下當前的ESP
kd> dd esp a74ffca0 0040107c 0000001b 0012ff38 00000023 a74ffcb0 00000000 00000000 00000000 00000000 a74ffcc0 0000027f 00000000 00000000 00000000 a74ffcd0 00000000 00000000 00001f80 0000ffff a74ffce0 00000000 00000000 00000000 00000000 a74ffcf0 00000000 00000000 00000000 00000000 a74ffd00 00000000 00000000 00000000 00000000 a74ffd10 00000000 00000000 00000000 00000000- 0040107:三環的返回地址
- 0000001b:三環段選擇子
- 0012ff38:三環的ESP
- 00000023:三環的SS段寄存器
有參調用門
示例代碼
#include <stdio.h> #include <stdlib.h> #include <windows.h>void __declspec(naked)GetRegister() {__asm{int 3;retf;} }int main() {__asm{int 3;}printf("%p", GetRegister);//構造call cs eip指令char buff[6];*(DWORD*)&buff[0] = 0x12345678; //廢棄的EIP*(WORD*)&buff[4] = 0x48; //段選擇子 __asm{//有參數的時候 參數需要自己指定push 1;push 2;push 3;call fword ptr[buff];}getchar();return 0; }構造調用門
offset in segment 31:16:0040 P:1 DPL:11 S:0--->E Type:1100--->C Param Count:3 Segment Select:0008 offset in Segment 15:00:1040 #調用門描述符 0040EC03`00081040Param Count參數個數修改為3 其他不變
修改GDT表
kd> eq 80b95048 0040EC03`00081040 kd> dq gdtr 80b95000 00000000`00000000 00cf9b00`0000ffff 80b95010 00cf9300`0000ffff 00cffb00`0000ffff 80b95020 00cff300`0000ffff 80008b1e`400020ab 80b95030 834093f7`1c003748 7f40f3fd`f0000fff 80b95040 0000f200`0400ffff 0040ec03`00081040 80b95050 830089f6`f0000068 830089f6`f0680068 80b95060 00000000`00000000 00000000`00000000 80b95070 800092b9`500003ff 00000000`00000000中斷現場
編譯后在虛擬機中運行,此時windbg第一次中斷,這個時候中斷在用戶層,查看一下當前的寄存器環境
kd> g Break instruction exception - code 80000003 (first chance) 001b:00401056 cc int 3 kd> r eax=00203340 ebx=7ffda000 ecx=8966fe00 edx=00000002 esi=74c62108 edi=002040b0 eip=00401056 esp=0012ff38 ebp=0012ff40 iopl=0 nv up ei pl nz ac po nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000212 001b:00401056 cc int 3- eip=00401056
- esp=0012ff38
- cs=001b
- ss=0023
接著再次運行,程序第二次中斷,此時中斷在內核層,并查看當前的寄存器環境
kd> r eax=00000048 ebx=7ffda000 ecx=74c19a18 edx=74c610a4 esi=74c62108 edi=002040b0 eip=00401040 esp=8d303c94 ebp=0012ff40 iopl=0 nv up ei pl nz na po nc cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00000202 00401040 cc int 3- eip=00401040–>我們指定的Offset
- esp=8d303c94–>零環的堆棧
- cs=0008–>我們指定的零環的段選擇子
- ss=0010–>零環的SS段寄存器
接著再查看一下當前的堆棧
kd> dd esp 8d303c94 00401082 0000001b 00000003 00000002 8d303ca4 00000001 0012ff2c 00000023 00000000 8d303cb4 00000000 00000000 00000000 0000027f 8d303cc4 00000000 00000000 00000000 00000000 8d303cd4 00000000 00001f80 0000ffff 00000000 8d303ce4 00000000 00000000 00000000 00000000 8d303cf4 00000000 00000000 00000000 00000000 8d303d04 00000000 00000000 00000000 00000000- 00401082為三環的返回地址
- 0000001b為三環的CS段選擇子
- 00000003 00000002 00000001為我們傳遞的三個參數
- 0012ff2c為三環的ESP
- 00000023為三環的SS段寄存器
總結
總結
- 上一篇: [保护模式]段间跳转和跨段跳转
- 下一篇: [保护模式]中断门