日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

[保护模式]调用门

發布時間:2025/3/21 编程问答 19 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [保护模式]调用门 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

    • 調用門
      • 調用門執行流程
      • 調用門描述符
    • 調用門實驗
      • 無參調用門
        • 示例代碼
        • 構造調用門
        • 修改GDT表
        • 執行流程
        • 中斷現場
      • 有參調用門
        • 示例代碼
        • 構造調用門
        • 修改GDT表
        • 中斷現場
      • 總結

調用門

調用門執行流程

CALL FAR的指令格式:CALL CS:EIP(EIP是廢棄的)

執行步驟:

  • 根據CS的值 查GDT表,找到對應的段描述符,這個描述符是一個調用門
  • 在調用門描述符中存儲另一個代碼段的段選擇子
  • 選擇子指向的段 段的Base+偏移 就是真正要執行的地址
  • 調用門描述符

    調用門描述符如圖:

    調用門實驗

    無參調用門

    示例代碼

    #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`00000000

    80b95048這個位置并沒有用到,我們就將構造好的調用門放到這個位置,然后查看修改后的結果

    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`00081040

    Param 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段寄存器

    總結

  • 當通過調用門,權限提升到零環時,會Push四個值:返回地址 CS ESP SS
  • 新的CS值由調用門決定
  • 新的SS和ESP由TSS提供
  • 總結

    以上是生活随笔為你收集整理的[保护模式]调用门的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。