Panoptes 1.0.0
Endpoint Detection and Response
Loading...
Searching...
No Matches
Functions | Variables
events.cpp File Reference
#include <Windows.h>
#include <evntrace.h>
#include <stdio.h>
#include <evntcons.h>
#include <string>
#include <tdh.h>
#include <assert.h>
#include <memory>
#include <in6addr.h>
#include <chrono>
#include <iomanip>
#include <sstream>
#include <nlohmann/json.hpp>
#include "pano_log.h"
#include "utils.h"
#include "service_constants.h"
#include "grpc.hpp"
#include "panoptes_service.h"

Go to the source code of this file.

Functions

std::string FormatSystemTime (const FILETIME &ft)
 
std::optional< GUID > GetProviderGuid (const std::string &providerNameToFind)
 
std::vector< GUID > GetProvidersGUID (std::vector< std::string > providers)
 
void DisplayEventInfo (PEVENT_RECORD rec, PTRACE_EVENT_INFO info)
 https://github.com/zodiacon/Win10SysProgBookSamples/blob/9f2d1bb61a24fee4e08ec46738680e44f6c132de/Chapter20/ParseETW/ParseETW.cpp#L131
 
VOID WINAPI EventRecordCallback (EVENT_RECORD *pEventRecord)
 
ULONG WINAPI BufferCallback (EVENT_TRACE_LOGFILE *pLogFile)
 
ULONG StopAndDeleteTrace ()
 
VOID StopPanoptesTrace ()
 
ULONG StartPanoptesTrace (LPVOID lpParam)
 

Variables

TRACEHANDLE hTrace = 0
 
ULONG result
 
ULONG bufferSize
 
EVENT_TRACE_LOGFILEW trace
 
EVENT_TRACE_PROPERTIES * traceProp = nullptr
 

Function Documentation

◆ BufferCallback()

ULONG WINAPI BufferCallback ( EVENT_TRACE_LOGFILE *  pLogFile)

Definition at line 266 of file events.cpp.

266 {
267 return TRUE;
268}

◆ DisplayEventInfo()

void DisplayEventInfo ( PEVENT_RECORD  rec,
PTRACE_EVENT_INFO  info 
)

https://github.com/zodiacon/Win10SysProgBookSamples/blob/9f2d1bb61a24fee4e08ec46738680e44f6c132de/Chapter20/ParseETW/ParseETW.cpp#L131

Parameters
rec
info

Definition at line 102 of file events.cpp.

102 {
103
104 //GUID providerId = { 0x7036af95, 0x9daf, 0x4486, 0x8d, 0x93, 0x70, 0x5, 0xd4, 0x5a, 0x6a, 0x6 };
105 //if (rec->EventHeader.ProviderId != providerId)
106 // return;
107
108 nlohmann::json jsonObject;
109 if (info->KeywordsNameOffset)
110 printf("Keywords: %ws ", (PCWSTR)((BYTE*)info + info->KeywordsNameOffset));
111 if (info->OpcodeNameOffset)
112 printf("Opcode: %ws ", (PCWSTR)((BYTE*)info + info->OpcodeNameOffset));
113 if (info->LevelNameOffset)
114 printf("Level: %ws ", (PCWSTR)((BYTE*)info + info->LevelNameOffset));
115 if (info->TaskNameOffset) {
116 printf("Task: %ws ", (PCWSTR)((BYTE*)info + info->TaskNameOffset));
117 std::wstring taskName = (PCWSTR)((BYTE*)info + info->TaskNameOffset);
118 jsonObject["Event"] = ToString(taskName);
119 }
120 if (info->EventMessageOffset)
121 printf("\nMessage: %ws", (PCWSTR)((BYTE*)info + info->EventMessageOffset));
122
123 printf("\nProperties: %u\n", info->TopLevelPropertyCount);
124
125 // properties data length and pointer
126 auto userlen = rec->UserDataLength;
127 auto data = (PBYTE)rec->UserData;
128
129 auto pointerSize = (rec->EventHeader.Flags & EVENT_HEADER_FLAG_32_BIT_HEADER) ? 4 : 8;
130 ULONG len;
131 WCHAR value[512];
132
133 for (DWORD i = 0; i < info->TopLevelPropertyCount; i++) {
134 auto& pi = info->EventPropertyInfoArray[i];
135 auto propName = (PCWSTR)((BYTE*)info + pi.NameOffset);
136 printf(" Name: %ws ", propName);
137 std::string propNameStr = ToString(propName);
138
139 len = pi.length;
140 if ((pi.Flags & (PropertyStruct | PropertyParamCount)) == 0) {
141 //
142 // deal with simple properties only
143 //
144 PEVENT_MAP_INFO mapInfo = nullptr;
145 std::unique_ptr<BYTE[]> mapBuffer;
146 PWSTR mapName = nullptr;
147 //
148 // retrieve map information (if any)
149 //
150 if (pi.nonStructType.MapNameOffset) {
151 ULONG size = 0;
152 mapName = (PWSTR)((BYTE*)info + pi.nonStructType.MapNameOffset);
153 if (ERROR_INSUFFICIENT_BUFFER == ::TdhGetEventMapInformation(rec, mapName, mapInfo, &size)) {
154 mapBuffer = std::make_unique<BYTE[]>(size);
155 mapInfo = reinterpret_cast<PEVENT_MAP_INFO>(mapBuffer.get());
156 if (ERROR_SUCCESS != ::TdhGetEventMapInformation(rec, mapName, mapInfo, &size))
157 mapInfo = nullptr;
158 }
159 }
160
161 ULONG size = sizeof(value);
162 USHORT consumed;
163 // special case for IPv6 address
164 if (pi.nonStructType.InType == TDH_INTYPE_BINARY && pi.nonStructType.OutType == TDH_OUTTYPE_IPV6)
165 len = sizeof(IN6_ADDR);
166
167 auto error = ::TdhFormatProperty(info, mapInfo, pointerSize,
168 pi.nonStructType.InType, pi.nonStructType.OutType,
169 (USHORT)len, userlen, data, &size, value, &consumed);
170 if (ERROR_SUCCESS == error) {
171 printf("Value: %ws", value);
172 jsonObject[propNameStr] = ToString(value);
173 len = consumed;
174 if (mapName)
175 printf(" (%ws)", (PCWSTR)mapName);
176 printf("\n");
177 }
178 else if (mapInfo) {
179 error = ::TdhFormatProperty(info, nullptr, pointerSize,
180 pi.nonStructType.InType, pi.nonStructType.OutType,
181 (USHORT)len, userlen, data, &size, value, &consumed);
182 if (ERROR_SUCCESS == error) {
183 printf("Value: %ws\n", value);
184 jsonObject[propNameStr] = ToString(value);
185 }
186 }
187 if (ERROR_SUCCESS != error)
188 printf("(failed to get value)\n");
189 }
190 else {
191 printf("(not a simple property)\n");
192 }
193 userlen -= (USHORT)len;
194 data += len;
195 }
196 auto& header = rec->EventHeader;
197 jsonObject["TID"] = header.ThreadId;
198 jsonObject["PID"] = header.ProcessId;
199 if (header.ProcessId == GetCurrentProcessId()) {
200 return;
201 }
202 std::string timeLog = FormatSystemTime(*(FILETIME*)&header.TimeStamp);
203 jsonObject["Time"] = timeLog;
204
205 try {
206 std::string eventName = jsonObject["Event"].get<std::string>();
207 if (!eventName.empty()) {
208 if (eventName == "FileCreated" || eventName == "FileModified") {
209 std::string fileName = jsonObject["FileName"].get<std::string>();
210 SelfQueuePeScan(fileName, "");
211 }
212 else if (eventName == "KERNEL_NETWORK_TASK_TCPIP" || eventName == "KERNEL_NETWORK_TASK_UDPIP"){
213 auto destAddr = jsonObject["daddr"].get<std::string>();
214 auto srcAddr = jsonObject["saddr"].get<std::string>();
215 if (srcAddr == "127.0.0.1" || destAddr == "127.0.0.1") {
216 return;
217 }
218 if (srcAddr == "::1" || destAddr == "::1") {
219 return;
220 }
221 }
222 }
223
224 }
225 catch (...){
226 WriteToLogFile(jsonObject.dump() + "\n");
227 return;
228 }
229
230 WriteToLogFile(jsonObject.dump() + "\n");
231}
std::string FormatSystemTime(const FILETIME &ft)
Definition events.cpp:26
void SelfQueuePeScan(std::string pePath, std::string fileHash)
Definition grpc.cpp:224
unsigned char BYTE
Definition inject.h:4
unsigned long DWORD
Definition inject.h:2
void WriteToLogFile(const std::string &message)
Definition pano_log.cpp:32
std::string ToString(const std::wstring &wstr)
Definition utils.cpp:50

References FormatSystemTime(), SelfQueuePeScan(), ToString(), and WriteToLogFile().

Referenced by EventRecordCallback().

◆ EventRecordCallback()

VOID WINAPI EventRecordCallback ( EVENT_RECORD *  pEventRecord)

Definition at line 243 of file events.cpp.

243 {
244 //DisplayGeneralEventInfo(pEventRecord);
245
246 ULONG size = 0;
247 auto status = ::TdhGetEventInformation(pEventRecord, 0, nullptr, nullptr, &size);
248 assert(status == ERROR_INSUFFICIENT_BUFFER);
249
250 auto buffer = std::make_unique<BYTE[]>(size);
251 if (!buffer) {
252 printf("Out of memory!\n");
253 ::ExitProcess(1);
254 }
255
256 auto info = reinterpret_cast<PTRACE_EVENT_INFO>(buffer.get());
257 status = ::TdhGetEventInformation(pEventRecord, 0, nullptr, info, &size);
258 if (status != ERROR_SUCCESS) {
259 printf("Error processing event!\n");
260 return;
261 }
262
263 DisplayEventInfo(pEventRecord, info);
264}
void DisplayEventInfo(PEVENT_RECORD rec, PTRACE_EVENT_INFO info)
https://github.com/zodiacon/Win10SysProgBookSamples/blob/9f2d1bb61a24fee4e08ec46738680e44f6c132de/Cha...
Definition events.cpp:102

References DisplayEventInfo().

Referenced by StartPanoptesTrace().

◆ FormatSystemTime()

std::string FormatSystemTime ( const FILETIME &  ft)

Definition at line 26 of file events.cpp.

26 {
27 SYSTEMTIME st;
28 FileTimeToSystemTime(&ft, &st);
29
30 std::ostringstream ss;
31 ss << std::setfill('0')
32 << st.wYear << '/'
33 << std::setw(2) << st.wMonth << '/'
34 << std::setw(2) << st.wDay << ' '
35 << std::setw(2) << st.wHour << ':'
36 << std::setw(2) << st.wMinute << ':'
37 << std::setw(2) << st.wSecond;
38 return ss.str();
39}

Referenced by DisplayEventInfo().

◆ GetProviderGuid()

std::optional< GUID > GetProviderGuid ( const std::string &  providerNameToFind)

Definition at line 41 of file events.cpp.

41 {
42 ULONG bufferSize = 0;
43 PROVIDER_ENUMERATION_INFO* providerInfo = nullptr;
44 std::optional<GUID> result;
45
46 // Get the required buffer size
47 ULONG status = TdhEnumerateProviders(nullptr, &bufferSize);
48 if (status == ERROR_INSUFFICIENT_BUFFER) {
49 providerInfo = (PROVIDER_ENUMERATION_INFO*)malloc(bufferSize);
50 if (providerInfo == nullptr) {
51 throw std::runtime_error("Failed to allocate memory");
52 }
53
54 // Enumerate providers
55 status = TdhEnumerateProviders(providerInfo, &bufferSize);
56 if (status == ERROR_SUCCESS) {
57 for (ULONG i = 0; i < providerInfo->NumberOfProviders; i++) {
58 TRACE_PROVIDER_INFO& provider = providerInfo->TraceProviderInfoArray[i];
59 wchar_t* providerName = (wchar_t*)((BYTE*)providerInfo + provider.ProviderNameOffset);
60
61 std::wstring wProviderName(providerName);
62 std::string providerNameStr(wProviderName.begin(), wProviderName.end());
63
64 if (providerNameStr == providerNameToFind) {
65 result = provider.ProviderGuid;
66 break;
67 }
68 }
69 }
70 else {
71 throw std::runtime_error("TdhEnumerateProviders failed with error: " + std::to_string(status));
72 }
73
74 free(providerInfo);
75 }
76 else {
77 throw std::runtime_error("TdhEnumerateProviders failed with error: " + std::to_string(status));
78 }
79
80 return result;
81}
ULONG result
Definition events.cpp:22
ULONG bufferSize
Definition events.cpp:22

References bufferSize, and result.

Referenced by GetProvidersGUID(), and StartPanoptesTrace().

◆ GetProvidersGUID()

std::vector< GUID > GetProvidersGUID ( std::vector< std::string >  providers)

Definition at line 83 of file events.cpp.

83 {
84 std::vector<GUID> guids;
85 for (const auto& providerName : providers) {
86 auto guid = GetProviderGuid(providerName);
87 if (guid.has_value()) {
88 guids.push_back(guid.value());
89 }
90 else {
91 printf("Provider %s not found\n", providerName.c_str());
92 }
93 }
94 return guids;
95}
std::optional< GUID > GetProviderGuid(const std::string &providerNameToFind)
Definition events.cpp:41

References GetProviderGuid().

◆ StartPanoptesTrace()

ULONG StartPanoptesTrace ( LPVOID  lpParam)

Definition at line 305 of file events.cpp.

305 {
308 auto providers = serviceContext.config->m_eventProviders;
309
310 // Initialize properties for the single trace session
311 ULONG bufferSize = sizeof(EVENT_TRACE_PROPERTIES) + (MAX_PATH * sizeof(WCHAR));
312 EVENT_TRACE_PROPERTIES* pProperties = (EVENT_TRACE_PROPERTIES*)malloc(bufferSize);
313 ZeroMemory(pProperties, bufferSize);
314
315 pProperties->Wnode.BufferSize = bufferSize;
316 pProperties->Wnode.Flags = WNODE_FLAG_TRACED_GUID;
317 pProperties->Wnode.ClientContext = 1; // QPC clock resolution
318 pProperties->LogFileMode = EVENT_TRACE_REAL_TIME_MODE;
319 pProperties->LoggerNameOffset = sizeof(EVENT_TRACE_PROPERTIES);
320 pProperties->LogFileNameOffset = 0;
321
322 // Start the trace session
323 TRACEHANDLE hTrace;
324 WCHAR sessionName[] = L"Panoptes";
325 ULONG result = StartTraceW(&hTrace, sessionName, pProperties);
326 if (result != ERROR_SUCCESS)
327 {
328 // Handle error
329 free(pProperties);
330 return 1;
331 }
332
333 // Enable multiple providers
334 for (const auto& provider : providers)
335 {
336 auto [provName, provMatchAny, provMatchAll] = provider;
337
338 GUID provGUID = GetProviderGuid(provName).value_or(GUID{});
339 if (provGUID == GUID{}) {
340 printf("[!] Could not retrieve GUID for %s\n", provName);
341 continue;
342 }
343
344 result = EnableTraceEx2(
345 hTrace,
346 &provGUID,
347 EVENT_CONTROL_CODE_ENABLE_PROVIDER,
348 TRACE_LEVEL_INFORMATION,
349 provMatchAny,
350 provMatchAll,
351 0,
352 NULL
353 );
354 if (result != ERROR_SUCCESS)
355 {
356 // Handle error
357 printf("[!] Could not enable trace for %s\n", provName);
358 continue;
359 }
360 }
361
362 // Set up the trace session
363 EVENT_TRACE_LOGFILEW trace;
364 ZeroMemory(&trace, sizeof(EVENT_TRACE_LOGFILE));
365 trace.LoggerName = (LPWSTR)sessionName;
366 trace.ProcessTraceMode = PROCESS_TRACE_MODE_REAL_TIME | PROCESS_TRACE_MODE_EVENT_RECORD;
367 trace.EventRecordCallback = EventRecordCallback;
368
369 // Start processing events
370 TRACEHANDLE hProcessTrace = OpenTraceW(&trace);
371 if (hProcessTrace == INVALID_PROCESSTRACE_HANDLE)
372 {
373 // Handle error
374 ControlTraceW(hTrace, NULL, pProperties, EVENT_TRACE_CONTROL_STOP);
375 free(pProperties);
376 return 1;
377 }
378
379 ProcessTrace(&hProcessTrace, 1, NULL, NULL);
380
381 // Clean up
382 CloseTrace(hProcessTrace);
383 ControlTraceW(hTrace, NULL, pProperties, EVENT_TRACE_CONTROL_STOP);
384 free(pProperties);
385
386 return 1;
387
388}
#define MAX_PATH
Definition callbacks.h:6
std::vector< std::tuple< std::string, unsigned long, unsigned long > > m_eventProviders
The event providers from the configuration file.
VOID WINAPI EventRecordCallback(EVENT_RECORD *pEventRecord)
Definition events.cpp:243
EVENT_TRACE_LOGFILEW trace
Definition events.cpp:23
TRACEHANDLE hTrace
Definition events.cpp:21
ULONG StopAndDeleteTrace()
Definition events.cpp:270
PanoptesContext * serviceContext
Definition grpc.cpp:27
Configuration * config

References bufferSize, PanoptesContext::config, EventRecordCallback(), GetProviderGuid(), hTrace, Configuration::m_eventProviders, MAX_PATH, result, serviceContext, StopAndDeleteTrace(), and trace.

Referenced by WinMain().

◆ StopAndDeleteTrace()

ULONG StopAndDeleteTrace ( )

Definition at line 270 of file events.cpp.

271{
272 std::wstring sessionName = TRACE_NAMEW;
273 EVENT_TRACE_PROPERTIES* pProperties = NULL;
274 ULONG bufferSize = 0;
275 ULONG status = ERROR_SUCCESS;
276
277 // Calculate the buffer size
278 bufferSize = sizeof(EVENT_TRACE_PROPERTIES) + (wcslen(sessionName.c_str()) + 1) * sizeof(WCHAR);
279 pProperties = (EVENT_TRACE_PROPERTIES*)malloc(bufferSize);
280 if (pProperties == NULL)
281 {
282 return ERROR_OUTOFMEMORY;
283 }
284
285 ZeroMemory(pProperties, bufferSize);
286 pProperties->Wnode.BufferSize = bufferSize;
287 pProperties->Wnode.Flags = WNODE_FLAG_TRACED_GUID;
288 pProperties->LoggerNameOffset = sizeof(EVENT_TRACE_PROPERTIES);
289
290 // Stop and delete the trace session
291 status = ControlTraceW(NULL, sessionName.c_str(), pProperties, EVENT_TRACE_CONTROL_STOP);
292
293 free(pProperties);
294 return status;
295}
#define TRACE_NAMEW

References bufferSize, and TRACE_NAMEW.

Referenced by StartPanoptesTrace().

◆ StopPanoptesTrace()

VOID StopPanoptesTrace ( )

Definition at line 297 of file events.cpp.

297 {
298 std::wstring Name = TRACE_NAMEW;
299 ControlTraceW(NULL, Name.c_str(), traceProp, EVENT_TRACE_CONTROL_STOP);
300 if (hTrace != NULL) {
301 CloseTrace(hTrace); // Ensure hTrace is closed
302 }
303}
EVENT_TRACE_PROPERTIES * traceProp
Definition events.cpp:24

References hTrace, TRACE_NAMEW, and traceProp.

Variable Documentation

◆ bufferSize

ULONG bufferSize

Definition at line 22 of file events.cpp.

Referenced by GetProviderGuid(), StartPanoptesTrace(), and StopAndDeleteTrace().

◆ hTrace

TRACEHANDLE hTrace = 0

Definition at line 21 of file events.cpp.

Referenced by StartPanoptesTrace(), and StopPanoptesTrace().

◆ result

ULONG result

◆ trace

EVENT_TRACE_LOGFILEW trace

Definition at line 23 of file events.cpp.

Referenced by StartPanoptesTrace().

◆ traceProp

EVENT_TRACE_PROPERTIES* traceProp = nullptr

Definition at line 24 of file events.cpp.

Referenced by StopPanoptesTrace().