保護模式驗證段暫存器的屬性

2021-10-10 01:16:51 字數 3467 閱讀 1995

保護模式第一篇段暫存器,學習過8086彙編的同學應該知道段暫存器在8086種的重要程度,8086cpu的暫存器都是16位,8086cpu能夠以16位的位址匯流排訪問到1mb的記憶體位址,採用的就是段位址*16+偏移位址=實體地址的方式,以16位位址匯流排訪問1mb的物理記憶體,8086時代訪問的位址都是實體地址沒有虛擬位址的概念,程序訪問的都是實體地址,如果不小心改了系統資料這是非常的危險的,本人在保護模式下編寫驅動都沒少藍過,實在不敢想象如果應用程式能直接訪問作業系統,得讓作業系統崩潰多少次,實在不安全,於是隨著時代的發在實模式退出了舞台(當然計算機剛上電進入的是實模式然後跳轉到保護模式的),來到了保護模式的時代,首先需要理解的是保護模式保護的是什麼

剛接觸程式設計的時候老師們就沒少給我們灌輸,計算機所有能操作的東西都必須載入到記憶體中才能夠處理資料,可見記憶體有多麼重要,理所當然保護模式就是保護的記憶體資源,從實模式到保護模式,由單任務->到多工,有直接訪問的實體地址->到抽象到虛擬位址(每個程序有4gb的虛擬位址,低2gb不同,高2gb是作業系統核心所有程序通用的),我們應用程式能有許可權訪問的只有低2gb,高2gb執行著作業系統的核心應用程式沒有許可權訪問,保護模式保護的是記憶體,它是通過段機制,和頁機制的雙層保護機制(後面會講到cpu是如果通過段機制和頁機制實現對記憶體的保護)

通過上面的科普讓大家了解了一點實模式和保護模式的知識,也來到今天的課題段暫存器32位windows系統下使用的暫存器都是32位,段暫存器有cs  es  ds  ss  fs  gs等,我們在使用dtbug等除錯工具看到的這些暫存器都是16位的,而這16位只是段暫存器的可見部分(稱為段選子),還有80位是不可見的但卻實際存在的,總共分為四部分

struct  segment{

shrot       select;                                     //16位的段選擇子

shrot       atrribute;                                 //16位的段屬性    決定了這個段是可讀,可寫,還是可執行

int           base;                                      //段的開始

int           limit;                                      //段的限長          從開始到結束就是段的限長可以訪問的地方

段cs  es  ds  ss  fs  gs

在3環可以看到windows  xp系統可以看到

cs的段選擇子為0x1b          base=0x00000000             limit=0xffffffff           cs段的屬性為可讀,可執行(稍後證明)

es=ss=ds=0x23               base=0x00000000             limit=0xffffffff           這些資料段的屬性為可讀可寫(稍後證明)

fs的段選擇子為0x3b          base=0x7ffdf000            limit=0xfff                      屬性為可讀可寫

作業系統有兩種表非常的重要gdt(全域性描述符表)idt(中斷描述符表)

這些段寄存會根據段選擇子,從gdt表中載入段描述符(顧名思義就描述載入段的屬性 訪問屬性,base,limit)

載入的時機就是當段寄存的選擇子發生(也就是可見部分)改變的時候比如:mov ds,ax  執行這行**後,ds段選擇子發生賦值

就會從gdt表中載入段描述符(需要新的屬性描述這個段了)

可以看到下面這張,   mov  ax,ss  mov  ds,ax  把ss的段選擇值,給了ds 在執行為mov   ds,ax後 cpu需要從gdt表中

根據段選擇子載入對應的段描述符,用於描述ds段的屬性,這裡ds和ss的選擇值本來就是相同的都是0x23  段的屬性也都相同可讀可寫,段的開始和結束也都一樣,得到的結構也完全沒有問題

cs的選擇子是0x1b   base=0,limit=0xffffffff和ds相同的,但是cs段的屬性是可讀可執行,ds段的屬性是可讀可寫,

可以看到執行了mov  ds,ax  ds=0x1b後  cpu會從gdt表中載入對應的段描述符(用於描述ds段的屬性),載入完成後ds段訪問許可權和cs段一樣了可讀,可執行當執行mov  ds:[taolaoda],1000就掛了  0xc0000005訪問異常 沒有寫的許可權

fs段寄存的選擇子位0x3b  base=0x7ffdf000(以自己電腦的為準)   limit=0xfff把0x3b賦值給es後,cpu從gdt表中根據段選擇子載入段屬性,base,limit 此時 es段的base=0x7ffdf000,所有  mov  edi,dword ptr es:[0]這行**訪問的是 es.base+0這個記憶體位址,這才是本質,平常es=ds=ss的base=0所以  裡面的位址就是實際的虛擬位址   0+中的位址

es段暫存器賦值了fs的選擇子,當cpu從gdt表中記載完成後,base=0x7ffdf000,limit=0xfff所以es段的範圍只有

base到base+limit之間,這明顯越界了,所以過不了段的檢測

就是這麼簡單,有人肯定會有疑問2gb以上的記憶體空間訪問會出問題是因為沒道理?難道因為搞2gb是核心空間所有不能訪問,

應用程式確實不能訪問高2gb,但不是因為高2gb是核心,ds,es,ss的base=0,limit=0xffffffff,這說明核心也在他們訪問範圍之內,可以過段的檢查,但是別忘了保護模式是有段和頁機制一起實現,過來段的檢查過不了頁的檢查啊,

gs暫存器windows並沒有使用到,我們可以自己使用,需要注意的是gs暫存器幾乎進核心就會把清0(後面的帖子到逆向windows的執行緒切換**swapcontext中可以找到這條清0的反彙編**),這是初學核心需要注意的地方,下斷點除錯的時候如果實現了gs單步的時候可能會掛,讓程式直接執行就可以了。

我們上面寫段暫存器的時候只寫入了16位,剩下的80位填充什麼,從**來的?答案是根據寫入的段選擇子,cpu從gdt表中對應位置的段描述符中載入而來的,本期見這裡了,後面還會帶來,cpu如果從gdt表中記載段描述到段暫存器,和各種保護模式的只是,頁的只是,應用程式到系統呼叫如何從ring3進入ring0,程序執行緒的只是,windows執行緒切換的逆向,apc機制等等

保護模式1 段暫存器 基本屬性

段暫存器是什麼?segment register 也可以稱作 selector register 當我們用彙編讀寫某個位址時 mov dword ptr ds 0x00401000 eax 我們讀寫的位址其實是ds.base 0x00401000 0x00401000被稱為讀寫的有效位址 ds.ba...

保護模式 2講 段 段暫存器結構

目錄保護模式,主要學習的就是段 與 頁 的關係.學習段的時候先學習段暫存器 所以先從段開始學.先看一段彙編 如下 mov eax,fs 0 mov eax,fs eax 0x30 上面的 學過 teb peb 結構的人應該知道.是在做什麼.而我麼你這裡所說不講 peb teb 看彙編 我們操作了fs...

段暫存器屬性的探測

在之前段暫存器隨筆中說了一下段暫存器是用來保護記憶體中的資料不被隨意訪問 當然還有頁 那如何限制你的呢 首先要了解段暫存器的結構 段暫存器的結構長度是96位,可以顯示的只是16位的selecter 段選擇子 剩餘部分不可見,但是可以探測到的 在段暫存器中有個attribute屬性,它會限制你能不能寫...