You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何拦截特定程序的所有系统调用?含Windows/Linux场景咨询

针对特定程序的用户态系统调用拦截方案(Windows x86-64)

针对你的需求——拦截特定程序的系统调用(如NtCreateFile)且无需内核驱动,以下是几种可行的用户态方案,完全适配你能控制目标文件、拥有管理员权限的场景:

一、Hook NTDLL导出的系统调用函数(最推荐)

Windows下所有用户态系统调用最终都会路由到ntdll.dll导出的NtXXX/ZwXXX函数(比如fopen最终会调用NtCreateFile)。Hook这些导出函数可以覆盖所有来源的系统调用(包括标准库、第三方库或你自己写的直接syscall)。

实现步骤:

  1. 编写Hook DLL:使用成熟的Hook库(如MinHook、EasyHook)实现对NtCreateFile的拦截。示例代码(MinHook):
    #include <windows.h>
    #include <ntstatus.h>
    #include <winternl.h>
    #include <MinHook.h>
    #include <wchar.h>
    
    // 定义原始函数指针
    typedef NTSTATUS(NTAPI* pNtCreateFile)(
        PHANDLE FileHandle,
        ACCESS_MASK DesiredAccess,
        POBJECT_ATTRIBUTES ObjectAttributes,
        PIO_STATUS_BLOCK IoStatusBlock,
        PLARGE_INTEGER AllocationSize,
        ULONG FileAttributes,
        ULONG ShareAccess,
        ULONG CreateDisposition,
        ULONG CreateOptions,
        PVOID EaBuffer,
        ULONG EaLength
    );
    
    pNtCreateFile OriginalNtCreateFile = NULL;
    
    // Hook函数:处理日志/拦截逻辑
    NTSTATUS NTAPI HookedNtCreateFile(
        PHANDLE FileHandle,
        ACCESS_MASK DesiredAccess,
        POBJECT_ATTRIBUTES ObjectAttributes,
        PIO_STATUS_BLOCK IoStatusBlock,
        PLARGE_INTEGER AllocationSize,
        ULONG FileAttributes,
        ULONG ShareAccess,
        ULONG CreateDisposition,
        ULONG CreateOptions,
        PVOID EaBuffer,
        ULONG EaLength
    ) {
        // 日志记录:打印目标文件名
        if (ObjectAttributes && ObjectAttributes->ObjectName) {
            wprintf(L"[LOG] NtCreateFile called: %wZ\n", ObjectAttributes->ObjectName);
        }
    
        // 可选:拦截操作(返回拒绝访问)
        // return STATUS_ACCESS_DENIED;
    
        // 调用原始函数继续执行
        return OriginalNtCreateFile(FileHandle, DesiredAccess, ObjectAttributes, IoStatusBlock, AllocationSize, FileAttributes, ShareAccess, CreateDisposition, CreateOptions, EaBuffer, EaLength);
    }
    
    BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) {
        switch (ul_reason_for_call) {
        case DLL_PROCESS_ATTACH:
            // 初始化MinHook并创建Hook
            if (MH_Initialize() != MH_OK) break;
            OriginalNtCreateFile = (pNtCreateFile)GetProcAddress(GetModuleHandle(L"ntdll.dll"), "NtCreateFile");
            if (MH_CreateHook(OriginalNtCreateFile, HookedNtCreateFile, (LPVOID*)&OriginalNtCreateFile) == MH_OK) {
                MH_EnableHook(OriginalNtCreateFile);
            }
            break;
        case DLL_PROCESS_DETACH:
            // 清理Hook
            MH_DisableHook(OriginalNtCreateFile);
            MH_Uninitialize();
            break;
        }
        return TRUE;
    }
    
  2. 注入DLL到目标进程:
    • 使用CreateProcess以CREATE_SUSPENDED模式启动目标程序,通过WriteProcessMemory写入DLL路径,再调用CreateRemoteThread加载DLL,最后恢复进程运行。
    • 也可使用现成的注入工具(如Process Hacker的注入功能)。

优缺点:

  • ✅ 覆盖所有系统调用来源,稳定性高
  • ✅ 实现简单,依赖成熟库减少出错
  • ❌ 需要注入到目标进程

二、修改目标PE文件的导入表

既然你能完全控制目标文件,可直接修改其PE导入表,将ntdll.dll的NtCreateFile引用重定向到你自定义的函数,无需运行时注入。

实现步骤:

  1. 解析PE结构:使用Win32 API或PE解析库(如PELib)读取目标.exe的导入表,找到ntdll.dll下的NtCreateFile条目。
  2. 重定向导入:将该条目的导入地址指向你编写的DLL中的自定义NtCreateFile函数,同时确保目标程序会加载你的DLL(可通过添加导入表条目实现)。
  3. 自定义函数逻辑:在你的DLL中实现日志/拦截逻辑,可选择调用原始NtCreateFile或直接返回。

优缺点:

  • ✅ 无需注入,目标程序启动即生效
  • ✅ 无运行时注入的权限风险
  • ❌ 需要处理PE结构细节,若目标程序有反篡改保护可能失效

三、VEH(向量异常处理)Hook

利用VEH捕获指令执行异常,动态修改内存中的系统调用指令实现拦截,适合不想修改导入表或注入DLL的场景(需管理员权限)。

实现思路:

  1. 注册VEH:在目标进程中注册向量异常处理函数。
  2. 修改指令触发异常:将ntdll.dll中NtCreateFile开头的指令替换为int 3(断点指令)。
  3. 异常处理:当触发异常时,在VEH中保存上下文,执行日志/拦截逻辑,恢复原始指令,执行原始函数,再将指令改回int 3以持续拦截。

优缺点:

  • ✅ 无需修改导入表或注入DLL(可通过远程线程修改内存)
  • ❌ 实现复杂,需处理多线程指令修改冲突,稳定性不如前两种方案

针对你的示例代码的验证

你提供的fopen示例最终会通过C标准库调用CreateFileW,再路由到NtCreateFile。使用上述任意方案,都能捕获到该NtCreateFile调用,实现日志记录或拦截文件创建操作。


内容的提问来源于stack exchange,提问作者anom907 zat

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 22:02:31