win64 内核hook API

Posted 不会写代码的丝丽

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了win64 内核hook API相关的知识,希望对你有一定的参考价值。

前言

除了 SSDT hook和Inline hook外,内核还提供其他官方的API方便我们进行hook操作从而完成一些安全软件的研发等。

举例其中以下API函数

PsSetCreateProcessNotifyRoutine

typedef VOID (*PCREATE_PROCESS_NOTIFY_ROUTINE)(
    _In_ HANDLE ParentId,
    _In_ HANDLE ProcessId,
    _In_ BOOLEAN Create
    );

NTSTATUS PsSetCreateProcessNotifyRoutine(
  [in] PCREATE_PROCESS_NOTIFY_ROUTINE NotifyRoutine,
  [in] BOOLEAN                        Remove
);

PsSetCreateProcessNotifyRoutineEx


typedef VOID (*PCREATE_PROCESS_NOTIFY_ROUTINE_EX) (
    _Inout_ PEPROCESS Process,
    _In_ HANDLE ProcessId,
    _Inout_opt_ PPS_CREATE_NOTIFY_INFO CreateInfo
    );



NTSTATUS PsSetCreateProcessNotifyRoutineEx(
  [in] PCREATE_PROCESS_NOTIFY_ROUTINE_EX NotifyRoutine,
  [in] BOOLEAN                           Remove
);

两个函数都是用于注册一个回调监听进程的创建或者退出时调用NotifyRoutine,不同的是EX后缀函数不仅可以监听而且还可以控制创建的进程结果。

参数说明
NotifyRoutine : 回调函数
Remove : 如果为TRUE ,从系统回调表中删除回调函数的注册。FALSE为注册函数到回调函数表中。

示例

我们以PsSetCreateProcessNotifyRoutineEx 为示例具体讲解。

函数返回值

STATUS_SUCCESS 成功注册
STATUS_INVALID_PARAMETER 函数已经注册过,或者注册表已经达到上限不能注册
STATUS_ACCESS_DENIED 如果没有PE格式设置 IMAGE_DLLCHARACTERISTICS_FORCE_INTEGRITY标记,那么会抛出这个。

关于IMAGE_DLLCHARACTERISTICS_FORCE_INTEGRITY一些介绍可参阅:
/INTEGRITYCHECK(需要签名检查)

具体在编写驱动时加入以下标志:

我们最后看相关的回调函数

typedef VOID (*PCREATE_PROCESS_NOTIFY_ROUTINE_EX) (
    //可以通过这个获取一些进程的上下文信息
    _Inout_ PEPROCESS Process,
    //进程id
    _In_ HANDLE ProcessId,
    //如果这个参数为NULL表示程序退出。 不为NULL表示程序创建
    _Inout_opt_ PPS_CREATE_NOTIFY_INFO CreateInfo
    );

我编写一个相关案例实现效果如下:

(1) 打印创建/退出的进程名字
(2) 如果进程是计算器进程修改进程创建结果,使其创建失败

#include <Ntddk.h>

//系统隐藏API 只需要声明即可
extern "C" UCHAR * PsGetProcessImageFileName(PEPROCESS Process);

//设置的进程监听的回调函数
VOID MyProcessNotify(
	_Inout_ PEPROCESS Process,
	_In_ HANDLE ProcessId,
	_Inout_opt_ PPS_CREATE_NOTIFY_INFO CreateInfo
) 
	DbgPrint("[My learning] MyProcessNotify invoke \\r\\n");
	
	//获取进程的名称
	UCHAR* ImageFileName = PsGetProcessImageFileName(Process);
	
	//如果不为空证明创建进程
	if (CreateInfo != NULL)
	
		DbgPrint("[My learning] MyProcessNotify create process \\r\\n");
		DbgPrint("[My learning] MyProcessNotify   %s pid: %d   path:%wZ \\r\\n",
			ImageFileName,
			ProcessId,
			CreateInfo->ImageFileName
		);

		//比较当前的进程名称是否为计算器
		if (RtlCompareMemory("Calculator.exe", ImageFileName, sizeof "Calculator.exe"))
		
			DbgPrint("[My learning] MyProcessNotify create process \\r\\n");
			//控制创建进程的标志为失败标志
			CreateInfo->CreationStatus = STATUS_INVALID_PARAMETER;
		
	
	else 
		//进程为空 退出进程
		DbgPrint("[My learning] MyProcessNotify exit process %s \\r\\n", ImageFileName);
	



//这个函数被注册用于驱动卸载调用
VOID myUnload(
	struct _DRIVER_OBJECT* DriverObject
) 
	UNREFERENCED_PARAMETER(DriverObject);

	DbgPrint("[My learning]  drive myUnload \\r\\n");
	//一定设置卸载回调。不然一直会在注册表中
	PsSetCreateProcessNotifyRoutineEx(&MyProcessNotify, TRUE);




//驱动被加载的时候会调用此函数
extern "C"
NTSTATUS
DriverEntry(
	_In_ struct _DRIVER_OBJECT* DriverObject,
	_In_ PUNICODE_STRING    RegistryPath
)

	//如果你没有用到参数需要告诉系统。
	UNREFERENCED_PARAMETER(RegistryPath);
	//打印信息
	DbgPrint("[My learning]  drive loaded\\r\\n ");
	//注册监听回调
	NTSTATUS stat = PsSetCreateProcessNotifyRoutineEx(&MyProcessNotify, FALSE);
	//打印注册结果
	DbgPrint("[My learning]  PsSetCreateProcessNotifyRoutineEx ret %p \\r\\n", stat);

	DriverObject->DriverUnload = myUnload;

	return STATUS_SUCCESS;


开启调试后日志:

[My learning]  drive loaded
 [My learning]  PsSetCreateProcessNotifyRoutineEx ret 0000000000000000 
Suspending
[My learning] MyProcessNotify invoke 
[My learning] MyProcessNotify create process 
[My learning] MyProcessNotify   taskhostw.exe pid: 2964   path:\\??\\C:\\Windows\\system32\\taskhostw.exe 
[My learning] MyProcessNotify invoke 
[My learning] MyProcessNotify create process 
[My learning] MyProcessNotify   ApplicationFra pid: 2076   path:\\??\\C:\\Windows\\system32\\ApplicationFrameHost.exe 
[My learning] MyProcessNotify invoke 
[My learning] MyProcessNotify create process 
[My learning] MyProcessNotify   dllhost.exe pid: 348   path:\\??\\C:\\Windows\\system32\\DllHost.exe



[My learning] MyProcessNotify invoke 
[My learning] MyProcessNotify create process 
[My learning] MyProcessNotify   Calculator.exe pid: 3108   path:\\??\\C:\\Program Files\\WindowsApps\\Microsoft.WindowsCalculator_10.1506.19010.0_x64__8wekyb3d8bbwe\\Calculator.exe 
[My learning] MyProcessNotify create process 
[My learning] MyProcessNotify invoke 
[My learning] MyProcessNotify exit process Calculator.exe 

运行后你发现你永远无法打开计算器这个应用程序,并且会出输出所有的程序创建。

回调记录表

PsSetCreateProcessNotifyRoutineEx 会构造一张表存储相关。
我们反编译相关window内核文件C:\\Windows\\System32\\ntoskrnl.exe。




也就是我们清空这个表地址数据那么我们的hook计算器无法打开的操作讲失效.我们使用windbg尝试对应的操作

以上是关于win64 内核hook API的主要内容,如果未能解决你的问题,请参考以下文章

Win64与Win32的本质区别

IAT HOOK DEMO win32/win64

IAT HOOK DEMO win32/win64

求助WIN64 HOOK SSDT NtTerminateProcess

win 64 SSDT HOOK

求助WIN64 HOOK SSDT NtTerminateProcess