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

如何通过AuthzReportSecurityEvent为安全日志添加Data Name字段

问题描述

我写了一段用AuthzReportSecurityEvent生成安全日志的C++代码,现在需要给日志添加特定信息,但找不到创建“Data Name”字段的方法,相关资料极少,想在日志对应位置加上这个信息。我试过AuthzReportSecurityEventFromParams函数,但缺乏相关文档,不确定是不是更优方案。现有代码如下:

#include <stdio.h>
#include <iostream>
#include <string>
#include <strsafe.h>
#include <windows.h>
#include <Authz.h>
#include <Ntsecapi.h>

#pragma comment(lib,"Authz.lib")
#pragma comment(lib,"Advapi32.lib")

BOOL SetPrivilege(
    HANDLE hToken,          // access token handle
    LPCTSTR lpszPrivilege,  // name of privilege to enable/disable
    BOOL bEnablePrivilege   // to enable or disable privilege
)
{
    TOKEN_PRIVILEGES tp;
    LUID luid;

    if (!LookupPrivilegeValue(
        NULL,            // lookup privilege on local system
        lpszPrivilege,   // privilege to lookup
        &luid))        // receives LUID of privilege
    {
        printf("LookupPrivilegeValue error: %u\n", GetLastError());
        return FALSE;
    }

    tp.PrivilegeCount = 1;
    tp.Privileges[0].Luid = luid;
    if (bEnablePrivilege)
        tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
    else
        tp.Privileges[0].Attributes = 0;

    // Enable the privilege or disable all privileges.
    if (!AdjustTokenPrivileges(
        hToken,
        FALSE,
        &tp,
        sizeof(TOKEN_PRIVILEGES),
        (PTOKEN_PRIVILEGES)NULL,
        (PDWORD)NULL))
    {
        printf("AdjustTokenPrivileges error: %u\n", GetLastError());
        return FALSE;
    }

    if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)
    {
        printf("The token does not have the specified privilege.\n");
        return FALSE;
    }

    printf("Get the specified privilege!\n");
    return TRUE;
}

int main(int argc, const char* argv[])
{
    BOOL bResult = TRUE;
    DWORD event_id = 4624;
    AUTHZ_SECURITY_EVENT_PROVIDER_HANDLE hEventProvider = NULL;
    PAUDIT_PARAMS p;
    std::string Source_Name = "Test security audit";
    std::wstring ws;
    std::string pbuf = "What is your purpose ?";
    std::wstring ws_buf;
    int return_code = 0;
    int i = 0;

    HANDLE token;
    HANDLE hevent_source;
    ws.assign(Source_Name.begin(), Source_Name.end());
    ws_buf.assign(pbuf.begin(), pbuf.end());

    if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token))
        return FALSE;

    SetPrivilege(token, L"SeAuditPrivilege", true);

    AUTHZ_SOURCE_SCHEMA_REGISTRATION ar;
    memset(&ar, 0, sizeof(ar));
    ar.dwFlags = AUTHZ_ALLOW_MULTIPLE_SOURCE_INSTANCES;
    ar.szEventSourceName = &ws[0];
    ar.szEventMessageFile = &ws_buf[0];
    ar.szEventSourceXmlSchemaFile = NULL;
    ar.szEventAccessStringsFile = &ws_buf[0];
    ar.szExecutableImagePath = NULL;

    AuthzInstallSecurityEventSource(0, &ar);

    bResult = AuthzRegisterSecurityEventSource(0, ws.c_str(), &hEventProvider);
    int err = GetLastError();
    if (!bResult)
    {
        printf("AuthzRegisterSecurityEventSource failed, error is %d\n", err);
        return_code = -1;
    }

    SID id;
    if (hEventProvider)
    {
        // Generate the audit.
        while (i < 10) {
            bResult = AuthzReportSecurityEvent(
                APF_AuditSuccess,
                hEventProvider,
                event_id,
                NULL,
                3,
                APT_String, L"Jay Hamlin",
                APT_String, L"March 21, 1960",
                APT_Ulong, 45);
            int err1 = GetLastError();
            if (!bResult)
            {
                printf("AuthzReportSecurityEvent failed, error is %d\n", err1);
                return_code = -2;
                break;
            }

            i++;
        }

        AuthzUnregisterSecurityEventSource(0, &hEventProvider);
        AuthzUninstallSecurityEventSource(0, &ws[0]);
    }
    std::cout << "Exit  : " << return_code << std::endl;
    getchar();
}
解决方案

1. 核心问题说明

AuthzReportSecurityEvent是可变参数接口,只能按顺序传递参数值,无法指定参数的名称(即你需要的“Data Name”字段)。要实现带命名字段的安全日志,必须使用AuthzReportSecurityEventFromParams——这是专门为传递带名称的审计参数设计的接口。

2. 实现步骤

定义带名称的审计参数

使用AUDIT_PARAMS结构体数组,每个元素指定参数的类型、名称和值:

AUDIT_PARAMS auditParams[] = {
    { APT_String, L"UserName", L"Jay Hamlin" },
    { APT_String, L"BirthDate", L"March 21, 1960" },
    { APT_Ulong, L"EmployeeID", (PVOID)45 }
};

替换日志生成函数

用AuthzReportSecurityEventFromParams替代原有的AuthzReportSecurityEvent,传入定义好的参数数组:

bResult = AuthzReportSecurityEventFromParams(
    APF_AuditSuccess,
    hEventProvider,
    event_id,
    NULL,
    _countof(auditParams),
    auditParams
);

3. 注意事项

  • AUDIT_PARAMS的Name字段必须是宽字符串(LPCWSTR),参数值的类型要和Type字段匹配(例如APT_Ulong对应PVOID类型的数值指针)。
  • 若需要日志查看工具完美识别命名字段,需为事件源注册对应的XML Schema(设置AUTHZ_SOURCE_SCHEMA_REGISTRATION的szEventSourceXmlSchemaFile字段),否则部分工具可能仅显示原始参数值。
  • SeAuditPrivilege权限的启用逻辑和原代码保持一致即可。

完整修改后的代码

#include <stdio.h>
#include <iostream>
#include <string>
#include <strsafe.h>
#include <windows.h>
#include <Authz.h>
#include <Ntsecapi.h>

#pragma comment(lib,"Authz.lib")
#pragma comment(lib,"Advapi32.lib")

BOOL SetPrivilege(
    HANDLE hToken,          // access token handle
    LPCTSTR lpszPrivilege,  // name of privilege to enable/disable
    BOOL bEnablePrivilege   // to enable or disable privilege
)
{
    TOKEN_PRIVILEGES tp;
    LUID luid;

    if (!LookupPrivilegeValue(
        NULL,            // lookup privilege on local system
        lpszPrivilege,   // privilege to lookup
        &luid))        // receives LUID of privilege
    {
        printf("LookupPrivilegeValue error: %u\n", GetLastError());
        return FALSE;
    }

    tp.PrivilegeCount = 1;
    tp.Privileges[0].Luid = luid;
    if (bEnablePrivilege)
        tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
    else
        tp.Privileges[0].Attributes = 0;

    // Enable the privilege or disable all privileges.
    if (!AdjustTokenPrivileges(
        hToken,
        FALSE,
        &tp,
        sizeof(TOKEN_PRIVILEGES),
        (PTOKEN_PRIVILEGES)NULL,
        (PDWORD)NULL))
    {
        printf("AdjustTokenPrivileges error: %u\n", GetLastError());
        return FALSE;
    }

    if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)
    {
        printf("The token does not have the specified privilege.\n");
        return FALSE;
    }

    printf("Get the specified privilege!\n");
    return TRUE;
}

int main(int argc, const char* argv[])
{
    BOOL bResult = TRUE;
    DWORD event_id = 4624;
    AUTHZ_SECURITY_EVENT_PROVIDER_HANDLE hEventProvider = NULL;
    std::string Source_Name = "Test security audit";
    std::wstring ws;
    std::string pbuf = "What is your purpose ?";
    std::wstring ws_buf;
    int return_code = 0;
    int i = 0;

    HANDLE token;
    ws.assign(Source_Name.begin(), Source_Name.end());
    ws_buf.assign(pbuf.begin(), pbuf.end());

    if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token))
        return FALSE;

    SetPrivilege(token, L"SeAuditPrivilege", true);

    AUTHZ_SOURCE_SCHEMA_REGISTRATION ar;
    memset(&ar, 0, sizeof(ar));
    ar.dwFlags = AUTHZ_ALLOW_MULTIPLE_SOURCE_INSTANCES;
    ar.szEventSourceName = &ws[0];
    ar.szEventMessageFile = &ws_buf[0];
    ar.szEventSourceXmlSchemaFile = NULL;
    ar.szEventAccessStringsFile = &ws_buf[0];
    ar.szExecutableImagePath = NULL;

    AuthzInstallSecurityEventSource(0, &ar);

    bResult = AuthzRegisterSecurityEventSource(0, ws.c_str(), &hEventProvider);
    int err = GetLastError();
    if (!bResult)
    {
        printf("AuthzRegisterSecurityEventSource failed, error is %d\n", err);
        return_code = -1;
    }

    if (hEventProvider)
    {
        // 定义带Data Name的审计参数
        AUDIT_PARAMS auditParams[] = {
            { APT_String, L"UserName", L"Jay Hamlin" },
            { APT_String, L"BirthDate", L"March 21, 1960" },
            { APT_Ulong, L"EmployeeID", (PVOID)45 }
        };

        // Generate the audit.
        while (i < 10) {
            bResult = AuthzReportSecurityEventFromParams(
                APF_AuditSuccess,
                hEventProvider,
                event_id,
                NULL,
                _countof(auditParams),
                auditParams
            );
            int err1 = GetLastError();
            if (!bResult)
            {
                printf("AuthzReportSecurityEventFromParams failed, error is %d\n", err1);
                return_code = -2;
                break;
            }

            i++;
        }

        AuthzUnregisterSecurityEventSource(0, &hEventProvider);
        AuthzUninstallSecurityEventSource(0, &ws[0]);
    }
    std::cout << "Exit  : " << return_code << std::endl;
    getchar();
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 01:45:01