[驱动开发]隐藏idt HOOK

原理:

段基址 + 偏移地址  =  函数地址


让idt不动的话, 就需要更改段基址


实例代码:


#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));
}
 fa
__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;
}





原文链接: [驱动开发]隐藏idt HOOK 版权所有,转载时请注明出处,违者必究。
注明出处格式:流沙团 ( https://gyarmy.com/post-501.html )

发表评论

0则评论给“[驱动开发]隐藏idt HOOK”