首页
社区
课程
招聘
[求助]通过PsSetCreateProcessNotifyRoutineEx回调拦截进程导致内核句柄泄漏
发表于: 2025-7-8 12:29 1357

[求助]通过PsSetCreateProcessNotifyRoutineEx回调拦截进程导致内核句柄泄漏

2025-7-8 12:29
1357

Win10 22h2系统上通过PsSetCreateProcessNotifyRoutineEx注册回调函数拦截特定进程的创建,正常情况下拦截正常,不存在句柄泄漏问题。


```c++

// 回调函数

VOID NotifyOnCreateProcess(_Inout_ PEPROCESS proc, _In_ HANDLE pid, _Inout_opt_ PPS_CREATE_NOTIFY_INFO create_info) {

    if (create_info) {

            PCSTR proc_name = (PCSTR)PsGetProcessImageFileName((proc));

            if (proc_name) {

                if (FilterProcessCmdLine(create_info->ParentProcessId, proc_name, proc_cmd)) {

                    create_info->CreationStatus = STATUS_ACCESS_DENIED;

                }

            }

     }

}

```

但是使用多线程压测时会发现内存占用异常上涨,使用poolmon监控可以发现Tag=Toke池的内存上涨后无法释放,怀疑存在token句柄泄漏的情况。

通过任务管理器查看句柄总数,未发现明显增长,说明不是用户态句柄泄漏导致的。

  • 执行前

  • 执行后


开启对象引用追踪,使用!obtrace追踪所有创建进程的主令牌,可以发现大量进程的token在进程销毁会仍然存在引用,导致对象无法释放,

同样的驱动在win11 24h2上使用poolmon未发现问题。



补充说明:直接使用命令行多进程执行的情况下,不存在泄漏,但是使用C++ std::thread在子线程中执行就会发生(和子线程数量无关)。



传播安全知识、拓宽行业人脉——看雪讲师团队等你加入!

最后于 2025-7-11 10:59 被mb_yorfaxrs编辑 ,原因:
收藏
免费 0
支持
分享
最新回复 (14)
雪    币: 2805
活跃值: (12062)
能力值: (RANK:385 )
在线值:
发帖
回帖
粉丝
2
过段时间会释放吗?
2025-7-8 13:24
0
雪    币: 0
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
3
不会,只有重启才行
2025-7-8 14:13
0
雪    币: 1762
活跃值: (1536)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
4
用InterlockedDecrement在回调中手动释放EPROCESS内Token的RefCnt呢?
2025-7-9 23:35
0
雪    币: 2805
活跃值: (12062)
能力值: (RANK:385 )
在线值:
发帖
回帖
粉丝
5
目前楼主这问题没遇到过. 开发过进程拦截驱动.用的minifilter的通信端口通信.正常过滤. 没遇到泄露问题. 
2025-7-10 10:15
0
雪    币: 892
活跃值: (14576)
能力值: ( LV12,RANK:322 )
在线值:
发帖
回帖
粉丝
6
会不会和自己的代码有关
2025-7-10 14:20
0
雪    币: 0
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
7
TurkeybraNC 用InterlockedDecrement在回调中手动释放EPROCESS内Token的RefCnt呢?
不是所有的拦截都有问题,那就没办法决定什么时候调用要InterlockedDecrement
2025-7-11 10:02
0
雪    币: 0
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
8
一半人生 会不会和自己的代码有关
VOID NotifyOnCreateProcess(_Inout_ PEPROCESS proc, _In_ HANDLE pid, _Inout_opt_ PPS_CREATE_NOTIFY_INFO create_info) {
    if (create_info)
    {
        PCSTR proc_name = (PCSTR)PsGetProcessImageFileName((proc));
        if (proc_name) {
            if (_stricmp(proc_name, "shutdown.exe") == 0) {
                UNREFERENCED_PARAMETER(pid);
                create_info->CreationStatus = STATUS_ACCESS_DENIED;
                return;
            }
        }
    }
}

精简了一下代码,DriverEntry负责注册,不包含其它代码,还是存在一样的问题

2025-7-11 12:19
0
雪    币: 0
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
9
目前发现一个规避方案:
使用PsSetCreateThreadNotifyRoutine注册一个线程回调,在回调中通知应用层结束当前线程。
这种情况下就不会出现泄漏问题,但是对系统性能有点影响。
2025-7-11 15:19
0
雪    币: 2805
活跃值: (12062)
能力值: (RANK:385 )
在线值:
发帖
回帖
粉丝
10
mb_yorfaxrs 目前发现一个规避方案: 使用PsSetCreateThreadNotifyRoutine注册一个线程回调,在回调中通知应用层结束当前线程。 这种情况下就不会出现泄漏问题,但是对系统性能有点影响。

虽没试过.尝试下通过 EPROCESS 得到对应句柄.关闭这个句柄哪

伪代码:

HANDLE hProcessHandle = (HANDLE)-1;
    Status = ObOpenObjectByPointer(
        pEprocess,
        OBJ_KERNEL_HANDLE,
        0,
        0,
        *PsProcessType,
        KernelMode,
        &hProcessHandle
    );
    if (NT_SUCCESS(Status))
    {
        ZwClose(hProcessHandle);
        xxxx...
    }

2025-7-11 15:29
0
雪    币: 1762
活跃值: (1536)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
11
挂个内核调试器步出回调函数看一下会不会调用PsTerminateProcess,进程的清理是在这里完成的
2025-7-11 16:10
0
雪    币: 0
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
12
TkBinary 虽没试过.尝试下通过 EPROCESS 得到对应句柄.关闭这个句柄哪伪代码:HANDLE hProcessHandle = (HANDLE)-1; ...
试过了,还是一样的问题
2025-7-16 10:30
0
雪    币: 0
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
13
TurkeybraNC 挂个内核调试器步出回调函数看一下会不会调用PsTerminateProcess,进程的清理是在这里完成的
之前特意看过,shift+f11走的时候会调用到
2025-7-16 10:37
0
雪    币: 1762
活跃值: (1536)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
14
mb_yorfaxrs 之前特意看过,shift+f11走的时候会调用到
能给下内核详细版本号和测试程序源码吗,一直没有复现成功
2025-8-6 17:49
0
雪    币: 179
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
15
mb_yorfaxrs 之前特意看过,shift+f11走的时候会调用到
咋样了,解决没
2025-11-13 23:13
0
游客
登录 | 注册 方可回帖
返回