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

如何用C++蜜罐检测Windows中修改/删除特定文件的进程?

检测修改/删除特定诱饵文件的进程(Windows C++实现)

方法一:使用ETW(用户态实现,无需驱动)

ETW(Event Tracing for Windows)可捕获内核级文件操作事件,包含触发操作的进程ID,通过该ID可反向获取进程具体信息,适合快速搭建测试环境。

核心步骤

  • 启用Microsoft-Windows-Kernel-File事件提供者,捕获FileDelete(删除)和FileWrite(修改)事件。
  • 在事件回调中解析事件数据,提取目标文件路径与进程ID。
  • 通过OpenProcess和GetModuleFileNameEx将进程ID转换为进程路径/名称。

代码片段

#include <windows.h>
#include <evntrace.h>
#include <evntcons.h>
#include <psapi.h>
#include <iostream>
#include <string>

#pragma comment(lib, "advapi32.lib")
#pragma comment(lib, "psapi.lib")

// ETW事件回调函数
VOID WINAPI EtwEventCallback(PEVENT_RECORD pEventRecord) {
    // 匹配Microsoft-Windows-Kernel-File提供者GUID
    const GUID fileProviderGuid = {0x3D6FA8D0, 0xFE05, 0x11D0, {0x9D, 0xDA, 0x00, 0xC0, 0x4F, 0xC3, 0x35, 0x8C}};
    if (pEventRecord->EventHeader.ProviderId != fileProviderGuid) return;

    DWORD processId = pEventRecord->EventHeader.ProcessId;
    EVENT_DATA_DESCRIPTOR dataDesc;
    EventDataDescGet(&dataDesc, pEventRecord->UserData, pEventRecord->UserDataLength);
    wchar_t* filePath = (wchar_t*)dataDesc.DataPtr;

    // 检查是否为目标诱饵文件
    if (wcscmp(filePath, L"C:\\HoneyPot\\bait.txt") != 0) return;

    // 获取进程路径
    HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processId);
    if (hProcess == NULL) return;

    wchar_t processPath[MAX_PATH];
    if (GetModuleFileNameExW(hProcess, NULL, processPath, MAX_PATH)) {
        std::wcout << L"检测到操作诱饵文件的进程:" << processPath << L" (PID: " << processId << L")" << std::endl;
    }
    CloseHandle(hProcess);
}

int main() {
    TRACEHANDLE sessionHandle = 0;
    ULONG bufferSize = sizeof(EVENT_TRACE_PROPERTIES) + MAX_PATH * sizeof(WCHAR);
    EVENT_TRACE_PROPERTIES* pSessionProps = (EVENT_TRACE_PROPERTIES*)malloc(bufferSize);
    ZeroMemory(pSessionProps, bufferSize);

    pSessionProps->Wnode.BufferSize = bufferSize;
    pSessionProps->Wnode.Flags = WNODE_FLAG_TRACED_GUID;
    pSessionProps->EnableFlags = EVENT_TRACE_FLAG_FILE_IO;
    wcscpy_s(pSessionProps->LoggerName, MAX_PATH, L"HoneyPotMonitor");

    // 创建ETW会话
    if (StartTrace(&sessionHandle, pSessionProps->LoggerName, pSessionProps) != ERROR_SUCCESS) {
        std::cerr << "启动ETW会话失败" << std::endl;
        free(pSessionProps);
        return 1;
    }

    // 启用文件操作事件提供者
    if (EnableTraceEx2(sessionHandle, (LPGUID)&fileProviderGuid, EVENT_CONTROL_CODE_ENABLE_PROVIDER, TRACE_LEVEL_VERBOSE, 0, 0, 0, NULL) != ERROR_SUCCESS) {
        std::cerr << "启用事件提供者失败" << std::endl;
        ControlTrace(sessionHandle, pSessionProps->LoggerName, pSessionProps, EVENT_TRACE_CONTROL_STOP);
        free(pSessionProps);
        return 1;
    }

    // 开始处理事件
    EVENT_TRACE_LOGFILE traceLog = {0};
    traceLog.LoggerName = pSessionProps->LoggerName;
    traceLog.ProcessTraceMode = PROCESS_TRACE_MODE_REAL_TIME | PROCESS_TRACE_MODE_EVENT_RECORD;
    traceLog.EventRecordCallback = EtwEventCallback;

    std::cout << "监控已启动,按任意键退出..." << std::endl;
    ProcessTrace(&traceLog, 1, NULL, NULL);

    // 清理资源
    ControlTrace(sessionHandle, pSessionProps->LoggerName, pSessionProps, EVENT_TRACE_CONTROL_STOP);
    free(pSessionProps);
    return 0;
}

方法二:使用Minifilter驱动(内核态实现,高可靠性)

Minifilter是文件系统过滤驱动,可在文件操作执行前/后拦截事件,直接获取触发进程信息,无遗漏,适合精准检测勒索软件行为。

核心步骤

  • 实现Minifilter驱动,注册PreOperationCallback回调函数。
  • 在回调中检查目标文件路径,匹配诱饵文件。
  • 通过IoGetCurrentProcess获取当前进程对象,PsGetProcessImageFileName获取进程名称。

代码片段(驱动核心部分)

#include <fltKernel.h>

PFLT_FILTER gFilterHandle;

// 预操作回调,拦截文件修改/删除操作
FLT_PREOP_CALLBACK_STATUS PreOperationCallback(
    _Inout_ PFLT_CALLBACK_DATA Data,
    _In_ PCFLT_RELATED_OBJECTS FltObjects,
    _Flt_CompletionContext_Outptr_ PVOID* CompletionContext
) {
    UNREFERENCED_PARAMETER(CompletionContext);

    // 过滤目标操作类型:写入、删除、修改文件信息
    if (Data->Iopb->MajorFunction != IRP_MJ_WRITE && 
        Data->Iopb->MajorFunction != IRP_MJ_DELETE &&
        Data->Iopb->MajorFunction != IRP_MJ_SET_INFORMATION) {
        return FLT_PREOP_SUCCESS_NO_CALLBACK;
    }

    // 获取文件路径
    UNICODE_STRING filePath;
    NTSTATUS status = FltGetFileNameInformation(Data, FLT_FILE_NAME_NORMALIZED | FLT_FILE_NAME_QUERY_DEFAULT, &filePath);
    if (!NT_SUCCESS(status)) return FLT_PREOP_SUCCESS_NO_CALLBACK;

    // 匹配诱饵文件
    if (RtlCompareUnicodeString(&filePath, &(UNICODE_STRING)RTL_CONSTANT_STRING(L"C:\\HoneyPot\\bait.txt"), TRUE) == 0) {
        PEPROCESS process = IoGetCurrentProcess();
        CHAR processName[16];
        PsGetProcessImageFileName(process, processName, sizeof(processName));
        DbgPrint("检测到操作诱饵文件的进程:%s\n", processName);
    }

    FltReleaseFileNameInformation(&filePath);
    return FLT_PREOP_SUCCESS_NO_CALLBACK;
}

// 驱动入口
NTSTATUS DriverEntry(_In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath) {
    UNREFERENCED_PARAMETER(RegistryPath);

    FLT_REGISTRATION filterRegistration = {
        sizeof(FLT_REGISTRATION),
        FLT_REGISTRATION_VERSION,
        0,
        NULL,
        {
            { IRP_MJ_WRITE, 0, PreOperationCallback, NULL },
            { IRP_MJ_DELETE, 0, PreOperationCallback, NULL },
            { IRP_MJ_SET_INFORMATION, 0, PreOperationCallback, NULL },
            { IRP_MJ_OPERATION_END }
        },
        NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
    };

    NTSTATUS status = FltRegisterFilter(DriverObject, &filterRegistration, &gFilterHandle);
    if (NT_SUCCESS(status)) {
        status = FltStartFiltering(gFilterHandle);
        if (!NT_SUCCESS(status)) FltUnregisterFilter(gFilterHandle);
    }
    return status;
}

// 驱动卸载
NTSTATUS DriverUnload(_In_ FLT_FILTER_UNLOAD_FLAGS Flags) {
    UNREFERENCED_PARAMETER(Flags);
    FltUnregisterFilter(gFilterHandle);
    return STATUS_SUCCESS;
}

方法对比

  • ETW方法:用户态实现,无需驱动签名,开发成本低;但可能丢失少量事件,无法捕获内核态直接操作文件的行为。
  • Minifilter方法:内核态实现,检测无遗漏,覆盖所有文件操作场景;但需要驱动签名(测试环境可开启测试签名模式),开发复杂度高,需掌握Windows内核编程知识。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 20:13:14