當(dāng)我在說跳轉(zhuǎn)時(shí),說的什么?
CPU有很多指令,不是所有的指令都能夠隨時(shí)用,比如
ltr指令就不是隨便什么時(shí)候能用,在保護(hù)模式下,如果你不安規(guī)則來執(zhí)行指令,CPU就會(huì)拋出異常,比如你在INTEL手冊上就能看到如下文本
意思據(jù)是說,如果你當(dāng)前的CPL不是RING0,那么就會(huì)拋出GP(0)異常!
所以要正確使用這個(gè)指令,你就需要將CPL跳轉(zhuǎn)到RING0來。這就是跳轉(zhuǎn)!
RING3到RING0(用戶態(tài)到內(nèi)核態(tài))的特權(quán)轉(zhuǎn)變過程
首先得要有一個(gè)RING3的代碼段,并且該代碼段正處于運(yùn)行狀態(tài)
1.定義RING3代碼段
[SECTION .ring3]ALIGN 32[BITS 32]LABEL_CODE_RING3:
.
;此處省略RING3代碼段要做的事情
.
;最后一句轉(zhuǎn)移到ring0
2.必須為RING3代碼段定義描述符
LABEL_DESC_CODE_RING3: Descriptor 0, SegCodeRing3Len - 1, DA_C + DA_32 + DA_DPL3 ;DA_DPL3表明該代碼段特權(quán)等級(jí)是RING3
3.為RING3代碼段定義選擇子
SelectorCodeRing3 equ LABEL_DESC_CODE_RING3 - LABEL_GDT +SA_RPL3 ;SA_RPL3表明該選擇子的特權(quán)等級(jí)也是RING3
4.有了RING3的代碼段,描述符,選擇子,當(dāng)然應(yīng)該有RING0
[SECTION .ring0]ALIGN 32[BITS 32]LABEL_CODE_RING0:
.
;此處省略RING0代碼段要做的事情
LABEL_DESC_CODE_DEST: Descriptor 0, SegCodeDestLen - 1, DA_C + DA_32 ; 非一致代碼段 ,該段為RING0
SelectorCodeDest equ LABEL_DESC_CODE_DEST - LABEL_GDT ;RING0代碼段對(duì)應(yīng)的選擇子
到此準(zhǔn)備工作已經(jīng)做好(各級(jí)堆棧也需要準(zhǔn)備),要從RING3跳轉(zhuǎn)到RING0,通過這一篇文章,可以通過調(diào)用門實(shí)現(xiàn)從低級(jí)到高級(jí)的跳轉(zhuǎn),接下來定義調(diào)用門,和調(diào)用門的選擇子
調(diào)用門
LABEL_CALL_GATE_TEST: Gate SelectorCodeDest, 0, 0, DA_386CGate + DA_DPL3;
選擇子
SelectorCallGateTest equ LABEL_CALL_GATE_TEST - LABEL_GDT + SA_RPL3
調(diào)用門定義時(shí),需要用到RING0的選擇子。并且調(diào)用門和調(diào)用門選擇子的特權(quán)等級(jí)也都是RING3,加入調(diào)用門本身就定義為非RING3,那么在RING3代碼中執(zhí)行跳轉(zhuǎn)時(shí),就會(huì)報(bào)錯(cuò)。
現(xiàn)在來晚上RING3代碼段最后一句,跳轉(zhuǎn)到RING0
call SelectorCallGateTest:0 ;
準(zhǔn)備一大堆,一句話就跳轉(zhuǎn)了!RING3->RING0。從老幺一下權(quán)利躍升到老大!
新聞熱點(diǎn)
疑難解答
圖片精選