做教程网站资源放哪里,做运营的具体做什么,泊头哪里有做网站的,临沂网站建设电话前言
之前的文档中#xff0c;描写了如何对WFP防火墙进行操作以及如何在防火墙日志中读取被防火墙拦截网络通讯的日志。这边文档#xff0c;着重描述如何读取操作系统中所有被放行的网络通信行为。 读取系统中放行的网络通信行为日志#xff0c;在win10之后的操作系统上描写了如何对WFP防火墙进行操作以及如何在防火墙日志中读取被防火墙拦截网络通讯的日志。这边文档着重描述如何读取操作系统中所有被放行的网络通信行为。 读取系统中放行的网络通信行为日志在win10之后的操作系统上也可以通过前一篇提到的读取阻断日志的方式进行读取以FWPM_NET_EVENT0.type字段区分但是在较老的系统中却不支持直接读取。为了保持系统兼容性可以通过读取操作系统安全日志EventId:5156的方式进行网络通信日志的采集。
需要注意的坑点
查询放行日志时需要注意每个网络通信行为在日志中只会出现一条放行记录对应的筛选器ID只会是首次对其进行审计的过滤器ID。因此如果有其他权重更高的子层对网络连接进行了审计时就无法通过筛选器ID匹配的方式获取。如果有这方面需求的话解决方法只能是尽可能将自身子层的权重设为最高。网络日志中读取连入行为时WIN10/2016/2019源IP和目的IP字段与其它更早的操作系统相反需要特殊处理。连出行为无异常。
开启审计
采用读取安全日志的方式进行网络事件获取首先需要在系统中开启审计功能。在代码里面也有多种方式可以开启之后会单开一篇文档进行描述在这里先手动开启。 打开本地安全策略开始——运行——secpol.msc依次打开安全设置——本地策略——审核策略如图 在右侧窗口中打开 审核对象 标签页勾选 “成功” 复选框后点击保存即可开启网络访问的审计功能 右键单击 “我的电脑”——“管理”——“计算机管理”——“系统工具”——“事件查看器”——“Windows日志”——“安全”中查看5156日志即可。
网络通信日志默认情况下是开启状态为了以防万一每次获取之前需要使用代码开启一次。使用代码的开启方式下次单开文档分享。
使用WMI方式进行查询
使用ReadEventLog进行查询
优点兼容性高可支持XP/2003操作系统。读取性能高。 缺点无法做过滤在大量日志中提取少量日志时效率较低 使用ReadEventLog读取Windows的安全日志只需要三步即可1、打开EventLog句柄2、使用ReadEventLog循环读取日志3、关闭EventLog句柄。具体API描述如下。 打开EventLog句柄 HANDLE OpenEventLog( LPCSTR lpUNCServerName, LPCSTR lpSourceName );输入参数 lpUNCServerName远程服务器的名称。读取本地的话传入NULL即可。lpSourceName日志名称。这里读取安全日志传入“Serurity”。其他对应值系统日志“System”应用程序日志“Application” 输出参数 返回日志读取句柄。在ReadEventLog中使用需要调用CloseEventLog手动关闭。 读取日志 BOOL ReadEventLog( HANDLE hEventLog, DWORD dwReadFlags, DWORD dwRecordOffset, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, DWORD *pnBytesRead, DWORD *pnMinNumberOfBytesNeeded );输入参数 hEventLog需要读取日志的句柄就是刚才OpenEventLog返回的那个dwReadFlags读取标志可以选择从指定偏移读取EVENTLOG_SEEK_READ或按顺序读取EVENTLOG_SEQUENTIAL_READ也可以指定正序读取EVENTLOG_FORWARDS_READ或倒序读取EVENTLOG_BACKWARDS_READdwRecordOffset当dwReadFlags中包含EVENTLOG_SEEK_READ时有效表示开始的位置lpBuffer分配的缓冲区由外部划分内存nNumberOfBytesToReadlpBuffer缓冲区的大小pnBytesRead返回接收字节数pnMinNumberOfBytesNeeded返回lpBuffer所需最小缓冲区大小。仅当lpBuffer过小时返回可判断GetLastError()返回ERROR_INSUFFICIENT_BUFFER 时有效。 输出参数 正常执行返回非0值失败后返回0 关闭EventLog句柄
BOOL CloseEventLog( HANDLE hEventLog );输入参数 hEventLog事件句柄由OpenEventLog返回 输出参数 成功与否这玩意没啥好判断的。 关联结构体 typedef struct _EVENTLOGRECORD { DWORD Length; DWORD Reserved; DWORD RecordNumber; DWORD TimeGenerated; DWORD TimeWritten; DWORD EventID; WORD EventType; WORD NumStrings; WORD EventCategory; WORD ReservedFlags; DWORD ClosingRecordNumber; DWORD StringOffset; DWORD UserSidLength; DWORD UserSidOffset; DWORD DataLength; DWORD DataOffset; } EVENTLOGRECORD, *PEVENTLOGRECORD;参数说明 Length当前结构体的长度由于ReadEventLog是以内存块的方式返回单次返回的内存块中可能包含多个特别是为了节省资源可能会在代码中刻意一次读取大量的EventLogRecord结构体。这些结构体在内存块中就以Length参数作为分界线来进行分割 Reserved保留没有可以研究过用于啥 RecordNumber日志序号可配合ReadEventLog函数中的dwReadFlags参数和dwReadOffset参数设置读取的偏移地址 TimeGenerated事件时间转time_t就可以 TimeWrittern日志写入时间time_t格式 EventID事件ID最高两位代表严重性第三位代表是否为系统事件低16位代表在安全日志中可见的ID。 EventType事件类型 NumStrings包含字符串数目 EventCategory事件类别 ReservedFlags保留 ClosingRecordNumber保留 StringOffset事件包含字符串起始地址的偏移。字符串按顺序依次在内存中存储0长度的字符串代表结束。字符串的顺序和在事件查看器中看到的顺序一致如图 UserSidLength/UserSidOffset: 用户SID的长度及偏移与字符串类似 DataLength/DataOffset数据部分的长度及偏移 参考代码 #include iostream
#include windows.h
#include string
#include vector#define MAX_EVENTLOG_READONCE 2048
void ReadLogsByReadEventLogAPI()
{LPBYTE pEventLogBuffer new(std::nothrow) BYTE[MAX_EVENTLOG_READONCE];if (pEventLogBuffer NULL){return;}ZeroMemory(pEventLogBuffer, MAX_EVENTLOG_READONCE);HANDLE hEventLog OpenEventLog(NULL, LSecurity);if (hEventLog NULL){delete[] pEventLogBuffer;pEventLogBuffer NULL;return;}DWORD dwMemoryLen MAX_EVENTLOG_READONCE;DWORD dwReaded 0, dwMiniMemoryNeeded 0;while (true)// -_-|||{BOOL isSucc ReadEventLog(hEventLog, EVENTLOG_BACKWARDS_READ | EVENTLOG_SEQUENTIAL_READ, 0, pEventLogBuffer, dwMemoryLen, dwReaded, dwMiniMemoryNeeded);if (isSucc FALSE GetLastError() ERROR_INSUFFICIENT_BUFFER dwMiniMemoryNeeded){delete[] pEventLogBuffer;pEventLogBuffer NULL;pEventLogBuffer new (std::nothrow) BYTE[dwMiniMemoryNeeded];if (pEventLogBuffer NULL){break;}ZeroMemory(pEventLogBuffer, dwMiniMemoryNeeded);dwMemoryLen dwMiniMemoryNeeded;isSucc ReadEventLog(hEventLog, EVENTLOG_BACKWARDS_READ | EVENTLOG_SEQUENTIAL_READ, 0, pEventLogBuffer, dwMemoryLen, dwReaded, dwMiniMemoryNeeded);}if (isSucc FALSE){break;}int pos 0;do {EVENTLOGRECORD* pTempRecord (EVENTLOGRECORD*)(pEventLogBuffer pos);__time32_t occurTime pTempRecord-TimeWritten;int nEventId pTempRecord-EventID 0xffff;if (nEventId ! 5156){pos pos pTempRecord-Length;continue;}std::vectorstd::wstring vecEventParam;LPBYTE pTempBuffer (LPBYTE)pTempRecord pTempRecord-StringOffset;int strCount 0;while ((pTempBuffer ((LPBYTE)pTempRecord pTempRecord-Length)) (strCount pTempRecord-NumStrings)){int len wcslen((wchar_t*)pTempBuffer);if (len 0){break;}vecEventParam.push_back((wchar_t*)pTempBuffer);pTempBuffer pTempBuffer (len 1) * sizeof(wchar_t);strCount;}if (vecEventParam.size() 10){std::wcout \n\n std::endl;std::wcout LSource:\t vecEventParam[3] L[ vecEventParam[4] L] std::endl;std::wcout LDestination:\t vecEventParam[5] L[ vecEventParam[6] L] std::endl;std::wcout LProtocol Code:\t vecEventParam[7] std::endl;std::wcout LProcess Id:\t vecEventParam[0] std::endl;std::wcout LProcess Name:\t vecEventParam[1] std::endl;std::wcout \n\n std::endl;}pos pos pTempRecord-Length;} while (pos dwReaded);}CloseEventLog(hEventLog);delete[] pEventLogBuffer;pEventLogBuffer NULL;
} 输出截图 使用Evt系列API进行查询
优点性能高可自由配置过滤条件方便在海量日志中检索可读取的内容相当丰富 缺点不支持xp/2003操作系统 Evt系列API涉及到的功能较多如果只需要读取系统日志的话只需要枚举、遍历、读取、关闭四步即可完成。 枚举当前日志 EVT_HANDLE EvtQuery( EVT_HANDLE Session, LPCWSTR Path, LPCWSTR Query, DWORD Flags );遍历日志获取下一条 BOOL EvtNext( EVT_HANDLE ResultSet, DWORD EventsSize, PEVT_HANDLE Events, DWORD Timeout, DWORD Flags, PDWORD Returned );读取日志内容 BOOL EvtRender( EVT_HANDLE Context, EVT_HANDLE Fragment, DWORD Flags, DWORD BufferSize, PVOID Buffer, PDWORD BufferUsed, PDWORD PropertyCount );输入参数 Context:Fragment:Flags:BufferSize:Buffer:BufferUsed:PropertyCount: 输出参数 * 关闭枚举句柄 BOOL EvtClose( EVT_HANDLE Object );实例代码 void parseEventXML(std::wstring wstrXML)
{std::wstring_convertstd::codecvt_utf8_utf16wchar_t cv;std::string utfXML cv.to_bytes(wstrXML);tinyxml2::XMLDocument rootXML;if (rootXML.Parse(utfXML.c_str()) ! tinyxml2::XML_SUCCESS){return;}tinyxml2::XMLNode* rootNode rootXML.FirstChild();if (rootNode NULL){return;}std::string processId;std::string processName;std::string sourceAddress;std::string sourcePort;std::string destAddress;std::string destPort;std::string protocol;tinyxml2::XMLNode* eventNode rootXML.FirstChildElement(Event);if (eventNode){tinyxml2::XMLElement* eventDataNode eventNode-FirstChildElement(EventData);if (eventDataNode NULL){return;}tinyxml2::XMLElement* dataNode eventDataNode-FirstChildElement(Data);do {std::string strName dataNode-Attribute(Name);if (_stricmp(strName.c_str(), ProcessID) 0){processId dataNode-GetText();}else if (_stricmp(strName.c_str(), Application) 0){processName dataNode-GetText();}else if (_stricmp(strName.c_str(), SourceAddress) 0){sourceAddress dataNode-GetText();}else if (_stricmp(strName.c_str(), SourcePort) 0){sourcePort dataNode-GetText();}else if (_stricmp(strName.c_str(), DestAddress) 0){destAddress dataNode-GetText();}else if (_stricmp(strName.c_str(), DestPort) 0){destPort dataNode-GetText();}else if (_stricmp(strName.c_str(), Protocol) 0){protocol dataNode-GetText();}dataNode dataNode-NextSiblingElement(Data);} while (dataNode);std::cout \n\n std::endl;std::cout Source:\t sourceAddress [ sourcePort ] std::endl;std::cout Destination:\t destAddress [ destPort ] std::endl;std::cout Protocol Code:\t protocol std::endl;std::cout Process Id:\t processId std::endl;std::cout Process Name:\t processName std::endl;std::cout \n\n std::endl;}
}void ReadLogsByEvtAPI()
{DWORD dwEventLogBufferLen MAX_EVENTLOG_READONCE;LPBYTE pEventLogBuffer new(std::nothrow) BYTE[MAX_EVENTLOG_READONCE];if (pEventLogBuffer NULL){return;}ZeroMemory(pEventLogBuffer, MAX_EVENTLOG_READONCE);std::wstring wstrQuery std::wstring(LQueryListL QueryL SelectEvent/System[EventID5156]/SelectL /QueryL/QueryList);EVT_HANDLE hResult EvtQuery(NULL, LSecurity, wstrQuery.c_str(), EvtQueryChannelPath | EvtQueryReverseDirection);if (hResult NULL){delete[] pEventLogBuffer;pEventLogBuffer NULL;return;}while (true) // -_-{EVT_HANDLE hEventArrs[MAX_PATH] { 0 };DWORD dwReturnEvents 0;BOOL isSucc EvtNext(hResult, MAX_PATH, hEventArrs, INFINITE, 0, dwReturnEvents);if (isSucc dwReturnEvents){for (int eventPos 0; eventPos dwReturnEvents; eventPos){DWORD dwBufferUsed 0;DWORD dwPropertyCount 0;int nBufferSize dwEventLogBufferLen;ZeroMemory(pEventLogBuffer, nBufferSize);isSucc EvtRender(NULL, hEventArrs[eventPos], EvtRenderEventXml, nBufferSize, pEventLogBuffer, dwBufferUsed, dwPropertyCount);if (isSucc FALSE GetLastError() ERROR_INSUFFICIENT_BUFFER){delete[] pEventLogBuffer;pEventLogBuffer NULL;dwEventLogBufferLen dwBufferUsed 2;pEventLogBuffer new(std::nothrow) BYTE[dwEventLogBufferLen];if (pEventLogBuffer NULL){break;}nBufferSize dwEventLogBufferLen;ZeroMemory(pEventLogBuffer, dwEventLogBufferLen);isSucc EvtRender(NULL, hEventArrs[eventPos], EvtRenderEventXml, nBufferSize, pEventLogBuffer, dwBufferUsed, dwPropertyCount);}if (isSucc){std::wstring strEventXML std::wstring((wchar_t*)pEventLogBuffer);parseEventXML(strEventXML);}}}}if (pEventLogBuffer){delete[] pEventLogBuffer;pEventLogBuffer NULL;}
}输出截图 备注 实例代码中解析xml使用的是tinyxml2库对应github地址为https://github.com/leethomason/tinyxml2/tree/master 当前最新版9.0.0版本下载地址https://download.csdn.net/download/QQ1113130712/88235095