打造自己的HOOK引擎 之一 --- SSDT HOOK引擎
SSDT HOOK已经是老生常谈的话题了,这里我就不对其进行介绍了,其实HOOK技术已经被大牛们分析的淋漓尽致,无以复加了,我也只是个初学者,失误之处,还望大牛们多多指教
读者可以通过后面的参考连接得到更多的关于SSDT HOOK的信息
我就相当于在这里对论坛的关于SSDT的精华贴做个总结了 呵呵
【原创】扫盲贴,HOOK SSDT 短文一篇。
【原创】分享比较完整的ROOTKIT DEMO! 原来Shadow Hook和SSDT Hook一样容易!
【原创】SSDT Hook的妙用-对抗ring0 inline hook
【原创】寻找原始表,恢复 ssdt 表
【原创】RootKit hook之[二] SSDT hook
【原创】用DDDK编写驱动,修改SSDT表HOOK NTDebugActiveProcess函数
【转帖】城里城外看SSDT
关于HOOK的文章实在是太多了,但是不同的文章由于作者的不同,导致文章的写作风格不同,代码的风格也各不相同,这样就导致了同样的技术,不同的作者用代码表现出来的形式却大相径庭,这样对我们初学者来讲实在是很不方便,于是便有了打造自己的HOOK引擎的想法,将技术细节封装起来,因为这个本来就不用去修改,需要修改的仅仅是用户自定义的HOOK例程
这个也就是我的HOOK引擎的基本思想,将HOOK的具体实现封装在引擎中,用户想HOOK某个函数时,不用去想HOOK的技术细节了,直接编写自己的HOOK函数然后调用引擎提供的某个接口即可
因为是第一次写,就写个最简单的,SSDT的HOOK
譬如如果用户想把NtOpenProcess HOOK成自己的MyNtOpenProcess
用户只需要在DriverEntry中调用HookService((ULONG)ZwOpenProcess, (ULONG)MyNtOpenProcess)
然后编写自己的钩子函数即可 接口很简单也易于实现
这里是个调用的例子
// Unload例程 卸载钩子
VOID Unload(IN PDRIVER_OBJECT DriverObject)
{
KdPrint(("Unload Routine.\n"));
UnHookService((ULONG)ZwSetInformationFile);
UnHookService((ULONG)ZwOpenProcess);
}
// DriverEntry例程 初始化并安装钩子
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath)
{
DriverObject->DriverUnload = Unload;
InitServicesTable();
HookService((ULONG)ZwSetInformationFile, (ULONG)MyZwSetInformationFile);
HookService((ULONG)ZwOpenProcess, (ULONG)MyNtOpenProcess);
return STATUS_SUCCESS;
}
然后只需要关注自己的函数了,如下编写了两个示例,第一个例子HOOK了ZwSetInformationFile保护test.txt文件不被删除,第二个例子HOOK了NtOpenProcess保护PID大于1000的进程不被结束,代码都是参考前人的,我只是在这里做个总结罢了
// 定义HOOK的函数原型
typedef
NTSTATUS
(__stdcall *ZWSETINFORMATIONFILE)(IN HANDLE FileHandle,
OUT PIO_STATUS_BLOCK IoStatusBlock,
IN PVOID FileInformation,
IN ULONG Length,
IN FILE_INFORMATION_CLASS FileInformationClass);
typedef
NTSTATUS
(__stdcall *NTOPENPROCESS)( OUT PHANDLE ProcessHandle,
IN ACCESS_MASK AccessMask,
IN POBJECT_ATTRIBUTES ObjectAttributes,
IN PCLIENT_ID ClientId);
// 对于ntddk.h中未定义的函数
// 可以根据<<Undocument>>一书在这里给出定义
NTSYSAPI
NTSTATUS
NTAPI
ZwOpenProcess( OUT PHANDLE ProcessHandle,
IN ACCESS_MASK AccessMask,
IN POBJECT_ATTRIBUTES ObjectAttributes,
IN PCLIENT_ID ClientId);
// ==============================================================
// 用户自定义HOOK例程
NTSTATUS MyZwSetInformationFile(IN HANDLE FileHandle,
OUT PIO_STATUS_BLOCK IoStatusBlock,
IN PVOID FileInformation,
IN ULONG Length,
IN FILE_INFORMATION_CLASS FileInformationClass)
{
PFILE_OBJECT pFileObject;
// 在OldServiceAddressTable中取出原服务函数地址
ZWSETINFORMATIONFILE OldZwSetInformationFile =
(ZWSETINFORMATIONFILE)OldServiceAddressTable[SERVICE_ID(ZwSetInformationFile)];
NTSTATUS ret = ObReferenceObjectByHandle(FileHandle,
GENERIC_READ,
*IoFileObjectType,
KernelMode,
(PVOID*)&pFileObject,
0);
if(NT_SUCCESS(ret))
{
KdPrint(("%S opened.\n", pFileObject->FileName.Buffer));
if (wcsstr(pFileObject->FileName.Buffer, L"test.txt"))
{
KdPrint(("test.txt opened. Deny it.\n"));
return STATUS_ACCESS_DENIED;
}
}
[color=red]ObDereferenceObject(pFileObject);[/color]
// 调用原服务函数
return OldZwSetInformationFile( FileHandle, IoStatusBlock, FileInformation,
Length, FileInformationClass);
}
NTSTATUS MyNtOpenProcess(OUT PHANDLE ProcessHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes,
IN PCLIENT_ID ClientId )
{
NTSTATUS rc;
ULONG PID;
[color=red]
KPROCESSOR_MODE PreMode;
[/color]
NTOPENPROCESS OldNtOpenProcess =
(NTOPENPROCESS)OldServiceAddressTable[SERVICE_ID(ZwOpenProcess)];
[color=red]
PreMode = ExGetPreviousMode();
if(PreMode != KernelMode)
{
__try
{
ProbeForRead(ClientId, sizeof(CLIENT_ID), sizeof(ULONG));
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
return GetExceptionCode();
}
}
[/color]
if(ClientId != NULL)
{
PID = (ULONG)ClientId->UniqueProcess;
if(PID > 1000)
{
return STATUS_ACCESS_DENIED;
}
}
return OldNtOpenProcess(ProcessHandle, DesiredAccess, ObjectAttributes, ClientId);
}
上面的代码都是对前人的代码进行了一些整合而得到的,仅仅是对引擎做个测试而已
然后说明一点,就是HookService()的第一个参数都应该是以Zw开头的函数,因为代码是根据这个函数来计算服务ID的
还有就是在调用HookService()之前应该先调用InitServicesTalbe()来对SSDT进行一次性的保存,避免后面多次HOOK就要保存多次
附件中是全部代码 写的很烂 还望大大们批评指正。
[课程]FART 脱壳王!加量不加价!FART作者讲授!
上传的附件: