Windows 内核Hook之IOAPIC编程

Windows 内核HookIOAPIC编程

HOOK系列中,包括应用程序HOOK编程、IDTIOAPIC编程,其中IOPIC顾名思义I/O ADVANCED PROGRAMMABLE INTERRUPT CONTROLLER中断控制器。在Windows 中有固定的两个地址进行操作,第一、I/O寄存器选择寄存器,其地址是0xfec00000;另一个是I/O窗口寄存器,地址是0xfec00010。这两个地址不像通用寄存器一样能直接访问,必须映射大一片虚拟内存中操作。

IDT是中断描述符列表,IOAPIC的目的就是告诉指定的CPUIRQ号,用于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;

你可能感兴趣的:(windows)