IDT Hook

来源:互联网 发布:美国大数据公司排名 编辑:程序博客网 时间:2024/06/05 20:44

这两天读了combojiang(此君真乃天牛也)一篇关于IDT Hook的文章,于是自己实现了一个Hook鼠标中断服务的程序,自己也总结一下。

IDT即Interrupt Descriptor Table,描述了系统硬件/软件中断以及异常,这张表总共描述了0x7ff个中断(XP SP2),表中的每个元素代表一个中断门(Interrupt Gate),其格式如下所示:精力充沛

在我的程序中将该结构定义为:

typedef struct _IDTENTRY
{
unsigned short lw_offset;
unsigned short seg_selector;
unsigned char dword_count:5;
unsigned char unused0:3;
unsigned char type:4;
unsigned char unused1:1;
unsigned char dpl:2;
unsigned char present:1;
unsigned short hi_offset;
}IDTENTRY,*PIDTENTRY;

IDT Hook的核心思想就是找到你所需要的ISR(Interrupt Service Routine)的中断门,并修改其地址,即上述结构中的lw_offset与hi_offset。

因此问题的关键就是定位中断门位置,也就是找出IDT的首地址以及中断号。中断号可以使用内核调试器(我用WinDbg)很容易的找到。386中IDT的首地址保存在寄存器IDTR中,这是一个48bits的寄存器,其结构如下所示:

该寄存器可以使用sidt加载,为方便起见,我把IDTR定义为下面的结构:

typedef struct _IDTR
{
unsigned short limit;
unsigned short lwaddr;
unsigned short hiaddr;
}IDTR,*PIDTR;

这样我们就基本解决了IDT Hook的难点了,具体代码如下:

#include <ntddk.h>
#include "idthook.h"

static unsigned int gsCount = 0;

static unsigned long gs_old_inter;

unsigned long __stdcall SetIDTEntry(unsigned char offset,unsigned long addr)
{
IDTR idtr;
PIDTENTRY pIDTEntry;
unsigned long old_inter;

__asm
{
   sidt idtr
}

DbgPrint("Address:%x%x/tLimit:%x",idtr.hiaddr,idtr.lwaddr,idtr.limit);
pIDTEntry = (PIDTENTRY)((unsigned long)(idtr.hiaddr)<<16 | idtr.lwaddr );
#ifndef NDEBUG
for(i=0;i<0x7ff;i++)
{
   DbgPrint("IDTNO:%x/tISR:%x%x/tPresent:%x/tDPL:%x/tTYPE:%x/tSelector:%x/tDWORD_Count:%x/tUnused0:%x/tUnused1:%x",
    i,
    pIDTEntry[i].hi_offset,
    pIDTEntry[i].lw_offset,
    pIDTEntry[i].present,
    pIDTEntry[i].dpl,
    pIDTEntry[i].type,
    pIDTEntry[i].seg_selector,
    pIDTEntry[i].dword_count,
    pIDTEntry[i].unused0,
    pIDTEntry[i].unused1
    );
}
#endif

old_inter = (unsigned long)((unsigned long)pIDTEntry[offset].hi_offset << 16 | pIDTEntry[offset].lw_offset );
__asm
{
   cli    
}

pIDTEntry[offset].hi_offset = (unsigned short)(addr >> 16);
pIDTEntry[offset].lw_offset = (unsigned short)addr;

__asm
{
   sti
}

return old_inter;
}

NTSTATUS DriverUnload(IN PDRIVER_OBJECT DriverObject)
{
DbgPrint("Driver Unloading...");
SetIDTEntry(0xa3,gs_old_inter);
DbgPrint("Key Board Interrupt Count:%x",gsCount);
return STATUS_SUCCESS;
}

void __stdcall count_interrupt()
{
gsCount++;
}

__declspec(naked) inter_hook()
{
__asm
{
   call count_interrupt
   jmp gs_old_inter
}
}

NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING path)
{
DriverObject->DriverUnload = DriverUnload;
DbgPrint("Driver Loading...");

gs_old_inter = SetIDTEntry(0xa3,(unsigned long)inter_hook);
return STATUS_SUCCESS;
}

原创粉丝点击