win32 - 写入安全日志(AuthzRegisterSecurityEventSource和AuthzReportSecurityEvent)
微软文档介绍说,
安全日志在其他两个重要方面与其他日志不同。首先,在默认配置中,它受到强大的访问控制列表(ACL)和特权检查的保护,这将可以读取其内容的个人的范围限制为本地系统,管理员和安全特权的持有者。其次,也是最重要的一点,只允许一个实体(本地安全机构(LSA))写入安全日志。这实际上意味着,每次尝试为安全日志调用RegisterEventSource API时,即使您以本地系统身份运行,也会收到ACCESS_DENIED错误!这种设计可确保安全日志仅包含来自受信任来源的信息。
在Windows Server 2003中,安全日志写访问限制在某种程度上得到了放松,而没有通过引入一组特殊的API来更改基本设计(请参见图2)。这些API在内部使用本地过程调用(LPC)与LSA进行交互,指示LSA代表应用程序生成审核日志。该机制优雅而简单。
首先,应用程序通过调用AuthzRegisterSecurityEventSource向LSA注册安全事件源句柄。此API唯一感兴趣的参数是事件源的名称,该名称可以是几乎任何内容,并受一些限制。例如,它不能命名为“ Security”,因为该名称保留供系统使用。在以下步骤中使用此调用返回的安全事件源句柄。
接下来,通过调用两个紧密相关的API之一来生成事件:AuthzReportSecurityEvent或AuthzReportSecurityEventFromParams。最后,当应用程序关闭时,它将通过调用AuthzUnregisterSecurityEventSource取消注册安全事件源句柄。
在编译代码之前,我们需要赋予当前用户相关的权限,也就是Generate Security audits
具体步骤:
在开始菜单中,打开Local Security Policy,如下图,

找到Generate Security audits, 在里面添加当前用户,我们的计算机一般是以管理员身份运行的,所以可以将管理员也添加进来(添加完需要将电脑重启,以使组策略生效)。
如果是以管理员身份运行的,那么我们在编译代码时,也需要以管理员身份运行代码。不然还是无法获取SeAuditPrivilege权限。
另外,我们还需要在Audit Policy中Enable Audit object access的Success,Failure, 见下图,

代码示例:
#include <stdio.h>
#include <iostream>
#include <string>
#include <strsafe.h>
#include <windows.h>
#include <Authz.h>
#include <Ntsecapi.h> #define STATUS_SUCCESS ((NTSTATUS)0x00000000L) #pragma comment(lib,"Authz.lib")
#pragma comment(lib,"Advapi32.lib") void print_privileges(HANDLE hToken); 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[])
{
// Declare and initialize variables. 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;
// Register the audit provider.
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);
print_privileges(token); 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();
} void print_privileges(HANDLE hToken)
{
DWORD size = 0;
if (!GetTokenInformation(hToken, TokenPrivileges, NULL, 0, &size) && GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
PTOKEN_PRIVILEGES tp = (PTOKEN_PRIVILEGES)malloc(size);
if (tp != NULL && GetTokenInformation(hToken, TokenPrivileges, tp, size, &size)) {
size_t i;
for (i = 0; i < tp->PrivilegeCount; ++i) {
char name[64] = "?";
DWORD name_size = sizeof name;
LookupPrivilegeNameA(0, &tp->Privileges[i].Luid, name, &name_size);
PRIVILEGE_SET ps = {
1, PRIVILEGE_SET_ALL_NECESSARY, {
{ { tp->Privileges[i].Luid.LowPart, tp->Privileges[i].Luid.HighPart } }
}
};
BOOL fResult;
PrivilegeCheck(hToken, &ps, &fResult);
printf("%-*s %s\n", 32, name, fResult ? "Enabled" : "Disabled");
}
}
free(tp);
}
}
在运行过程中,首先确定是否获取了我们需要的权限。

如果是Enabled的状态,说明获取权限成功,后面只需要通过AuthzRegisterSecurityEventSource和AuthzReportSecurityEvent这两个api与LSA进行交互,从而写入安全日志。
最后的结果:

win32 - 写入安全日志(AuthzRegisterSecurityEventSource和AuthzReportSecurityEvent)的更多相关文章
- 支持异步写入的日志类,支持Framework2.0
因为工作需要需要在XP上运行一个C#编写的Winform插件,我就用Framework2.0,因为存在接口交互所以想保留交易过程的入参出参. 考虑到插件本身实施的因素,就没有使用Log4.NLog等成 ...
- c#.NET中日志信息写入Windows日志中解决方案
1. 目的应用系统的开发和维护离不开日志系统,选择一个功能强大的日志系统解决方案是应用系统开发过程中很重要的一部分.在.net环境下的日志系统解决方案有许多种,log4net是其中的佼佼者.在Wind ...
- 将shell脚本运行情况写入Rsyslog日志server
在运维工作中,免不了编写一些脚本交由计划任务(cron)去定时运行完毕一些日常工作,实现运维工作自己主动化.比方在我的日常工作中备份数据是一项重要的工作,须要定时将数据备份到备份服器和一些其它的备份介 ...
- 向jboss写入服务器日志
实际开发中,记录日志是常用的功能,jboss默认情况下已经记录了很多运行日志,如果开发人员要手动在server.log中写入日志,可以参考下面的方法: package utils; import ja ...
- 向服务器写入错误日志-log
/// <summary> /// 写日志,方便测试(看网站需求,也可以改成把记录存入数据库) /// </summary> /// <param name=" ...
- PHP 文件操作类(创建文件并写入) 生成日志
<?php /** * 文件操作(生成日志)支持多条插入 * (假设插入多条语句并换行 用','逗号分开) * */ class log { public $path = './info.txt ...
- 3种日志类型,微信付款反馈-->写入txt日志
--> 接收 $GLOBALS["HTTP_RAW_POST_DATA"] ---->xml 反系列化$qr = XML_unserialize( $rowpost ...
- NLog写入Mongo日志配置
Web网站中引入了NLog日志,日志记录在Mongo数据库中,经过两天的简单学习,现简要记录说明下: 首先贴出NLog的学习地址: https://github.com/NLog/NLog/wiki/ ...
- Python 写入训练日志文件并控制台输出
1. 背景 在深度学习的任务中,通常需要比较长时间的训练,因此我们会选择离开电脑.笔者在跟踪模型表现, 观察模型accuracy 以及 loss 的时候,比较传统的方法是在控制台print输出或者直接 ...
- 网站404,500错误页面的处理,及500异常写入errorLog日志
1.web.xml 配置 <error-page> <error-code>404</error-code> <location>/404.jsp< ...
随机推荐
- [转帖]jmeter必备正则表达式
元字符 . 注意是一个点号,表示匹配任意单个字符 \d 表示匹配任意单个数字 [0-9] 等价于0-9 [a-zA-Z] 等价于所有的大小写字母 限定符 + 加号,表示匹配至少大于1次(1次或多次 ...
- [转帖]jemalloc 性能测试
https://wenfh2020.com/2020/07/30/jemalloc/ jemalloc 是一个优秀的内存分配器,通过与系统默认的内存分配器进行比较:jemalloc 内存分配性能比 ...
- [转帖]NVMe 与 AHCI
https://www.cnblogs.com/zengkefu/p/5634345.html http://elf8848.iteye.com/blog/1731274 AHCI: NCQ技术,60 ...
- 使用buildx在x86机器上面编译arm64架构的Docker镜像
buildx 多架构编译 安装docker 下载docker 下载buildx 安装架构支持 docker run --privileged --rm tonistiigi/binfmt --inst ...
- redis 6源码解析之 sds
redis使用sds(simple dynamic string)实现了字符串的存储.sds实际上就是TLV格式的数据结构.其数据结构主要分为如下5种,主要分为首部和数据部分,首部给出了type和le ...
- Ant Design Vue中TreeSelect详解
<template> <a-tree-select v-model:value="value" style="width: 320px" :t ...
- 7.2 Windows驱动开发:内核注册并监控对象回调
在笔者上一篇文章<内核枚举进程与线程ObCall回调>简单介绍了如何枚举系统中已经存在的进程与线程回调,本章LyShark将通过对象回调实现对进程线程的句柄监控,在内核中提供了ObRegi ...
- SpringSecurity 的登录流程
用过SpringSecurity的小伙伴,都知道 Authentication 这个接口,我们在任何地方通过这个接口来获取到用户登录的信息,而我们用的频繁的一个它的一个实现类就是 Username ...
- vue-cli3创建多页面应用
首先用vue-cli3创建工程,我的全局安装了vue-cli2,又不想卸载掉:所以新建了一个文件夹安装vue-cli3:然后在该文件夹下创建工程: 同时安装vue-cli2和vue-cli3参考:ht ...
- 【C++深度剖析】为什么C++支持函数重载而C不支持--C++程序编译链接过程--符号表生成规则【Linux环境超详细解释C++函数重载底层原理】
文章目录 前言 Linux环境g++编译器的配置以及一些准备工作 源文件的符号表生成以及分析 尾声 前言 先赞后看好习惯 打字不容易,这都是很用心做的,希望得到支持你 大家的点赞和支持对于我来说是一种 ...