x86 IDT HOOK

准备资料:

  中断描述符表(Interrupt Descriptor Table,IDT)显然是用来处理中断的。IDT指定了如何处理诸如下一个键、发生页面错误或用户进程请求SSDT时所触发的中断。本文介绍HOOK IDT中的向量0x2E,该钩子在SSDT中的内核函数之前进行调用。

  处理IDT时需要注意两点,每个处理器都有自己的IDT,需要钩住系统上的所有IDT。

  当应用程序需要操作系统的支持时,NTDLL.DLL向EAX寄存器加载SSDT中系统调用的索引号,向EDX寄存器加载用户堆栈参数的指针。然后发出中断指令进入内核。

  SIDT指令将在内存中为每个CPU寻找IDT。SIDT指令将中断描述符表寄存器IDTR(64bit,16-47bit存有中断描述表符IDT基地址)的内容存入指定地址单元。这个指令不是特权指令。

  

__asm
{
    sidt Idt_info ;
}

  Idt_info实际上是IDTINFO结构。

 IDTINFO结构:
  typedef struct
   {
     WORD IDTLimit;
     WORD LowIDTbase;   //IDT的低半地址
     WORD HiIDTbase;     //IDT的高半地址
   } IDTINFO;
   
   #define MAKELONG(a, b)((LONG)(((WORD)(a))|((DWORD)((WORD)(b)))<< 16))

  IDT划分为一个较低的WORD值和一个较高的WORD值,可以通过MAKELONG宏来获得正确的DWORD值,其中最高位WORD在前面。

 

  IDT中每一项都具有自己的结构,长度为64位。每一项包含一个特定中断处理函数的地址。IDTENTRY结构中的LowOffset和HiOffset组成了中断处理程序的地址。

  

#pragma pack(1)
typedef struct
{
    unsigned short LowOffset;
    unsigned short selector;
    unsigned char unused_lo;
    unsigned char segment_type:4;    //0x0E is an interrupt gate
    unsigned char system_segment_flag:1;
    unsigned char DPL:2;    // descriptor privilege level 
    unsigned char P:1; /* present */
    unsigned short HiOffset;
} IDTENTRY;

/* sidt returns idt in this format */
typedef struct
{
    unsigned short IDTLimit;
    unsigned short LowIDTbase;
    unsigned short HiIDTbase;
} IDTINFO;

#pragma pack()

 

参考代码:(copy from www.rootkit.com)

  

  1 // ---------------------------
  2 // BASIC INTERRUPT HOOK part 3
  3 // this hooks the entire table
  4 // ---------------------------
  5 
  6 #include "ntddk.h"
  7 #include <stdio.h>
  8 
  9 //debuggering
 10 //#define _DEBUG
 11 
 12 #define MAKELONG(a, b) ((unsigned long) (((unsigned short) (a)) | ((unsigned long) ((unsigned short) (b))) << 16)) 
 13 
 14 // set this to the max int you want to hook
 15 #define MAX_IDT_ENTRIES 0xFF
 16 
 17 // the starting interrupt for patching
 18 // to 'skip' some troublesome interrupts
 19 // at the beginning of the table (TODO, find out why)
 20 #define START_IDT_OFFSET 0x00
 21 
 22 unsigned long g_i_count[MAX_IDT_ENTRIES];
 23 unsigned long old_ISR_pointers[MAX_IDT_ENTRIES];    // better save the old one!!
 24 
 25 char jump_template[] = { 
 26     0x90,                                        //nop, debug
 27     0x60,                                        //pushad
 28     0x9C,                                        //pushfd
 29     0xB8, 0xAA, 0x00, 0x00, 0x00,                //mov eax, AAh
 30     0x50,                                        //push eax
 31     0x9A, 0x11, 0x22, 0x33, 0x44, 0x08, 0x00,    //call 08:44332211h
 32     0x58,                                        //pop eax
 33     0x9D,                                        //popfd
 34     0x61,                                        //popad
 35     0xEA, 0x11, 0x22, 0x33, 0x44, 0x08, 0x00    //jmp 08:44332211h
 36 };
 37 
 38 char * idt_detour_tablebase;
 39 
 40 
 41 ///
 42 // IDT structures
 43 ///
 44 #pragma pack(1)
 45 
 46 // entry in the IDT, this is sometimes called
 47 // an "interrupt gate"
 48 typedef struct
 49 {
 50     unsigned short LowOffset;
 51     unsigned short selector;
 52     unsigned char unused_lo;
 53     unsigned char segment_type:4;    //0x0E is an interrupt gate
 54     unsigned char system_segment_flag:1;
 55     unsigned char DPL:2;    // descriptor privilege level 
 56     unsigned char P:1; /* present */
 57     unsigned short HiOffset;
 58 } IDTENTRY;
 59 
 60 /* sidt returns idt in this format */
 61 typedef struct
 62 {
 63     unsigned short IDTLimit;
 64     unsigned short LowIDTbase;
 65     unsigned short HiIDTbase;
 66 } IDTINFO;
 67 
 68 #pragma pack()
 69 
 70 
 71 
 72 VOID OnUnload( IN PDRIVER_OBJECT DriverObject )
 73 {    
 74     int i;
 75     IDTINFO        idt_info;        // this structure is obtained by calling STORE IDT (sidt)
 76     IDTENTRY*    idt_entries;    // and then this pointer is obtained from idt_info
 77     char _t[255];
 78 
 79     // load idt_info
 80     __asm    sidt    idt_info    
 81     idt_entries = (IDTENTRY*) MAKELONG(idt_info.LowIDTbase,idt_info.HiIDTbase);
 82 
 83     DbgPrint("ROOTKIT: OnUnload called\n");
 84 
 85     for(i=START_IDT_OFFSET;i<MAX_IDT_ENTRIES;i++)
 86     {
 87         _snprintf(_t, 253, "interrupt %d called %d times", i, g_i_count[i]);
 88         DbgPrint(_t);
 89     }
 90 
 91     DbgPrint("UnHooking Interrupt...");
 92 
 93     for(i=START_IDT_OFFSET;i<MAX_IDT_ENTRIES;i++)
 94     {
 95         // restore the original interrupt handler
 96         __asm cli
 97         idt_entries[i].LowOffset = (unsigned short) old_ISR_pointers[i];
 98         idt_entries[i].HiOffset = (unsigned short)((unsigned long)old_ISR_pointers[i] >> 16);
 99         __asm sti
100     }
101 
102 
103     DbgPrint("UnHooking Interrupt complete.");
104 }
105 
106 NTSTATUS DriverEntry( IN PDRIVER_OBJECT theDriverObject, IN PUNICODE_STRING theRegistryPath )
107 {
108     IDTINFO        idt_info;        // this structure is obtained by calling STORE IDT (sidt)
109     IDTENTRY*    idt_entries;    // and then this pointer is obtained from idt_info
110     IDTENTRY*    i;
111     unsigned long     addr;
112     unsigned long    count;
113     char _t[255];
114 
115     theDriverObject->DriverUnload  = OnUnload; 
116 
117     for(count=START_IDT_OFFSET;count<MAX_IDT_ENTRIES;count++)
118     {
119         g_i_count[count]=0;
120     }
121 
122     // load idt_info
123     __asm    sidt    idt_info
124     idt_entries = (IDTENTRY*) MAKELONG(idt_info.LowIDTbase,idt_info.HiIDTbase);
125 
126     ////
127     // save old idt pointers
128     ////
129     for(count=START_IDT_OFFSET;count < MAX_IDT_ENTRIES;count++)
130     {
131         i = &idt_entries[count];
132         addr = MAKELONG(i->LowOffset, i->HiOffset);
133 
134         _snprintf(_t, 253, "Interrupt %d: ISR 0x%08X", count, addr);
135         DbgPrint(_t);
136 
137         old_ISR_pointers[count] = MAKELONG(idt_entries[count].LowOffset,idt_entries[count].HiOffset);
138     }
139 
140 
141     ///
142     // setup the detour table
143     ///
144     idt_detour_tablebase = ExAllocatePool(NonPagedPool, sizeof(jump_template)*256);
145 
146     for(count=START_IDT_OFFSET;count<MAX_IDT_ENTRIES;count++)
147     {
148         int offset = sizeof(jump_template)*count;    
149         char *entry_ptr = idt_detour_tablebase + offset;
150 
151         // entry_ptr points to the start of our jump code in the detour_table
152 
153         // copy the starter code into the template location
154         memcpy(entry_ptr, jump_template, sizeof(jump_template));
155 
156         // stamp the far jump to the original ISR
157         *( (unsigned long *)(&entry_ptr[20]) ) = old_ISR_pointers[count];
158 
159         // finally, make the interrupt point to our template code
160         __asm cli
161         idt_entries[count].LowOffset = (unsigned short)entry_ptr;
162         idt_entries[count].HiOffset = (unsigned short)((unsigned long)entry_ptr >> 16);
163         __asm sti
164     }
165 
166     DbgPrint("Hooking Interrupt complete");
167 
168     return STATUS_SUCCESS;
169 }

 

XP虚拟机加载该驱动后,贴出DbgView日志

View Code

 

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值