熱點推薦:
您现在的位置: 電腦知識網 >> 操作系統 >> Windows優化 >> 正文

解析Windows2000的IDT擴展機制

2022-06-13   來源: Windows優化 

  > Windows陷阱機制簡介
  
   陷阱(Trap)是Windows系統中一種不可缺少的系統機制當系統中發生中斷(硬件中斷或軟件中斷)異常時處理器會捕捉這個動作並將系統的控制轉移到一個固定的處理程序處進行相應的操作處理在處理器開始處理發生的中斷或異常前必須保存一些處理器環境參數到堆棧中以備系統還原時使用系統是通過一種稱為陷阱幀(Trap Frame)的方式來實現的它將系統中全部線程的環境數據保存到內核堆棧(Kernel Stack)中在執行完後通過堆棧的出棧機制來恢復系統控制流程中的執行點內核中的陷阱機制分為中斷和異常中斷是系統中隨即發生的異步事件與當前系統的處理器狀態無關同時系統中的中斷可分為可屏蔽中斷和不可屏蔽中斷而異常則是一種同步事件在特定情況下異常可以重現而中斷不可以中斷又可以分為硬件中斷和軟件中斷很明顯硬件中斷是與硬件相關的比如I/O設備執行的某些操作處理器時鐘或硬件端口上的處理等軟件中斷則是通過中斷指令int xx引入的它往往是應用程序在用戶模式執行後進入操作系統的代碼這時系統為用戶提供了各種各樣的系統服務比如我們上次提到的系統服務調用(System Service Call)在Windows NT/下就是通過軟件中斷int xe(System Service Interrupt)來實現的雖然在Windows XP/下微軟使用了一種稱為快速系統調用接口來為用戶提供系統服務不過大量的中斷服務仍然存在與系統之中的
  
  > 中斷處理及其相關流程
  
   此處我們討論的是與特定處理器相關的數據結構所以會有一些移植方面的問題本文僅針對Intel的x Family處理器並且本文附帶的程序也只支持在Intel x處理器上正常執行何為IDT?IDT(Interrupt Descriptor Table)稱為中斷描述符表它是可容納個單元的數組數組中的每個成員是稱之為的長度為字節的段描述符在IDT中門可分為三種中斷門(Interrrupt Gate)陷阱門(Trap Gate)和任務門(Task Gate)但主要的是中斷門和陷阱門而它們兩者之間也只有少許差別我們在此只關心IDT中的中斷門如果您對這方面比較感興趣請查閱Intel處理器的相關文檔《Intel Architecture Software Developers ManualVolume 同時在系統中存在一個中斷描述符表寄存器(IDTR)它包含了系統中斷描述符表的基地址和IDT的限制信息它於一條匯編指令sidt息息相關在下文中我們將看到它是我們實現各種中斷描述符表擴展的基礎和關鍵!還有一點是需要注意的在Windows系統中引入了分頁分段和虛擬存儲機制後就存在這一種調度機制將需要執行的代碼和數據調入內存將不需要的數據調到外存(輔助存儲器如硬盤等)如果我們在執行某些代碼時發現了我們需要的數據不在內存中時就會發出一個缺頁中斷這時系統就會在IDT中搜尋這個中斷的ISR(Interrupt Service Routine中斷服務例程)執行相應的調入工作大家可以想象如果我們的中斷描述符表被調出到外存後會是什麼樣的結果?那時系統將無法定位缺頁中斷的服務例程至此系統將會崩潰掉!
  
   在中斷描述符表中我們剛才提到了一個感興趣的寄存器IDTR當然我們更關心對我們來說更直接的數據IDT中的代碼段選擇器(Code Segment Selector)中斷執行代碼的偏移量(Offset)和中斷描述符的權限等級(Descriptor Privilege Level)參數下面我們看看中斷指令的執行流程我們應該知道應用程序執行在用戶模式(Ring )下而中斷描述符表則是存在於內核模式(Ring )才可以訪問的系統地址空間內的在軟件中斷發生後也就是應用程序調用了某條軟件中斷指令後處理器首先在IDT中檢索傳入的中斷號參數找到響應的入口單元後就檢查中斷門的權限等級參數看是否允許Ring 下的應用程序調用這樣操作系統就為我們保留了對軟件中斷調用控制的權力然而硬件中斷和異常是不會關注權限方面的信息如果當前權限等級(Current Privilge LevelCPL)數值大於中斷門描述符需要的權限(Descriptor Privilege Level)也就是權限不夠時會引發一個通用保護故障(General Protection Fault)反之則進行處理器的切換從用戶堆棧到內核堆棧現在是保存線程環境的時候了處理器將在用戶模式下的堆棧指針(SS:ESP)和標准的中斷幀(EFLAGS和CS:EIP)壓入堆棧之後處理器進入我們的中斷服務例程執行相關的代碼處理後通過匯編指令iretd返回到調用的應用程序在指令iretd執行時系統將存儲在堆棧中的線程環境數據出棧還原待系統恢復中斷指令執行前的環境後就接著執行應用程序的後續代碼
  
  > 中斷相關數據結構
  
   首先我們介紹一下前面我們提到的一條關鍵匯編指令sidt的相關數據結構在執行指令sidt後系統將會把中斷描述符表的基地址和限制(總共長六字節)保存在指令中指向的變量指針中這就是我們進行IDT操作的入門口
  
  typedef struct _idtr
  {
   //定義中斷描述符表的限制長度兩字節
   short IDTLimit;
   //定義中斷描述服表的基址長度四字節
   unsigned int IDTBase;
  }IDTR*PIDTR;
  
   當我們獲得了IDT的入口後就會在中斷描述符表中檢索我們需要處理的中斷號對應的IDT單元單元中包含了很多我們需要注意的數據結構其中我們最為關心的是代碼段選擇器中斷代碼執行的偏移量和特權等級等那好我們先給出它的定義在下文中我們將詳細討論它們的具體應用
  
  typedef struct _idtentry
  {
   //中斷執行代碼偏移量的底
   unsigned short OffsetLow;
   //選擇器也就是寄存器
   unsigned short Selector;
   //保留位始終為零
   unsigned char Reserved;
   //IDT中的門的類型包括中斷門陷阱門和任務門
   unsigned char Type:;
   //段標識位
   unsigned char SegmentFlag:;
   //中斷門的權限等級表示內核級表示用戶級
   unsigned char DPL:;
   //呈現標志位
   unsigned char Present:;
   //中斷執行代碼偏移量的高
   unsigned short OffsetHigh;
  }IDTENTRY*PIDTENTRY;
  
  > 創建軟件中斷鉤子的作用
  
   作為普通的Windows程序員或許您需要的是熟悉對系統基本功能的操作以及對通用程序開發的熟練掌握但對於一個有想法的Windows內核級分析開發人員來說對系統底層的深入了解是非常必要的同時也是非常重要的Hook為我們創造了一個絕好的機會它使我們了解系統內部運行機制的想法成為了一種可能同時書寫一個系統相關的監視程序可以自動的對系統內部操作進行記錄與分析當然我們不能局限於對系統的了解我們更渴望實施對系統的修改與擴展改變系統原有的操作特性注入我們需要的功能組件讓系統做更適合我們自己也是我們最希望看到的操作前面我們曾經談到了創建系統服務調用的鉤子來截獲系統服務調用同樣在Windows系統服務是通過系統服務中斷(System Service Interruptint xe)來實現的通過截獲軟件中斷同樣可以達到監視並修改系統服務調用的功能在此我們主要討論的是為軟件中斷創建鉤子不過對於硬件中斷和異常也同樣不例外我們同樣可以將本文提到的方法應用於硬件中斷和異常比如我們也可以通過截獲鍵盤驅動的中斷調用來書寫內核級的鍵盤記錄器它可以直接對每次擊鍵和釋放進行操作效果是非常的明顯不過這還需要使用到一些微軟為我們提供的與硬件中斷鉤子相關的函數
  
  > 如何創建軟件中斷鉤子?
  
   其實創建軟件中斷鉤子的過程應該是比較明顯了下面我們將先簡要介紹一下創建Hook的過程然後以實際代碼進行具體的講解首先我們通過匯編指令sidt(sidt: Store Interrupt Descriptor Table Registerlidt: Load Interrupt Descriptor Table Register)來獲取IDT的基地址IDTBase然後我們在中斷描述符表中搜尋我們需要HOOK的中斷號HOOKINTID它應該是在內的一個整數雖然最新的Intel處理器聲稱支持個中斷描述符單元但由於某些限制原因仍然只能處理前個中斷描述門在找到我們需要Hook的中斷描述門後將它原本的中斷執行代碼偏移量(位)保存到一個全局變量OldISR中以備我們在執行中斷處理或恢復IDT時使用這樣新的IDT中對應中斷號的執行代碼偏移量就指向了我們自己的處理代碼了在我們的處理代碼NewISR中注意先要保存一些線程環境在處理完我們額外添加的執行程序(Monitor監視注冊表相關的個系統服務調用)後恢復現場並執行中斷門以前指向的程序代碼這樣對外就看不出我們對中斷門做了什麼額外的處理感覺和以前沒什麼兩樣!如果我們只是處理了我們添加的代碼而沒有繼續執行中斷門對應的以前的程序代碼那麼系統必將混亂甚至崩潰!同樣在我們卸載我們的軟件中斷鉤子時就是進行了一個逆向工作先獲取IDT的基地址然後將保存在全局變量中的舊的執行代碼地址偏移量賦給對應中斷號的偏移量單元(OffsetLow/OffsetHigh)大概過程講得差不多了相關程序為THookInt我們再看看代碼吧!
  
  VOID
  HookInt(VOID)
  {
   //保存IDT入口的基地址和限制信息的數據結構
   IDTR idtr;
   //記錄IDT數組的指針通過它可以查找到我們需要Hook中斷號對應的中斷門
   PIDTENTRY IdtEntry;
  
   //匯編指令sidt獲取IDT入口信息
   __asm sidt idtr;
  
   //賦予IDT基地址值
   IdtEntry = (PIDTENTRY)idtrIDTBase;
  
   //保存中斷號HOOKINTID對應
From:http://tw.wingwit.com/Article/os/youhua/201311/10802.html
    推薦文章
    Copyright © 2005-2022 電腦知識網 Computer Knowledge   All rights reserved.