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的主要内容,如果未能解决你的问题,请参考以下文章