驱动开发中内核SSDT函数的 HOOK跳板选择
/*此程序于2022年3月17日下午正式调试修改完成,涉及很多知识*//*64位的内核跳出转很有讲究,不能直接改,因为驱动程序的内存地址与内核需要修改的地址之间的差距过大,超过0xFFFFFFFF*/
/*所以必须得有跳板,这个跳板通常很难选择,用KeBugCheckEx()是个好办法*/
下面提供一下思路,有一定基础的朋友,应该可以实现功能:
/*处理跳板函数*/
VOID FuckKeBugCheckEx()
{
KIRQL irql;
ULONGLONG myfun;
UCHAR jmp_code[] = "\xFF\x25\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF";
myfun = (ULONGLONG)New_ZwQueryDirectoryFile;
DbgPrint("myfun地址是========%p\n", myfun);
memcpy(jmp_code + 6, &myfun, 8); // &myfun 取函数的地址
//DbgPrint("KeBugCheckEx2地址是========%p\n", KeBugCheckEx2);
ori_head_byte = kmalloc(15);
irql = WPOFFx64();
//保存原头部15字节
memcpy(ori_head_byte, KeBugCheckEx2, 15); //在UNLOAD时恢复03-17
//直接写函数名,即操作此函数的代码!
//memcpy(KeBugCheckEx, ori_head_byte, 15);
//保存地址时需要申请内存。
//以下改写原函数开头代码
memset(KeBugCheckEx2, 0x90, 15);
memcpy(KeBugCheckEx2, jmp_code, 14);
/*---------------------------------*/
WPONx64(irql);
}
// SSDT Unhook
BOOLEAN SSDTUnhook()
{
return TRUE;
}
// SSDT Hook
BOOLEAN SSDTHook()
{
UNICODE_STRING ustrDllFileName;
ULONG ulSSDTFunctionIndex = 0;
PMDL pMdl = NULL;
PVOID pNewAddress = NULL;
ULONGLONG ulNewFuncAddr = 0;
NTSTATUS status;
KIRQL irql;
KeBugCheckEx2 = (PVOID)((ULONGLONG)KeBugCheckEx + 16);
/*lkd> u KeBugCheckEx //原始数据
t!KeBugCheckEx:
fffff800`01e82640 48894c2408 mov qword ptr ,rcx
fffff800`01e82645 4889542410 mov qword ptr ,rdx
fffff800`01e8264a 4c89442418 mov qword ptr ,r8
fffff800`01e8264f 4c894c2420 mov qword ptr ,r9
fffff800`01e82654 9c pushfq
*/
/*lkd> u KeBugCheckEx //HOOK以后的
nt!KeBugCheckEx:
fffff800`01e82640 48894c2408 mov qword ptr ,rcx
fffff800`01e82645 4889542410 mov qword ptr ,rdx
fffff800`01e8264a 4c89442418 mov qword ptr ,r8
fffff800`01e8264f 4cff2500000000jmp qword ptr
fffff800`01e82656 cc int 3
fffff800`01e82657 3a3e cmp bh,byte ptr
fffff800`01e82659 17 ???
fffff800`01e8265a 80f8ff cmp al,0FFh
ff250000000jmp qword ptr [nt!KeBugCheckEx+0x16 (fffff800`01e82656)
//跳转到相对偏址为0,即接下地址中储存值(8字节长)为地址的地方
fffff880-173e3acc
*/
RtlInitUnicodeString(&ustrDllFileName, L"\\??\\C:\\Windows\\System32\\ntdll.dll");
// 从 ntdll.dll 中获取 SSDT 函数索引号
ulSSDTFunctionIndex = GetSSDTFunctionIndex(ustrDllFileName, "ZwQueryDirectoryFile");
DbgPrint("ZwQueryDirectoryFile== ulSSDTFunctionIndex ====>%d", ulSSDTFunctionIndex);
ULONG dwtmp = 0;
ULONGLONG Ldwtmp = 0;
ULONGLONG addr = 0;
PULONG ServiceTableBase = NULL;
ServiceTableBase = (PULONG)(((PSYSTEM_SERVICE_DESCRIPTOR_TABLE)SSDTAddress)->ServiceTableBase);
DbgPrint("服务表基址ServiceTableBasenAddre======>%p", ServiceTableBase);
dwtmp = (ULONGLONG)(((PULONG32)((PSYSTEM_SERVICE_DESCRIPTOR_TABLE)SSDTAddress)->ServiceTableBase));//PULONG=PLONG32只能这样,64都不行.
ssdtfunaddr = &((PULONG32)((PSYSTEM_SERVICE_DESCRIPTOR_TABLE)SSDTAddress)->ServiceTableBase);
DbgPrint("存放原始偏址的地址ssdtfunaddr===%p", ssdtfunaddr);
oldaddr = dwtmp; //原来的偏移地址,没有
DbgPrint("原偏移地址值 oldaddr======>%p", oldaddr);
dwtmp = dwtmp >> 4;
g_pOldSSDTFunctionAddress = (PVOID)(dwtmp + (ULONGLONG)ServiceTableBase);//&0xFFFFFFF0; 原函数地址
DbgPrint("换算后的真实原函数地址g_pOldSSDTFunctionAddre======>%p", g_pOldSSDTFunctionAddress);
FuckKeBugCheckEx();
irql = WPOFFx64();
(ULONG)(*ssdtfunaddr) =GetOffsetAddress((ULONGLONG)KeBugCheckEx2, 11); //HOOK的关键步骤
//GetOffsetAddress((ULONGLONG)KeBugCheckEx2, 11);
WPONx64(irql);
//
// DbgPrint("KeBugCheckEx: %llx", (ULONGLONG)KeBugCheckEx);
DbgPrint("KeBugCheckEx: %llx", (ULONGLONG)KeBugCheckEx);
DbgPrint("KeBugCheckEx: %p\n", &KeBugCheckEx);
DbgPrint("KeBugCheckEx2: %llx", (ULONGLONG)KeBugCheckEx2);
//跳板函数的地址,与原SSDT应该较近
//DbgPrint("TEST======>%p\n", &((PULONG32)((PSYSTEM_SERVICE_DESCRIPTOR_TABLE)SSDTAddress)->ServiceTableBase));
//DbgPrint("TEST======>%p\n", &(((PULONG64)((PSYSTEM_SERVICE_DESCRIPTOR_TABLE)SSDTAddress)->ServiceTableBase)));
return TRUE;
}
大神,有个软件1分钟闪退,经测试是软件调用了terminateprocess关闭的,想通过hook这个来达到避免软件关闭的目的,是否可行? 13525372903 发表于 2023-5-9 17:10
大神,有个软件1分钟闪退,经测试是软件调用了terminateprocess关闭的,想通过hook这个来达到避免软件关闭 ...
这个肯定可以的了!
页:
[1]