x64技术之SSDT_Hook

x64技术之SSDT_Hook

测试环境:

虚拟机: Windows 7 64bit

过PG工具

驱动加载工具

PCHunter64

系统自带的计算器和任务管理器等

实现思路:

实际思路与win32的思路一样.都是替换SSDT表里边的函数地址.不过微软被搞怕了,所以在x64上做了一些手脚.

具体手脚就是x64通过SSDT得到的函数地址,不是真实的函数绝对地址了,而是加密了的.

HOOK

1.得到系统服务表基址

2.保存需要Hook的函数地址(实际为偏移)

3.使内存可写,把表中要Hook的地址替换成KeBugCheckEx的地址,还原内存属性

4.HookKeBugCheckEx函数,在其开始处jmp到我们自己的函数地址.

5.自己实现Hook的函数,在其中做处理.

注:

x64要Hook的函数地址是 ServiceTableBase[Index]>>4 + ServiceTableBase

此处Hook了NtOpenProcess,导出序号是35号.处理了结束计算器进程的时候,禁止结束.

还原Hook的时候不需要还原KeBugCheckEx,因为这个函数就是崩溃蓝屏需要执行的函数.

这篇文章不会讲述过PG.

关键代码:

获取服务表基址

//获取服务表基址
ULONGLONG GetKeServiceDescriptorTable64() 
{
	PUCHAR StartSearchAddress = (PUCHAR)__readmsr(0xC0000082);
	PUCHAR EndSearchAddress = StartSearchAddress + 0x500;
	PUCHAR i = NULL;
	UCHAR byte1 = 0, byte2 = 0, byte3 = 0;
	ULONG temp = 0;
	ULONGLONG addr = 0;
	//开始搜索
	for (i = StartSearchAddress;i < EndSearchAddress;i++)
	{
		if (MmIsAddressValid(i) && MmIsAddressValid(i + 1) && MmIsAddressValid(i + 2))
		{
			byte1 = *i;
			byte2 = *(i + 1);
			byte3 = *(i + 2);
			if (byte1 == 0x4c && byte2 == 0x8d && byte3 == 0x15) //4c8d15
			{
				memcpy(&temp, i + 3, 4);
				addr = (ULONGLONG)temp + (ULONGLONG)i + 7;
				return addr;
			}
		}
	}
	return 0;
}

获取SSDT表中的函数地址

//获取SSDT中的函数地址
ULONGLONG GetSSDTFuncCurrentAddr(ULONG id)
{
	LONG dwtemp = 0;
	PULONG ServiceTableBase = NULL;
	ServiceTableBase = (PULONG)KeServiceDescriptorTable->ServiceTableBase;
	dwtemp = ServiceTableBase[id];
	dwtemp = dwtemp >> 4;
	return (LONGLONG)dwtemp + (ULONGLONG)ServiceTableBase;
}

开启Hook

//开启Hook
VOID HookSSDT()
{
	KIRQL irql;
	ULONGLONG dwtmp = 0;
	PULONG ServiceTableBase = NULL;
	//获取老函数地址
	g_OldOpenProcess = (NTOPENPROCESS)GetSSDTFuncCurrentAddr(35);
	//HookKeBugCheckEx
	InlineHookKeBugCheckEx();
	//保存地址数据,替换数据
	ServiceTableBase = (PULONG)KeServiceDescriptorTable->ServiceTableBase;
	OldTpVal = ServiceTableBase[35];	//保存表中的偏移变量
	irql = WriteProtectOFFx64();
	ServiceTableBase[35] = GetOffsetAddress((ULONGLONG)KeBugCheckEx);
	WriteProtectONx64(irql);
}

HookKeBugCheckEx作为跳转

//InlineHook_KeBugCheckEx
VOID InlineHookKeBugCheckEx()
{
	KIRQL irql;
	ULONGLONG myfun;
	UCHAR jmp_code[] = "\x48\xB8\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xE0";
	myfun = (ULONGLONG)HookNtOpenProcess;//替换成自己的函数地址
	memcpy(jmp_code + 2, &myfun, 8);
	irql = WriteProtectOFFx64();
	memset(KeBugCheckEx, 0x90, 15);
	memcpy(KeBugCheckEx, jmp_code, 12);//拷贝12字节
	WriteProtectONx64(irql);
}

测试效果:

过PG后,加载驱动,使用任务管理器结束"计算器"程序失败,提示"拒绝访问"



PCHunter64位查看,又看到驱动挂钩了NtOpenProcess函数


PS:博客的技术内容的宽度可是开的有点大了,感觉自己很难把这些坑都填完.尽力填吧,每一个技术方面都尽力去深究.不过也有自己的事要做,填坑的速度肯定是快不了的.

猜你喜欢

转载自blog.csdn.net/wrsharper/article/details/80272337