zoukankan      html  css  js  c++  java
  • HOOK技术之SSDT hook(x86/x64)

    x86 SSDT Hook

    32位下进行SSDT Hook比较简单,通过修改SSDT表中需要hook的系统服务为自己的函数,在自己的函数中进行过滤判断达到hook的目的。

    获取KeServiceDescriptorTable基地址

    要想进行ssdt hook,首先需要获得SSDT表的基地址。
    因为KeServiceDescriptorTable是ntoskrnl.exe导出的,所以我们可以直接在程序中声明导入符号得到KeServiceDescriptorTable的值。

    typedef struct ServiceDescriptorEntry {
    	unsigned int *ServiceTableBase;
    	unsigned int *ServiceCounterTableBase;
    	unsigned int NumberOfServices;
    	unsigned char *ParamTableBase;
    } ServiceDescriptorTableEntry_t, *PServiceDescriptorTableEntry_t;
    
    extern "C" __declspec(dllimport)  ServiceDescriptorTableEntry_t  KeServiceDescriptorTable;
    

    可以通过ntoskrnl.exe的EAT导出表得到KeServiceDescriptorTable的值。

    还可以通过搜索KeAddSystemServiceTable进行硬编码0xB883得到KeServiceDescriptorTable的值

    获取KeServiceDescriptorTableShadow基地址

    因为KiServiceDescriptorTableShadow并未被win32k.sys导出,所以只能通过硬编码搜索KeAddSystemServiceTable/KeRemoteSystemServiceTable得到

    基地址差法,一般KiServiceDescriptorTableShadow就在KiServiceDescriptorTable附近如果xp就是 KeServiceDescriptorTableShadow=KeServiceDescriptorTable-0×40。如果是win7:KeServiceDescriptorTableShadow=KeServiceDescriptorTable+0×40;

    注意KeServiceDescriptorTableShadow表中包含了KeServiceDescriptorTable表的内容

    x64 SSDT Hook

    HOOK思路

    因为x64位中ssdt表是加密的,ssdt中的每一项占4个字节但并不是对应的系统服务的地址,因为x64中地址为64位而ssdt每一项只有4个字节32位所以无法直接存放服务的地址。其实际存储的4个字节的前28位表示的是对应的系统服务相对于SSDT表基地址的偏移,而后4位如果对应的服务的参数个数小于4则其值为0,不小于4则为参数个数减去4。所以我们在ssdt hook时向ssdt表项中填入的函数得在ntoskrnl.exe模块中,原因是因为函数到SSDT表基地址的偏移大小小于4个字节。所以我们选取一个ntoskrnl.exe中很少使用的函数KeBugCheckEx作为中转函数,将需要hook的ssdt项的改为KeBugCheckEx函数,然后在inlinehook KeBugCheck函数,jmp到我们的函数中进行过滤。

    PatchGard

    64系统增加了内核哨兵机制(PatchGard),一旦发现内核关键代码被篡改就会直接蓝屏。所以在64位系统上进行SSDT Hook需要绕过PatchGard。

    获取KeServiceDescriptorTable和KeServiceDescriptorTableShadow基地址

    64位系统调用过程为 syscall --》nt!KiSystemCall64--》nt!KiSystemServiceStart--》nt!KiSystemServiceRepeat--》call r10调用对应的系统服务。

    我们可以通过获取nt!KiSystemCall64函数的地址,然后找到nt!KiSystemServiceRepeat函数通过硬编码得到KeServiceDescriptorTable和KeServiceDescriptorTableShadow的基地址。因为MSR寄存器的0xC0000082被设置为nt!KiSystemCall64函数的地址,所以我们可以通过读取MSR寄存器得到此函数地址。

    ULONGLONG MyGetKeServiceDescriptorTable64()
    {
    	PUCHAR StartSearchAddress = (PUCHAR)__readmsr(0xC0000082);
    	PUCHAR EndSearchAddress = StartSearchAddress + 0x500;
    	PUCHAR i = NULL;
    	UCHAR b1 = 0, b2 = 0, b3 = 0;
    	ULONG templong = 0;
    	ULONGLONG addr = 0;
    	for (i = StartSearchAddress;i < EndSearchAddress;i++)
    	{
    		if (MmIsAddressValid(i) && MmIsAddressValid(i + 1) && MmIsAddressValid(i + 2))
    		{
    			b1 = *i;
    			b2 = *(i + 1);
    			b3 = *(i + 2);
    			if (b1 == 0x4c && b2 == 0x8d && b3 == 0x15) //4c8d15
    			{
    				memcpy(&templong, i + 3, 4);
    				addr = (ULONGLONG)templong + (ULONGLONG)i + 7;
    				return addr;
    			}
    		}
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    js中属性点.和中括号[]的关系。
    jQuery中的$(window).load()与$(document).ready()以及jquery $(document).ready() 与window.onload的区别
    今天中了一个脚本病毒。把我的所有 html 加了 vbs 脚本,WriteData 是什么鬼?
    原生js 当前时间 倒计时代码
    一看就懂得移动端rem布局、rem如何换算
    使用CSS实现三栏自适应布局(两边宽度固定,中间自适应)
    js运算符的一些特殊应用
    中文目录对 sublime text 有什么影响?
    Spring的注解@Qualifier小结
    伪共享(False Sharing)
  • 原文地址:https://www.cnblogs.com/revercc/p/14701592.html
Copyright © 2011-2022 走看看