好友
阅读权限10
听众
最后登录1970-1-1
|
/*此程序于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 [rsp+8],rcx
fffff800`01e82645 4889542410 mov qword ptr [rsp+10h],rdx
fffff800`01e8264a 4c89442418 mov qword ptr [rsp+18h],r8
fffff800`01e8264f 4c894c2420 mov qword ptr [rsp+20h],r9
fffff800`01e82654 9c pushfq
*/
/*lkd> u KeBugCheckEx //HOOK以后的
nt!KeBugCheckEx:
fffff800`01e82640 48894c2408 mov qword ptr [rsp+8],rcx
fffff800`01e82645 4889542410 mov qword ptr [rsp+10h],rdx
fffff800`01e8264a 4c89442418 mov qword ptr [rsp+18h],r8
fffff800`01e8264f 4cff2500000000 jmp qword ptr [nt!KeBugCheckEx+0x16 (fffff800`01e82656)]
fffff800`01e82656 cc int 3
fffff800`01e82657 3a3e cmp bh,byte ptr [rsi]
fffff800`01e82659 17 ???
fffff800`01e8265a 80f8ff cmp al,0FFh
ff250000000 jmp 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)[ulSSDTFunctionIndex]);//PULONG=PLONG32只能这样,64都不行.
ssdtfunaddr = &((PULONG32)((PSYSTEM_SERVICE_DESCRIPTOR_TABLE)SSDTAddress)->ServiceTableBase)[ulSSDTFunctionIndex];
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)[ulSSDTFunctionIndex]);
//DbgPrint("TEST======>%p\n", &(((PULONG64)((PSYSTEM_SERVICE_DESCRIPTOR_TABLE)SSDTAddress)->ServiceTableBase)[ulSSDTFunctionIndex]));
return TRUE;
}
|
|
发帖前要善用【论坛搜索】功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。 |
|
|
|
|