天天看點

Windows 核心Hook之IOAPIC程式設計Windows 核心Hook之IOAPIC程式設計

HOOK系列中,包括應用程式HOOK程式設計、IDT和IOAPIC程式設計,其中IOPIC顧名思義I/O ADVANCED PROGRAMMABLE INTERRUPT CONTROLLER中斷控制器。在Windows 中有固定的兩個位址進行操作,第一、I/O寄存器選擇寄存器,其位址是0xfec00000;另一個是I/O視窗寄存器,位址是0xfec00010。這兩個位址不像通用寄存器一樣能直接通路,必須映射大一片虛拟記憶體中操作。

IDT是中斷描述符清單,IOAPIC的目的就是告訴指定的CPU的IRQ号,用于IDT查詢中斷服務位址。

是以如果想修改中斷的處理過程,首先需要修改IOAPIC的中斷号,在通過IDT修改中斷服務函數,這樣就可以達到過濾和擷取資料的目的,如下代碼;

// 選擇寄存器。選擇寄存器雖然是32位的寄存器,但是隻使用

         // 低8位,其他的位都被保留。

         P2C_U8 *io_reg_sel;

         // 視窗寄存器,用來讀寫被選擇寄存器選擇的值,是32位的。

         P2C_U32 *io_win;

         P2C_U32 ch,ch1;

         // 定義一個實體位址,這個位址為0xfec00000。正是IOAPIC

         // 寄存器組在Windows上的開始位址

         PHYSICAL_ADDRESS      phys ;

         PVOID paddr;

         RtlZeroMemory(&phys,sizeof(PHYSICAL_ADDRESS));

         phys.u.LowPart = 0xfec00000;

         // 實體位址是不能直接讀寫的。MmMapIoSpace把實體位址映射

         // 為系統空間的虛拟位址。0x14是這片空間的長度。

         paddr = MmMapIoSpace(phys, 0x14, MmNonCached);

         // 如果映射失敗了就傳回0.

         if (!MmIsAddressValid(paddr))

                   return 0;

         // 選擇寄存器的偏移為0

         io_reg_sel = (P2C_U8 *)paddr;

         // 視窗寄存器的偏移為0x10.

         io_win = (P2C_U32 *)((P2C_U8 *)(paddr) + 0x10);

         // 選擇第0x12,剛好是irq1的項

         *io_reg_sel = 0x12;

         ch = *io_win;

         // 如果new_ch不為0,我們就設定新值。并傳回舊值。

         if(new_ch != 0)

         {

                   ch1 = *io_win;

                   ch1 &= 0xffffff00;

                   ch1 |= (P2C_U32)new_ch;

                   *io_win = ch1;

                   KdPrint(("p2cSeachOrSetIrq1: set %2x to irq1./r/n",(P2C_U8)new_ch));

         }

         // 視窗寄存器裡讀出的值是32位的,但是我們隻需要

         // 一個位元組就可以了。這個位元組就是中斷向量的值。

         // 一會我們要修改這個值。

         ch &= 0xff;

         MmUnmapIoSpace(paddr, 0x14);

         KdPrint(("p2cSeachOrSetIrq1: the old vec of irq1 is %2x./r/n",(P2C_U8)ch));

         return (P2C_U8)ch;

繼續閱讀