(8)JMP FAR段间跳转
一、回顧
在前面的課程中我們學習了MOV和LES等修改段寄存器的指令,當時老師說過,CS寄存器比較特殊,不能用MOV和"LCS"進行修改,原因是CS和EIP共同決定下一條指令的地址,要修改CS,就必須同時修改EIP,這也是Intel沒有提供"LCS"指令的原因。
二、JMP FAR 執行流程
JMP 0x20:0x004183D7
上面是一條 JMP FAR 指令,CPU執行該指令分為以下5步:
(1)拆分段選擇子
0x20 = 00100 0 00
RPL = 0
TI = 0
INDEX = 4
(2)查GDT表得到段描述符
根據段選擇子拆得的下標,找到GDT表第5項。如果P=1,S=1,TYPE高1位=1,則表明這是一個代碼段,就可以進行下一步。
(3)權限檢查
TYPE域高2位是C屬性,C=0表示非一致代碼段,C=1表示一致代碼段。
如果是非一致代碼段,要求:CPL == DPL 并且 RPL <= DPL;
如果是一致代碼段,要求:CPL >= DPL。
(4)加載段描述符
通過上面的權限檢查后,CPU會將段描述符加載到CS段寄存器中。
(5)執行代碼
CPU將 CS.Base + Offset 的值寫入EIP 然后執行CS:EIP處的代碼,段間跳轉結束。
三、練習
非一致代碼段:
要求:CPL == DPL 并且 RPL <= DPL
所以,我們需要尋找P=1,DPL=11,S=1,TYPE=10??的段。
解釋:我們的程序在3環,CPL=3,根據要求,DPL也一定要是3,P=1段才有效,S=1,TYPE高1位是1才是代碼段,TYPE高2位是0才是非一致代碼段。
觀察GDT,可以發現,滿足條件只有第四個,已用紅色箭頭標出:
RPL可以取00或11,TI=0,INDEX=00011,所以段選擇子可以取0x18或0x1B.
打開OD,觀察CS,此時CS=0x1B,為了看到CS的變化,我們取段選擇子為0x18.
觀察段描述符,BASE=0,LIMIT=FFFFFFFF,所以Offset可以任取,為了方便觀察,我們就取EIP后面不遠處的一條指令來測試。
將EIP處指令修改為 JMP FAR 0018:0046FEAD,觀察執行前后EIP和CS的變化。
和預期有出入,EIP確實修改成功了,但是CS并沒有變成0x18,我用原版OD,DTdebug和x64dbg測試過,結果都是一樣的,CS沒變。
這里我說一下我的分析:可能OD認為CS寄存器指向的段沒有改變(1B和18的區別是RPL,但是在GDT里是同一個地方),所以就沒更新?
OD這個特性導致我們沒辦法觀察CS的變化,為了解決這個問題,可以把 00cffb00`0000ffff 復制一份到別處。
在windbg中使用eq命令可以拷貝數據
此時,8003f048 標記了一個段,它的值和8003f018完全相同,區別是在GDT表的位置不同。
然后我們修改段選擇子為01001 0 00 或 01001 0 11,比如取前者0x48,再次執行指令,觀察EIP和CS變化:
這次可以看到,EIP和CS都被修改了。但是還是和預想有出入,CS并沒有和預想一樣改成48,而是改成了4B。并且后面的32bit變成了16bit,我無法解釋這些現象。觀察得到的結論就是,OD或操作系統會將RPL=00的段選擇子改為11.
2020年11月2日21:53:12 補充:
查閱Intel開發手冊,有如下一段話:
Current privilege level (CPL) — The CPL is the privilege level of the currently executing program or task. It
is stored in bits 0 and 1 of the CS and SS segment registers. Normally, the CPL is equal to the privilege level of
the code segment from which instructions are being fetched. The processor changes the CPL when program
control is transferred to a code segment with a different privilege level. The CPL is treated slightly differently
when accessing conforming code segments. Conforming code segments can be accessed from any privilege
level that is equal to or numerically greater (less privileged) than the DPL of the conforming code segment.
Also, the CPL is not changed when the processor accesses a conforming code segment that has a different
privilege level than the CPL.
說得很清楚了,CS, SS低2位是當前CPL,因為JMP FAR之后還是在3環,所以CS低2位當然是11了。這不是你RPL能決定的。
接下來,我們把DPL改成0,再次測試
kd> eq 8003f048 00cf9b00`0000ffff kd> g此時CPL!=RPL,執行指令會跳到異常處理。
一致代碼段:
一致代碼段可以讓用戶態訪問內核態(CPL=3時訪問0環代碼),一致代碼段又叫共享段。如果有些內核代碼不會對內核造成破壞的,希望用戶態程序直接訪問的,就可以設置成一致代碼段。WINDOWS XP中沒有使用一致代碼段,所以這個實驗我們要自己構造一致代碼段。
要求:CPL >= DPL
直接修改 8003f048,將其改為DPL=0的一致代碼段,然后我們在3環訪問它。
執行 JMP FAR 004B:0046FEAD 指令,觀察結果。
結果和預期一致,低權限程序跳轉到高權限代碼段成功了。
總結
以上是生活随笔為你收集整理的(8)JMP FAR段间跳转的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: (7)数据段权限检查
- 下一篇: (9)跨段跳转,短调用和长调用堆栈图