首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> VC >> 關於VC++

深度解析 Windows 2000 IDT 擴展機制:中斷鉤子與自訂中斷門實作

     編輯:關於VC++

中斷描述符表(IDT)是 x86 處理器處理中斷與異常的核心資料結構。本文深入剖析 Windows 2000 下的 IDT 架構,示範如何透過修改 IDT 實作軟體中斷鉤子(Hook int 0x2e 截獲系統服務呼叫)與新增自訂中斷門,並提供完整組合語言與 C 語言混合程式碼,為核心層級開發與逆向分析奠定基礎。

Windows 陷阱機制與 IDT 基礎

當硬體中斷、軟體中斷(int n)或異常發生時,處理器依 IDT 中對應的「門」描述符定位中斷服務例程(ISR)。IDT 最多支援 8192 個條目,每個 8 位元組,包含程式碼段選擇子、位移位址、類型(中斷門/陷阱門/任務門)與特權等級(DPL)。sidt 指令可讀取 IDTR 暫存器,取得 IDT 基址與界限,是所有 IDT 操作的起點。

中斷門描述符結構

typedef struct _idtentry {
    unsigned short OffsetLow;   // 位移低 16 位
    unsigned short Selector;    // 程式碼段選擇子
    unsigned char  Reserved;    // 保留,必為 0
    unsigned char  Type:4;      // 門類型:0xE=中斷門, 0xF=陷阱門
    unsigned char  SegmentFlag:1;
    unsigned char  DPL:2;       // 特權等級:0=核心, 3=使用者
    unsigned char  Present:1;   // 存在位
    unsigned short OffsetHigh;  // 位移高 16 位
} IDTENTRY, *PIDTENTRY;

實作軟體中斷鉤子(Hook int 0x2e)

  1. 執行 sidt 取得 IDT 基址。
  2. 定位 IDT[0x2e],備份原始 OffsetLow/OffsetHigh 至全域變數 OldISR。
  3. cli 關中斷,將 IDT[0x2e] 位移指向自訂 NewISR;sti 開中斷。
  4. NewISR 中保存現場、執行監控邏輯(如依 EAX 區分系統服務號)、還原現場、jmp OldISR 執行原系統服務。
  5. 卸載時將 OldISR 寫回 IDT。

核心程式碼

VOID HookInt(VOID) {
    IDTR idtr; PIDTENTRY IdtEntry;
    __asm sidt idtr;
    IdtEntry = (PIDTENTRY)idtr.IDTBase;
    OldISR = ((ULONG)IdtEntry[HOOKINTID].OffsetHigh << 16) | IdtEntry[HOOKINTID].OffsetLow;
    __asm cli;
    IdtEntry[HOOKINTID].OffsetLow  = (USHORT)NewISR;
    IdtEntry[HOOKINTID].OffsetHigh = (USHORT)((ULONG)NewISR >> 16);
    __asm sti;
}

VOID __fastcall Monitor() {
    __asm mov dwServiceId, eax;
    dwProcessId = (ULONG)PsGetCurrentProcessId();
    KeRaiseIrql(HIGH_LEVEL, &OldIrql);
    switch(dwServiceId) {
        case 0x23: DbgPrint("ProcessId: %d ZwCreateKey\n", dwProcessId); break;
        // ... 監控其他登錄表相關系統服務
    }
    KeLowerIrql(OldIrql);
}

新增自訂軟體中斷門(擴充系統服務)

IDT 中仍有未使用的條目(如 0xF0 以上)。將目標條目 Type=0xE、DPL=3(允許 Ring 3 呼叫)、Selector=8(核心程式碼段)、Present=1、位移指向自訂 ISR。使用者模式即可透過 int 0xF0 呼叫核心功能,實現系統服務擴充。

安裝與移除範例

NTSTATUS InstallIG() {
    // 檢查目標中斷門是否空閒
    if (IdtEntry[ADDINTID].OffsetLow || IdtEntry[ADDINTID].OffsetHigh)
        return STATUS_UNSUCCESSFUL;
    RtlCopyMemory(&OldIdtEntry, &IdtEntry[ADDINTID], sizeof(IDTENTRY));
    __asm cli;
    IdtEntry[ADDINTID].OffsetLow     = (USHORT)InterruptServiceRoutine;
    IdtEntry[ADDINTID].Selector      = 8;
    IdtEntry[ADDINTID].Type          = 0xE;
    IdtEntry[ADDINTID].DPL           = 3;
    IdtEntry[ADDINTID].Present       = 1;
    IdtEntry[ADDINTID].OffsetHigh    = (USHORT)((ULONG)InterruptServiceRoutine >> 16);
    __asm sti;
    return STATUS_SUCCESS;
}

void _cdecl InterruptServiceRoutine() {
    __asm mov Command, eax;  // 取得使用者傳入參數
    DbgPrint("NtBuildNumber == %d\n", (USHORT)NtBuildNumber);
    __asm iretd;
}

實務應用與注意事項

  • 鍵盤記錄器:掛鉤鍵盤硬體中斷(需配合 IoConnectInterrupt)。
  • 核心後門:新增中斷門提供 SYSTEM 權限指令執行。
  • Windows XP/2003 採用 sysenter 取代 int 0x2e,本文技術於新版 Windows 失效。
  • 修改 IDT 需極度謹慎,錯誤會導致系統即時崩潰(藍畫面)。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved