您的位置:首页 > 其它

反idt hook 隐藏hook idt

2017-05-14 22:57 232 查看
#include "ntddk.h"

#include "ntddk.h"

#define WORD	USHORT
#define DWORD	ULONG

#define MAKELONG(a, b)      ((LONG)(((WORD)(((DWORD_PTR)(a)) & 0xffff)) \
| ((DWORD)((WORD)(((DWORD_PTR)(b)) & 0xffff))) << 16))

typedef struct _IDTR{    //idt的表的地址
USHORT   IDT_limit;
USHORT   IDT_LOWbase;
USHORT   IDT_HIGbase;
}IDTR, *PIDTR;

typedef struct _IDTENTRY   //idt的表的元素地址
{
unsigned short LowOffset;
unsigned short selector;//16位
unsigned char retention : 5;
unsigned char zero1 : 3;
unsigned char gate_type : 1;
unsigned char zero2 : 1;
unsigned char interrupt_gate_size : 1;
unsigned char zero3 : 1;
unsigned char zero4 : 1;
unsigned char DPL : 2;
unsigned char P : 1;
unsigned short HiOffset;
} IDTENTRY, *PIDTENTRY;

typedef struct _KGDTENTRY {   //gdt表的元素的结构里
USHORT  LimitLow;
USHORT  BaseLow;
union {
struct {
UCHAR   BaseMid;
UCHAR   Flags1;     // Declare as bytes to avoid alignment
UCHAR   Flags2;     // Problems.
UCHAR   BaseHi;
} Bytes;
struct {
ULONG   BaseMid : 8;
ULONG   Type : 5;
ULONG   Dpl : 2;
ULONG   Pres : 1;

ULONG   LimitHi : 4;
ULONG   Sys : 1;
ULONG   Reserved_0 : 1;
ULONG   Default_Big : 1;
ULONG   Granularity : 1;
ULONG   BaseHi : 8;
} Bits;
} HighWord;
} KGDTENTRY, *PKGDTENTRY;
//global
USHORT g_FilterJmp[3];//2字节
ULONG  g_uOrigInterruptFunc;//保存老的3号中断的函数地址
void PageProtectOn()
{
__asm{//恢复内存保护
mov  eax, cr0
or   eax, 10000h
mov  cr0, eax
sti
}
}

void PageProtectOff()
{
__asm{//去掉内存保护
cli
mov  eax, cr0
and  eax, not 10000h
mov  cr0, eax
}
}

USHORT	g_u_cs;
void __stdcall FilterInterrupt()//过滤函数
{
KdPrint(("%s---%X", (char*)PsGetCurrentProcess() + 0x16c, g_u_cs));
}

__declspec(naked)
void NewInterrupt3OfOrigBase()//我的hook函数
{
__asm{
pushad
pushfd

push	fs
push	0x30
pop		fs

call	FilterInterrupt

pop		fs

popfd
popad

jmp		g_uOrigInterruptFunc
}
}

__declspec(naked)
void NewInterrupt3()//新3号中断函数 直接把基地址改成偏移了 就进入了我的hook函数
{
__asm{
mov	g_u_cs, cs
jmp	fword ptr[g_FilterJmp] //NewInterrupt3OfOrigBase 现实了远跳转 在原始的段基址
}
}

ULONG	GetInterruptFuncAddress(ULONG InterruptIndex)//得到老3号中断的地址 保存
{
IDTR		idtr;
IDTENTRY	*pIdtEntry;
__asm	SIDT	idtr;
pIdtEntry = (IDTENTRY *)MAKELONG(idtr.IDT_LOWbase, idtr.IDT_HIGbase);
KdPrint(("idt表地址%x\n", pIdtEntry));
return MAKELONG(pIdtEntry[InterruptIndex].LowOffset, pIdtEntry[InterruptIndex].HiOffset);
}

ULONG GetNewBase(ULONG NewInterruptFunc, ULONG OrigInterruptOffset)
{
return (NewInterruptFunc - OrigInterruptOffset);
}

VOID SetInterrupt(ULONG InterruptIndex, ULONG uNewBase, BOOLEAN bIsNew)//先 得到idt gdt 表地址 然后再改选择符
{
ULONG			u_fnKeSetTimeIncrement;
UNICODE_STRING	usFuncName;
ULONG			u_index;
ULONG			*u_KiProcessorBlock;
IDTENTRY		*pIdtEntry;
PKGDTENTRY		pGdt;
RtlInitUnicodeString(&usFuncName, L"KeSetTimeIncrement");
u_fnKeSetTimeIncrement = (ULONG)MmGetSystemRoutineAddress(&usFuncName);
if (!MmIsAddressValid((PVOID)u_fnKeSetTimeIncrement))
{
return;
}
u_KiProcessorBlock = *(ULONG**)(u_fnKeSetTimeIncrement + 44);
u_index = 0;
while (u_KiProcessorBlock[u_index])
{
pIdtEntry = *(IDTENTRY**)(u_KiProcessorBlock[u_index] - 0xE8);//得到idt表地址
pGdt = *(PKGDTENTRY*)(u_KiProcessorBlock[u_index] - 0xE4);//得到gdt表地址
KdPrint(("Idt段基址选择符%x\n", pIdtEntry[3].selector));//得到3号中断 段选择符 为8
KdPrint(("GDT表:%X--%X--%X--%X\n", pGdt, pGdt[1].BaseLow, pGdt[1].HighWord.Bits.BaseMid, pGdt[1].HighWord.Bits.BaseHi));//由8二进制1000得到内核层gdt表的数组1号元素的 段内偏移
PageProtectOff();

if (bIsNew)
{
pIdtEntry[InterruptIndex].selector = 0xa8;//10101000   第21元素 idt表的选择符8修改成了a8   1111000  //A8原来是
RtlCopyMemory(&pGdt[21], &pGdt[1], sizeof(KGDTENTRY));//把第2元素的地址复制给了 第21元素的地址
KdPrint(("新段基址%x\n", uNewBase));
pGdt[21].BaseLow = (USHORT)(uNewBase & 0xffff);//第21元素的内容修改
pGdt[21].HighWord.Bytes.BaseMid = (UCHAR)((uNewBase >> 16) & 0xff);
pGdt[21].HighWord.Bytes.BaseHi = (UCHAR)(uNewBase >> 24); //直接把基地址改成偏移了 就进入了我的hook函数
}
else{
pIdtEntry[InterruptIndex].selector = 0x8;//还原选择为8
memset(&pGdt[21], 0, sizeof(KGDTENTRY));//还原第21元素的地址修改为0 int3中断走正常的选择符
}
PageProtectOn();
u_index++;
}
}

VOID HookInterruptFunc(ULONG InterruptIndex, ULONG NewInterruptFunc)
{	//USHORT g_FilterJmp[3];//2字节
ULONG	uNewBase;
g_uOrigInterruptFunc = GetInterruptFuncAddress(InterruptIndex);//保存老的3号中断的函数地址
uNewBase = NewInterruptFunc - g_uOrigInterruptFunc;//新3号中断函数 - 老3号中断函数 = 新段基址 直接把基地址改成偏移了 就进入了我的hook函数
*(ULONG*)g_FilterJmp = (ULONG)NewInterrupt3OfOrigBase; //低1, 4的元素 赋值  我的hook函数
g_FilterJmp[2] = 0x8;//高5,6的元素 赋值
SetInterrupt(InterruptIndex, uNewBase, TRUE);
}

void UnHookInterruptFunc(ULONG InterruptIndex)
{
SetInterrupt(InterruptIndex, 0, FALSE);
}

VOID MyUnload(PDRIVER_OBJECT	pDriverObject)
{
UnHookInterruptFunc(3);
}

NTSTATUS DriverEntry(PDRIVER_OBJECT	pDriverObject, PUNICODE_STRING Reg_Path)
{
HookInterruptFunc(3, (ULONG)NewInterrupt3);
pDriverObject->DriverUnload = MyUnload;
return STATUS_SUCCESS;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: