1 段寄存器 1 1 段寄存器的結構 圖示: 結構體表示: 1 2 段寄存器的屬性探測 可以通過MOV指令進行讀寫(LDTR和TR除外) 段寄存器成員簡介 探測Attribute是否存在 探測Base是否存在 探測Limit是否存在 1 3 段描述符與段選擇子 段寄存器的值是通過段描述符填充的。 1 ...
1 段寄存器
1-1 段寄存器的結構
圖示:
結構體表示:
struct SegMent
{
WORD Selector;
WORD Attribute;
DWORD Base;
DWORD Limit;
}
1-2 段寄存器的屬性探測
可以通過MOV指令進行讀寫(LDTR和TR除外)
段寄存器成員簡介
探測Attribute是否存在
int var=0;
int main()
{
__asm
{
mov ax, ss //cs不行 cs是可讀 可執行 但不可寫
mov ds, ax
mov dword ptr ds:[var], eax
}
}
探測Base是否存在
int var=0;
int main()
{
__asm
{
mov ax, fs
mov gs, ax
mov eax, gs:[0] //不要用DS否則編譯不過去 //fs.base+0是真正訪問的
//相當於
//mov edx, dword ptr ds:[0x7FFDE000] //這個地址是可以訪問的
mov dword ptr ds:[var], eax
}
}
探測Limit是否存在
int var=0;
int main()
{
__asm
{
mov ax, fs
mov gs, ax
mov eax, gs:[0x1000] //0x7FFDF000+0x1000,1000超過了0xFFF
//訪問的地址相當於下麵的 但DS的Limit是0xFFFFFFFF
mov edx, dword ptr ds:[0x7FFDF000+0x1000]
mov dword ptr ds:[var], eax
}
}
1-3 段描述符與段選擇子
段寄存器的值是通過段描述符填充的。
1-3-1 GDT(全局描述符表) LDT(局部描述符表)
當我們執行類似MOV DS, AX
指令時,CPU會查表,根據AX的值來決定查找GDT還是LDT,查找表的什麼位置,查出多少數據
1-3-2 段選擇子
段選擇子是一個16位的段描述符,該描述符指向了定義該段的段描述符.
1-3-3 載入段描述符至段寄存器
除了MOV指令,我們還可以使用LES、LSS、LDS、LFS、LGS指令修改寄存器.
CS不能通過上述的指令進行修改,CS為代碼段,CS的改變會導致EIP的改變,要改CS,必須要保證CS與EIP一起改,後面會講
char buffer[6];
__asm
{
les ecx, fword ptr ds:[buffer] //高2位元組給es,低四位元組給ecx
}
註意:RPL<=DPL(在數值上)
1-4 段描述符屬性_P位_G位_S位_TYPE域
1-4-1 P位
P = 1 段描述符有效
P = 0 段描述符無效
1-4-2 段描述符與段寄存器的對應關係
1-4-3 G位
重點在於Limit結構。
當G = 0 時,Limit是0x000XXXXX
當G = 1 時,Limit是0xFFFXXXXX -- 這裡存疑
1-4-4 S位
小結:先判斷P位,再判斷S位是0/1(確定是數據段/代碼段或者是系統段的)
DPL只能出現兩種情況,或0或1
1-4-5 TYPE域
S = 1 代碼段或數據段的描述符
S = 0 系統段的描述符
** 數據段說明:
A 訪問位,表示該位最後一次被操作系統清理後,該段是否被訪問過,每當處理器將該段選擇符置入某個段寄存器時,就將該位置1.
W 是否可寫
E 擴展方向
代碼段說明:**
A 訪問位
R 可讀位
C 一致位 { C = 1 一致代碼段; C = 0 非一致代碼段}
1-4-6 DB位
情況一:對CS段的影響
D = 1採用32位定址方式
D = 0採用16位定址方式
首碼67 改變定址方式
情況二:對SS段的影響
D = 1 隱式堆棧訪問指令(如:PUSH POP CALL)使用32位堆棧指令寄存器ESP
D = 0 隱式堆棧訪問指令(如:PUSH POP CALL)使用16位堆棧指令寄存器SP
情況三:向下擴展的數據段
D = 1 段上線為4GB
D = 0 段上線為64KB
1-5 段許可權檢查
1-5-1 CPU分級
1-5-2 如何查看程式處於第幾環?
CS寄存器的段選擇子(共16bit)的後兩個bit,表示的是CPL(Current Privilege Level):CPU當前特權等級
CS和SS中存儲的段選擇子後2個bit
1-5-3 DPL(Descriptor Privilege Level) 描述符特權等級
DPL存儲在段描述符中,規定了訪問該段所需要的特權級別是什麼
舉例說明:
如果AX指向的段DPL = 0 但當前程式的CPL = 3 這行指令是不會成功的
1-5-4 RPL(Request Privilege Level) 請求特權等級
舉例說明:
mov ax, 0008 與 mov ax, 000B //段選擇子
mov ds, ax //將段描述指向的是同一個段描述符,但RPL是不一樣的
1-5-5 數據段的許可權檢查
參考如下代碼:
比如當前程式處於0環, 也就是說CPL=0
mov ax, 000B //1011 RPL=3
mov ds, ax //ax指向的段描述符的DPL=0
數據段的許可權檢查:
CPL <= DPL 並且 RPL <= DPL(數值上的比較)
註意:
代碼段和系統段描述符中的檢查方式並不一樣,具體參見後面內容...
1-5-6 總結:
CPL CPU當前的許可權級別
DPL 如果你想訪問我,你應該具備什麼樣的許可權
RPL 用什麼許可權去訪問一個段
為啥要有RPL?
我們本可以用“讀、寫”的許可權去打開一個文件,但為了避免出錯,有些時候我們使用“只讀”的許可權去打開。