[驱动开发] idt hook测试

主要理解下面的内容:

1:

KiProcessorBlock数组的每一个非0项都是指向一个_kprcb结构,而_kprcb结构正是再_kpcr结构的+0x120处,_kpcr结构的+0x38就是_IDT结构地址。

2:

通过硬编码 使用ida找到 KiProcessorBlock

3:

IDt的表结构的理解, 进行函数过滤


详细使用代码 (xp3)

#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{
	USHORT   IDT_limit;
	USHORT   IDT_LOWbase;
	USHORT   IDT_HIGbase;
}IDTR, *PIDTR;

typedef struct _IDTENTRY
{
	unsigned short LowOffset;
	unsigned short selector;
	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;

//global
ULONG	g_InterruptFunc3;

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
	}
}


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;


void ReadIdtInfo()
{
	IDTR idtr;
	ULONG idtBase;
	PIDTENTRY pIDT;
	ULONG uIndex;

	__asm{
		sidt idtr;
	}

	idtBase = MAKELONG(idtr.IDT_LOWbase, idtr.IDT_HIGbase);

	DbgPrint("base: %X", idtBase);

	pIDT = (PIDTENTRY)idtBase;

	for (uIndex = 0; uIndex < (ULONG)idtr.IDT_limit / 8; uIndex++)
	{
		DbgPrint("%d,%X%X", uIndex, pIDT[uIndex].HiOffset, pIDT[uIndex].LowOffset);
	}



}

void __stdcall FilterInterruptFunc3()
{
	USHORT u_es, u_ds;
	KdPrint(("当前进程:%s", (char*)PsGetCurrentProcess() + 0x174)); //当前进程触发了 中断历程 进入内核
	__asm{
		mov	u_es, es
			mov u_ds, ds
	}
	KdPrint(("%X,%X\n", u_es, u_ds));
}

__declspec(naked)
void NewInterruptFunc3()
{
	__asm{
		pushad
			pushfd
			push	fs
			push	0x30
			pop		fs
			call	FilterInterruptFunc3
			pop		fs
			popfd
			popad
			jmp		g_InterruptFunc3
	}
}
ULONG	GetInterruptFuncAddress(ULONG InterruptIndex)//得到老3号中断地址
{
	IDTR		idtr;
	IDTENTRY	*pIdtEntry;
	__asm{
		SIDT	idtr
	};
	pIdtEntry = (IDTENTRY *)MAKELONG(idtr.IDT_LOWbase, idtr.IDT_HIGbase);
	return MAKELONG(pIdtEntry[InterruptIndex].LowOffset, pIdtEntry[InterruptIndex].HiOffset);//得到3号中断函数的地址 老地址 返回的是个4字节的
}


VOID SetInterrupt(ULONG InterruptIndex, ULONG NewInterruptFunc)//设置3号断点 跟新hook函数
{
	ULONG			u_fnKeSetIdealProcessorThread; //ULONG 4字节
	UNICODE_STRING	usFuncName;
	ULONG			u_index;
	ULONG			*u_KiProcessorBlock;
	IDTENTRY		*pIdtEntry;
	PKGDTENTRY		pGdt;
	RtlInitUnicodeString(&usFuncName, L"KeSetIdealProcessorThread");
	u_fnKeSetIdealProcessorThread = (ULONG)MmGetSystemRoutineAddress(&usFuncName);//得到系统程序地址 内核模块里的函数的地址
	if (!MmIsAddressValid((PVOID)u_fnKeSetIdealProcessorThread))
	{
		return;
	}
	u_KiProcessorBlock = *(ULONG**)(u_fnKeSetIdealProcessorThread + 94);//定位得到  cpu全局变量的地址
	u_index = 0;
	while (u_KiProcessorBlock[u_index])// 多核4核cpu
	{
		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号元素的 段内偏移
		//KdPrint(("pGdt%x\n", pGdt));数组为1的就是段基址
		
		PageProtectOff();
		pIdtEntry[InterruptIndex].LowOffset = (unsigned short)((ULONG)NewInterruptFunc & 0xffff);//取新函数低4位值 16位二进制不变 前16位全是0   
		pIdtEntry[InterruptIndex].HiOffset = (unsigned short)((ULONG)NewInterruptFunc >> 16);//取新函数高4位值	
		PageProtectOn();
		
		u_index++;
	}
}

VOID DriverUnload(IN PDRIVER_OBJECT pDriverObject)
{
	DbgPrint("DriverUnload");
	SetInterrupt(3, g_InterruptFunc3);
}


NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject, IN PUNICODE_STRING RegistryPath)
{
	//ReadIdtInfo();
	//ShowIdtInfo();

	USHORT u_cs;
	g_InterruptFunc3 = GetInterruptFuncAddress(3);
	__asm	mov		u_cs, cs;
	KdPrint(("\n%X--%X\n", NewInterruptFunc3, u_cs));
	SetInterrupt(3, (ULONG)NewInterruptFunc3);
	

	pDriverObject->DriverUnload = DriverUnload;
	DbgPrint("DriverEntry");
	return STATUS_SUCCESS;
}



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

发表评论

0则评论给“[驱动开发] idt hook测试”