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

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > windows >内容正文

windows

Windows内核实验002 中断现场

發(fā)布時(shí)間:2025/3/21 windows 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Windows内核实验002 中断现场 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

文章目錄

    • 如何獲取中斷現(xiàn)場(chǎng)環(huán)境
    • 中段現(xiàn)場(chǎng)環(huán)境
      • 觀察中斷現(xiàn)場(chǎng)堆棧環(huán)境
      • 觀察中斷現(xiàn)場(chǎng)的寄存器環(huán)境
    • 段選擇子
      • 段寄存器結(jié)構(gòu)
      • 變化的段寄存器的具體含義
    • 遺留問(wèn)題:SS段寄存器和棧頂指針來(lái)自于哪?
      • 什么是TSS
      • TSS的工作細(xì)節(jié)
      • 中斷提權(quán)的任務(wù)切換過(guò)程
    • 實(shí)驗(yàn)代碼

上一課我們已經(jīng)實(shí)現(xiàn)了利用中斷提權(quán)的方式讓自己寫的函數(shù)擁有了零環(huán)的權(quán)限,但是為了更方便的寫零環(huán)代碼。我們還需要搞清楚中斷現(xiàn)場(chǎng)的上下文環(huán)境,什么資源可以被使用,什么資源不能被使用。如果不清楚現(xiàn)場(chǎng)的環(huán)境,就很容易寫出有問(wèn)題的代碼,從而導(dǎo)致系統(tǒng)藍(lán)屏。

如何獲取中斷現(xiàn)場(chǎng)環(huán)境

比較方便的一個(gè)方式是在函數(shù)內(nèi)部將當(dāng)前的寄存器包括通用寄存器 段寄存器甚至是控制寄存器等等全部打印出來(lái)。

中段現(xiàn)場(chǎng)環(huán)境

觀察中斷現(xiàn)場(chǎng)堆棧環(huán)境

我們加上下面幾行代碼,來(lái)觀察一下中斷之前和之后的堆棧環(huán)境,看一下int 20這條指令對(duì)堆棧的影響

DWORD g_esp[2];void __declspec(naked) IdtEntry() {__asm{mov [g_esp+4], esp;iretd;} }void go() {__asm mov[g_esp], esp;__asm int 0x20; }

運(yùn)行程序,可以看到在中斷提權(quán)之前,地址是一個(gè)三環(huán)的esp,而中斷之后esp的地址則變成了零環(huán)的地址。

接下來(lái)我們?cè)诖a中加入一條int3指令,在調(diào)試器中觀察一下堆棧內(nèi)的數(shù)據(jù)情況

kd> dps esp a6e63c9c 0040114f a6e63ca0 0000001b a6e63ca4 00000246 a6e63ca8 0012ff44 a6e63cac 00000023 ......

可以看到棧頂?shù)臄?shù)據(jù)是0x0040114f,接著用ub命令觀察這個(gè)地方的反匯編

kd> ub 0040114f 00401131 668cc0 mov ax,es 00401134 66a380334000 mov word ptr ds:[00403380h],ax 0040113a 668ce0 mov ax,fs 0040113d 66a37c334000 mov word ptr ds:[0040337Ch],ax 00401143 668ce8 mov ax,gs 00401146 66a378334000 mov word ptr ds:[00403378h],ax 0040114c 58 pop eax 0040114d cd20 int 20h

可以發(fā)現(xiàn),這個(gè)地方就是我之前寫的代碼,也就是三環(huán)的返回地址。堆棧中的其他數(shù)據(jù)含義如下:

  • 0000001b是三環(huán)的cs
  • 00000246是三環(huán)的eflags
  • 0012ff44是三環(huán)的esp
  • 00000023是三環(huán)的ss

總結(jié):通過(guò)中斷門進(jìn)入零環(huán)之前需要先保存三環(huán)的寄存器環(huán)境來(lái)達(dá)到再次返回三環(huán)的目的

觀察中斷現(xiàn)場(chǎng)的寄存器環(huán)境

接下來(lái)我們修改一下代碼,把所有的寄存器盡可能全部打印出來(lái)。接著運(yùn)行我們寫的程序

可以看到中斷現(xiàn)場(chǎng)前后的寄存器環(huán)境中,ESP從三環(huán)棧切換到了零環(huán)棧,CS從0x1B變成了0x8,代碼提權(quán)也是從這里體現(xiàn)的,另外ss也發(fā)生了變化。

那么問(wèn)題也就來(lái)了,這些寄存器改變的背后是一種什么樣的機(jī)制,另外這些變化的寄存器都是從哪來(lái)的。要想知道這個(gè)問(wèn)題的答案,需要了解一個(gè)東西叫做段選擇子

段選擇子

段寄存器結(jié)構(gòu)

段寄存器結(jié)構(gòu)可以抽象成以下的結(jié)構(gòu)

struct SegMent {WORD selector; //段選擇子WORD attribute; //屬性DWORD base; //基址DWORD limit; //段限長(zhǎng) }
  • selector: 首先可見(jiàn)部分16位對(duì)應(yīng)上面SegMent的selector成員。在 OD 中,可以看到段寄存器后面就跟著一個(gè)數(shù)字,比如 ds 后面的 0023。而 0023 后面的部分就是,剩余部分不可見(jiàn)部分,不過(guò) OD 也給我們展示出來(lái)了
  • attribute: attribute 屬性記錄了該段是否有效,是否可讀寫等權(quán)限。如果往一個(gè)不可寫的段執(zhí)行寫數(shù)據(jù),會(huì)報(bào)異常。
  • base 表示基地址
  • limit 表示段界限,如果在超出了段界限進(jìn)行讀寫,會(huì)報(bào)錯(cuò)。

在段寄存器中,16位的段選擇子是可見(jiàn)的,其余80位的不可見(jiàn)的。我們主要關(guān)注段選擇子

例如上圖中CS的段選擇子位0x23,SS的段選擇子為0x2B。段選擇子就是一個(gè)數(shù)字,一共有16位,結(jié)構(gòu)如下:

| 1 | 0 | 字節(jié) |7654321076543 2 10| 比特 |-------------|-|--| 占位 | INDEX |T|R | 含義 | |I|P | | | |L |
  • INDEX:高13位表示的是在GDT數(shù)組或LDT數(shù)組的索引號(hào)
  • TI:Table Indicator,這個(gè)值為0表示查找GDT,1則查找LDT
  • RPL:請(qǐng)求特權(quán)級(jí)。以什么樣的權(quán)限去訪問(wèn)段。

變化的段寄存器的具體含義

明白了段選擇子的結(jié)構(gòu),接下來(lái)就來(lái)拆解其中的具體含義,以CS從0x1B變成了0x8為例:

0x1B=?00011011?

  • 索引號(hào):00011=3,代表查找GTB表下標(biāo)為3的描述符
  • TI:0代表查GDT表
  • RPL:11=3 代表特權(quán)等級(jí)為3 也就是三環(huán)權(quán)限

0x8=?00001000

  • ?索引號(hào):00001,代表查找GTB表下標(biāo)為1的描述符
  • TI:0代表查GDT表
  • RPL:0 代表特權(quán)等級(jí)為0,也就是零環(huán)權(quán)限

總結(jié):CS段寄存器從0x1B變成0x8,主要是代表特權(quán)等級(jí)從三環(huán)提升到了零環(huán)

權(quán)限切換了,esp堆棧和相應(yīng)的段寄存器ss自然也會(huì)跟著切換。因?yàn)闂?shù)據(jù)是線程的核心資源,特權(quán)切換必須伴隨棧切換

遺留問(wèn)題:SS段寄存器和棧頂指針來(lái)自于哪?

我們已經(jīng)知道代碼提權(quán)的時(shí)候是需要切換棧的。那么,還剩下一個(gè)問(wèn)題:就是SS段寄存器和棧頂指針是來(lái)自于哪?

答案是來(lái)自于TSS 任務(wù)狀態(tài)段

什么是TSS

TSS 全稱task state segment,是指在操作系統(tǒng)進(jìn)程管理的過(guò)程中,任務(wù)(進(jìn)程)切換時(shí)的任務(wù)現(xiàn)場(chǎng)信息。注意不要把TSS和任務(wù)切換關(guān)聯(lián)起來(lái),它只是一塊用于保存任務(wù)現(xiàn)場(chǎng)的一些數(shù)據(jù)

Inter白皮書(shū)給出的TSS在內(nèi)存中的圖是這樣的:

看的一臉懵逼對(duì)吧?我也看的一臉懵逼。抽象成結(jié)構(gòu)體就是這樣的

typedef struct TSS {DWORD link; // 保存前一個(gè) TSS 段選擇子,使用 call 指令切換寄存器的時(shí)候由CPU填寫。// 這 6 個(gè)值是固定不變的,用于提權(quán),CPU 切換棧的時(shí)候用DWORD esp0; // 保存 0 環(huán)棧指針DWORD ss0; // 保存 0 環(huán)棧段選擇子DWORD esp1; // 保存 1 環(huán)棧指針DWORD ss1; // 保存 1 環(huán)棧段選擇子DWORD esp2; // 保存 2 環(huán)棧指針DWORD ss2; // 保存 2 環(huán)棧段選擇子// 下面這些都是用來(lái)做切換寄存器值用的,切換寄存器的時(shí)候由CPU自動(dòng)填寫。DWORD cr3; DWORD eip; DWORD eflags;DWORD eax;DWORD ecx;DWORD edx;DWORD ebx;DWORD esp;DWORD ebp;DWORD esi;DWORD edi;DWORD es;DWORD cs;DWORD ss;DWORD ds;DWORD fs;DWORD gs;DWORD ldt;// 這個(gè)暫時(shí)忽略DWORD io_map; } TSS;

TSS的工作細(xì)節(jié)

TSS在任務(wù)切換過(guò)程中起著重要作用。在任務(wù)切換的過(guò)程中,首先,處理器中的各寄存器的當(dāng)前值被自動(dòng)保存到TR(任務(wù)寄存器)所指定的TSS中;然后下一任務(wù)的TSS選擇子被裝入TR;最后,從TR所指定的TSS中取出各寄存器的值送到處理器的各寄存器中,從而實(shí)現(xiàn)任務(wù)切換。

中斷提權(quán)的任務(wù)切換過(guò)程

三環(huán)程序通過(guò)中斷門進(jìn)入到零環(huán)時(shí),首先會(huì)保存當(dāng)前的寄存器環(huán)境到TR所指定的TSS中,這一點(diǎn)我們已經(jīng)在中斷現(xiàn)場(chǎng)的堆棧環(huán)境中見(jiàn)過(guò)了。

然后將零環(huán)所需要的選擇子裝入TR。

最后從TSS中取出各寄存器送到當(dāng)前環(huán)境下。這其中就包括了ss段寄存器和棧頂指針。我們也可以從TSS的結(jié)構(gòu)體中看到0環(huán)的ss段寄存器和esp棧頂指針。

總結(jié):ss段寄存器和esp棧頂指針來(lái)自于TSS

實(shí)驗(yàn)代碼

最后 附上本次實(shí)驗(yàn)所用到的代碼

#include "pch.h" #include <iostream> #include <stdio.h> #include <stdlib.h> #include <windows.h>DWORD g_eax[2], g_ecx[2], g_edx[2], g_ebx[2]; DWORD g_esp[2], g_ebp[2], g_esi[2], g_edi[2]; WORD g_cs[2], g_ds[2], g_ss[2], g_es[2], g_fs[2], g_gs[2]; WORD g_tr;void __declspec(naked) IdtEntry() {__asm{mov [g_eax + 4], eax;mov [g_ecx + 4], ecx;mov [g_edx + 4], edx;mov [g_ebx + 4], ebx;mov [g_esp + 4], esp;mov [g_ebp + 4], ebp;mov [g_esi + 4], esi;mov [g_edi + 4], edi;push eax;mov ax, cs;mov [g_cs + 2], ax;mov ax, ds;mov[g_ds + 2], ax;mov ax, ss;mov[g_ss + 2], ax;mov ax, es;mov[g_es + 2], ax;mov ax, fs;mov[g_fs + 2], ax;mov ax, gs;mov[g_gs + 2], ax;str ax;mov g_tr, ax;pop eax;int 3;iretd;} }void go() {__asm{mov[g_eax], eax;mov[g_ecx], ecx;mov[g_edx], edx;mov[g_ebx], ebx;mov[g_esp], esp;mov[g_ebp], ebp;mov[g_esi], esi;mov[g_edi], edi;push eax;mov ax, cs;mov[g_cs], ax;mov ax, ds;mov[g_ds], ax;mov ax, ss;mov[g_ss], ax;mov ax, es;mov[g_es], ax;mov ax, fs;mov[g_fs], ax;mov ax, gs;mov[g_gs], ax;pop eax;}__asm int 0x20; }//eq 80b95500 0040ee00`00081040 int main() {if ((DWORD)IdtEntry != 0x401040){printf("wrong addr:%p", IdtEntry);exit(-1);}go();printf("eax:%p,\tecx:%p\tedx:%p\tebx:%p\n", g_eax[0], g_ecx[0], g_edx[0], g_ebx[0]);printf("esp:%p,\tebp:%p\tesi:%p\tedi:%p\n", g_esp[0], g_ebp[0], g_esi[0], g_edi[0]);printf("cs:%p,\tds:%p\tss:%p\tes:%p\tfs:%p\tgs:%p\n", g_cs[0], g_ds[0], g_ss[0], g_es[0], g_fs[0], g_gs[0]);printf("eax:%p,\tecx:%p\tedx:%p\tebx:%p\n", g_eax[1], g_ecx[1], g_edx[1], g_ebx[1]);printf("esp:%p,\tebp:%p\tesi:%p\tedi:%p\n", g_esp[1], g_ebp[1], g_esi[1], g_edi[1]);printf("cs:%p,\tds:%p\tss:%p\tes:%p\tfs:%p\tgs:%p\n", g_cs[1], g_ds[1], g_ss[1], g_es[1], g_fs[1], g_gs[1]);printf("tr:%p\n", g_tr);system("pause"); }

總結(jié)

以上是生活随笔為你收集整理的Windows内核实验002 中断现场的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。