IDT

来源:互联网 发布:知微传播分析 编辑:程序博客网 时间:2024/05/22 21:54

中断描述符表寄存器(Interrupt Descriptor Table Register, IDTR)
中断描述符表(Interrupt Descriptor Table, IDT)

中断描述符表寄存器(Interrupt Descriptor Table Register, IDTR)存储了中断描述符表(Interrupt Descriptor Table, IDT)在内存中的基地址.

IDT是一个有256个入口的线形表,每个IDT的入口是个8字节的描述符,所以整个IDT表的大小为256*8=2048 bytes.

每个中断向量关联了一个中断处理过程。所谓的中断向量就是把每个中断或者异常用一个0-255的数字识别。

另外, 每个处理器拥有自己的IDTR寄存器, 所以都拥有自己的中断表, 因此, 在Hook IDT的时候, 要考虑这个问题.

我们可以使用KeGetCurrentProcessorNumber之类的函数来判断代码当前在哪个处理器上运行. 也可以使用KeSetTargetProcessorDpc等函数将代码调度到某个特定处理器上运行.

当中断发生时, 可以从中断指令或可编程中断控制器中获取中断编号, 然后通过IDT寻找要调用的中断服务例程.

IDT有三种不同的描述符或者说是入口,分别是:

  1. 任务门描述符
  2. 中断门描述符
  3. 陷阱门描述符

    其中, 陷阱门和中断门非常相似, 他们区别只在于陷阱门能够被可屏蔽中断所中断, 而中断门不能. 另一方面, 任务门是一个非常过时的处理器特性, 它可以用于强制x86处理器的任务切换. 然而, Windows并不使用该特性, 所以我们也不加过多的研究.

为了获得IDT的内存地址, 必须读取IDTR, 这可以用SIDT指令完成. 当然, 我们也可以用LIDT指令来修改IDTR的内容.

SIDT指令以如下格式存储IDTR的内容:

typedef struct  {      unsigned short IDTLimit; //代表IDT的大小, 为7FFH      unsigned short LowIDTbase;      unsigned short HiIDTbase;  }IDTINFO;  

其中的LowIDTbase和HiIDTbase分别指示了IDT地址的低半部分和高半部分.

IDT中每项的结构如下:

#pragma pack(1)  typedef struct  {      unsigned short LowOffset;      unsigned short selector;      unsigned char unused_lo;      unsigned char segment_type:4;       unsigned char system_segment_flag:1;      unsigned char DPL:2;      unsigned char P:1;      unsigned short HiOffect;  }IDTENTRY;  #pragma pack()  

下面是一个小程序, 用来打印全部的ISR Interrupt Service Routines(中断服务程序)

#include <ntddk.h>  #include <stdio.h>  typedef struct  {      unsigned short IDTLimit; //代表IDT的大小, 为7FFH      unsigned short LowIDTbase;      unsigned short HiIDTbase;  }IDTINFO;  #pragma pack(1)  typedef struct  {      unsigned short LowOffset;      unsigned short selector;      unsigned char unused_lo;      unsigned char segment_type:4;       unsigned char system_segment_flag:1;      unsigned char DPL:2;      unsigned char P:1;      unsigned short HiOffect;  }IDTENTRY;  #pragma pack()  #define MAKELONG(a, b) \      ((unsigned long) (((unsigned short) (a)) | ((unsigned long) ((unsigned short) (b))) << 16))   //IDT中的最大项数是256  #define MAX_IDT_ENTRIES 0xFF  VOID  DriverUnload(IN PDRIVER_OBJECT pDriverObj)  {          KdPrint(("[IDT] Unloading...\r\n"));      }  NTSTATUS  DriverEntry(IN PDRIVER_OBJECT pDriverObj, IN PUNICODE_STRING pRegistryString)  {      NTSTATUS        status = STATUS_SUCCESS;      IDTINFO            idt_info;      IDTENTRY*        idt_entrys;      unsigned long    count;      __asm sidt idt_info;      idt_entrys = (IDTENTRY*)MAKELONG(idt_info.LowIDTbase, idt_info.HiIDTbase);      KdPrint(("IDT Addr: 0x%08X\n", MAKELONG(idt_info.LowIDTbase, idt_info.HiIDTbase)));      KdPrint(("IDT Limit: %d\n", idt_info.IDTLimit));      for (count = 0; count<=MAX_IDT_ENTRIES; count++)      {          char _t[255];          unsigned long addr;          IDTENTRY* i = &idt_entrys[count];          addr = MAKELONG(i->LowOffset, i->HiOffect);          _snprintf(_t, 253, "Interrupt %3d\tISR 0x%08X", count, addr);          KdPrint(("%s", _t));      }      pDriverObj->DriverUnload = DriverUnload;      return STATUS_SUCCESS;  }  

打印结果如下:

这里写图片描述

0 0
原创粉丝点击