#include #include #include #include #include #include #include #include "global.h" #include "context.h" #include "etwMain.h" #include #include #include "tlhelp32.h" #include #pragma comment(lib, "Ws2_32.lib") #pragma comment(lib, "Ws2_32.lib") #pragma comment(lib, "tdh.lib") #pragma comment(lib, "dbghelp.lib") DWORD lsassPID = 0; // // Used to process ETW event properties. Plan to remove these and move to TDH functions in the future. // template inline auto GetData(byte*& data) { auto value{ reinterpret_cast(data) }; data += sizeof(*value); return value; } inline auto GetWideString(byte*& data) { auto wideString{ reinterpret_cast(data) }; data += (wcslen(wideString) + 1) * sizeof(WCHAR); return wideString; } int StopETWTrace() { TRACEHANDLE traceHandle = 0; ULONG status, bufferSize; wchar_t traceName[] = L"JonMon"; EVENT_TRACE_PROPERTIES* traceProp; bufferSize = sizeof(EVENT_TRACE_PROPERTIES) + sizeof(traceName) + sizeof(WCHAR); traceProp = (EVENT_TRACE_PROPERTIES*)LocalAlloc(LPTR, bufferSize); traceProp->Wnode.BufferSize = bufferSize; traceProp->Wnode.Guid = JonMonGuid; traceProp->LogFileNameOffset = 0; traceProp->LoggerNameOffset = sizeof(EVENT_TRACE_PROPERTIES); status = StopTrace(traceHandle, traceName, traceProp); if (status != ERROR_SUCCESS) { OutputDebugStringW(L"StopTrace Failed"); return status; } else { OutputDebugStringW(L"StopTrace Success"); return status; } return 0; } DWORD ProtectionCheck() { DWORD protectionLevel = 0; do { PROCESS_PROTECTION_LEVEL_INFORMATION protectionInfo = { 0 }; if (GetProcessInformation(GetCurrentProcess(), ProcessProtectionLevelInfo, &protectionInfo, sizeof(protectionInfo))) { if (protectionInfo.ProtectionLevel != 5) { protectionLevel = 1; } } else { printf("Failed to retrieve PPL. Error code: %lu\n", GetLastError()); return 1; } } while (protectionLevel == 0); return 0; } void ChangePPL() { HANDLE hDevice = CreateFile(L"\\\\.\\JonMon", GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); if (hDevice == INVALID_HANDLE_VALUE) { printf("Error %u\n", GetLastError()); return; } DWORD bytes; HANDLE hProcess; if (DeviceIoControl(hDevice, IOCTL_CHANGE_PROTECTION_LEVEL_PROCESS, NULL, NULL, NULL, NULL, NULL, NULL)) { OutputDebugStringW(L"Protection Level Changed\n"); } else { printf("Error: %u\n", GetLastError()); } CloseHandle(hDevice); } DWORD CheckLSASSPID() { HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); PROCESSENTRY32 processEntry = {}; processEntry.dwSize = sizeof(PROCESSENTRY32); LPCWSTR processName = L""; DWORD PID = 0; if (Process32First(snapshot, &processEntry)) { while (_wcsicmp(processName, L"lsass.exe") != 0) { Process32Next(snapshot, &processEntry); processName = processEntry.szExeFile; PID = processEntry.th32ProcessID; } return PID; } CloseHandle(snapshot); } int TraceEvent() { // // Changing PPL level // ChangePPL(); // // check to see if current process is protected // DWORD retValue = ProtectionCheck(); if (retValue != 0) { printf("Process is not protected\n"); ChangePPL(); } lsassPID = CheckLSASSPID(); const char name[] = "JonMon"; TRACEHANDLE hTrace = 0; ULONG result, bufferSize; EVENT_TRACE_LOGFILEA trace; EVENT_TRACE_PROPERTIES* traceProp; memset(&trace, 0, sizeof(EVENT_TRACE_LOGFILEA)); trace.ProcessTraceMode = PROCESS_TRACE_MODE_REAL_TIME | PROCESS_TRACE_MODE_EVENT_RECORD; trace.LoggerName = (LPSTR)name; trace.EventRecordCallback = (PEVENT_RECORD_CALLBACK)ProcessEvent; bufferSize = sizeof(EVENT_TRACE_PROPERTIES) + sizeof(name) + sizeof(WCHAR); traceProp = (EVENT_TRACE_PROPERTIES*)LocalAlloc(LPTR, bufferSize); traceProp->Wnode.BufferSize = bufferSize; traceProp->Wnode.ClientContext = 2; traceProp->Wnode.Guid = JonMonGuid; traceProp->Wnode.Flags = WNODE_FLAG_TRACED_GUID; traceProp->LogFileMode = EVENT_TRACE_REAL_TIME_MODE | EVENT_TRACE_SYSTEM_LOGGER_MODE; traceProp->LogFileNameOffset = 0; traceProp->LoggerNameOffset = sizeof(EVENT_TRACE_PROPERTIES); if ((result = StartTraceA(&hTrace, (LPCSTR)name, traceProp)) != ERROR_SUCCESS) { OutputDebugStringW(L"Error starting trace\n"); return GetLastError(); } ENABLE_TRACE_PARAMETERS enableTraceParameters; ZeroMemory(&enableTraceParameters, sizeof(ENABLE_TRACE_PARAMETERS)); enableTraceParameters.Version = ENABLE_TRACE_PARAMETERS_VERSION_2; enableTraceParameters.EnableProperty = EVENT_ENABLE_PROPERTY_STACK_TRACE; OutputDebugString(L"[+] JonMon Trace started\n"); //RPC Events if ((result = EnableTraceEx2( hTrace, &RPC, EVENT_CONTROL_CODE_ENABLE_PROVIDER, TRACE_LEVEL_INFORMATION, 0, 0, 0, &enableTraceParameters )) != ERROR_SUCCESS) { OutputDebugString(L"[!] Error EnableTraceEx - RPC\n"); } //Threat Intel if ((result = EnableTraceEx2( hTrace, &ThreatIntel, EVENT_CONTROL_CODE_ENABLE_PROVIDER, TRACE_LEVEL_INFORMATION, 0, 0, 0, &enableTraceParameters )) != ERROR_SUCCESS) { OutputDebugString(L"[!] Error EnableTraceEx - Threat Intel\n"); } //WMI Events if ((result = EnableTraceEx2( hTrace, &WMIActivty, EVENT_CONTROL_CODE_ENABLE_PROVIDER, TRACE_LEVEL_INFORMATION, 0, 0, 0, &enableTraceParameters )) != ERROR_SUCCESS) { OutputDebugString(L"[!] Error EnableTraceEx - WMI\n"); } //DotNet Events if ((result = EnableTraceEx2( hTrace, &DotNet, EVENT_CONTROL_CODE_ENABLE_PROVIDER, TRACE_LEVEL_INFORMATION, 0x8, 0, 0, NULL )) != ERROR_SUCCESS) { OutputDebugString(L"[!] Error EnableTraceEx - DotNet\n"); } //Network Events if ((result = EnableTraceEx( &Network, nullptr, hTrace, TRUE, TRACE_LEVEL_INFORMATION, 0, 0, 0, NULL )) != ERROR_SUCCESS) { OutputDebugString(L"[!] Error EnableTraceEx - Network\n"); } //Task Scheduler Events if ((result = EnableTraceEx( &TaskSched, nullptr, hTrace, TRUE, TRACE_LEVEL_INFORMATION, 0, 0, 0, NULL )) != ERROR_SUCCESS) { OutputDebugString(L"[!] Error EnableTraceEx - TaskSched\n"); } //AMSI Events if ((result = EnableTraceEx( &AMSI, nullptr, hTrace, TRUE, TRACE_LEVEL_INFORMATION, 0, 0, 0, NULL )) != ERROR_SUCCESS) { OutputDebugString(L"[!] Error EnableTraceEx - AMSI\n"); } if ((result = EnableTraceEx( &DPAPI, nullptr, hTrace, TRUE, TRACE_LEVEL_INFORMATION, 0, 0, 0, NULL )) != ERROR_SUCCESS) { OutputDebugString(L"[!] Error EnableTraceEx - DPAPI\n"); } hTrace = OpenTraceA(&trace); if (hTrace == INVALID_PROCESSTRACE_HANDLE) { OutputDebugString(L"[!] Error OpenTrace\n"); return 1; } result = ProcessTrace(&hTrace, 1, NULL, NULL); if (result != ERROR_SUCCESS) { printf("[!] Error ProcessTrace\n"); return 1; } } /* * ----------------------------- * Event Processessing Functions * ----------------------------- */ void ProcessEvent( _In_ PEVENT_RECORD EventRecord ) { PEVENT_HEADER eventHeader = &EventRecord->EventHeader; PEVENT_DESCRIPTOR eventDescriptor = &eventHeader->EventDescriptor; NTSTATUS status; if (eventHeader->ProviderId == ThreatIntel) { status = WriteThreatIntelEvents(EventRecord, eventHeader); } if (eventHeader->ProviderId == RPC) { switch (eventDescriptor->Id) { case 5: { auto data{ reinterpret_cast(EventRecord->UserData) }; BOOL result = RpcEvent(EventRecord, eventHeader, RPCClientCall); break; } case 6: { auto data{ reinterpret_cast(EventRecord->UserData) }; BOOL result = RpcEvent(EventRecord, eventHeader, RPCServerCall); break; } default: { break; } } } if (eventHeader->ProviderId == Network) { switch (eventDescriptor->Id) { case 10: { auto data{ reinterpret_cast(EventRecord->UserData) }; const wchar_t* Initiated = L"True"; BOOL result = WriteNetworkEvents(EventRecord, eventHeader, (wchar_t*)Initiated); break; } case 11: { const wchar_t* Initiated = L"False"; auto data{ reinterpret_cast(EventRecord->UserData) }; BOOL result = WriteNetworkEvents(EventRecord, eventHeader, (wchar_t*)Initiated); break; } default: { break; } } } if (eventHeader->ProviderId == DotNet) { switch (eventDescriptor->Id) { case 154: { auto data{ reinterpret_cast(EventRecord->UserData) }; //printf("DotNet AssemblyLoad Event from PID %d\n", eventHeader->ProcessId); WriteDotNetEvents(EventRecord, eventHeader); } default: { break; } } } if (eventHeader->ProviderId == AMSI) { BOOL res = WriteAMSIEvents(EventRecord, eventHeader); } if (eventHeader->ProviderId == TaskSched) { BOOL res = WriteTaskSchedEvents(EventRecord, eventHeader); } if (eventHeader->ProviderId == WMIActivty) { BOOL res = WriteWMIEvents(EventRecord, eventHeader); } if (eventHeader->ProviderId == DPAPI) { BOOL res = DPAPIEvents(EventRecord, eventHeader); } } NTSTATUS WriteETWEvents( _In_ PEVENT_DATA_DESCRIPTOR eventData, _In_ EVENT_DESCRIPTOR eventDescriptor, _In_ int metaDataSize ) { REGHANDLE RegistrationHandle = NULL; NTSTATUS status = EventRegister( &JonMonGuid, NULL, NULL, &RegistrationHandle ); if (status != ERROR_SUCCESS) { return status; } status = EventWrite( RegistrationHandle, &eventDescriptor, metaDataSize, eventData ); if (status != ERROR_SUCCESS) { EventUnregister(RegistrationHandle); return status; } //CleanUp EventUnregister(RegistrationHandle); } NTSTATUS WriteThreatIntelEvents( _In_ PEVENT_RECORD EventRecord, _In_ PEVENT_HEADER EventHeader ) { PEVENT_HEADER eventHeader = &EventRecord->EventHeader; PEVENT_HEADER_EXTENDED_DATA_ITEM extendedData = EventRecord->ExtendedData; PEVENT_DESCRIPTOR eventDescriptor = &eventHeader->EventDescriptor; NTSTATUS status = ERROR_SUCCESS; REGHANDLE RegistrationHandle = NULL; HANDLE hProcess = GetCurrentProcess(); wchar_t* sourceImagePath = nullptr; wchar_t* targetImagePath = nullptr; std::wstring ImagePath_str; std::wstring targetImagePath_str; wchar_t* CallStack = nullptr; static UINT32 prevCallingProcessId = 0; static UINT32 prevTargetProcessId = 0; switch (eventHeader->EventDescriptor.Id) { case 1: { auto data{ reinterpret_cast(EventRecord->UserData) }; auto CallingProcessId{ GetData(data) }; auto CallingProcessCreationTime{ GetData(data) }; auto CallingProcessStartKey{ GetData(data) }; auto CallingProcessSignatureLevel{ GetData(data) }; auto CallingProcessSectionSignatureLevel{ GetData(data) }; auto CallingProcessProtection{ GetData(data) }; auto CallingThreadId{ GetData(data) }; auto CallingThreadCreationTime{ GetData(data) }; auto TargetProcessId{ GetData(data) }; auto TargetProcessCreateTime{ GetData(data) }; auto TargetProcessStartKey{ GetData(data) }; auto TargetProcessSignatureLevel{ GetData(data) }; auto TargetProcessSectionSignatureLevel{ GetData(data) }; auto TargetProcessProtection{ GetData(data) }; auto OriginalProcessId{ GetData(data) }; auto OriginalProcessCreateTime{ GetData(data) }; auto OriginalProcessStartKey{ GetData(data) }; auto OriginalProcessSignatureLevel{ GetData(data) }; auto OriginalProcessProtection{ GetData(data) }; auto BaseAddress{ GetData(data) }; if (*CallingProcessId == *TargetProcessId) { goto Exit; } if (GetImagePath(*CallingProcessId, &sourceImagePath) != ERROR_SUCCESS) { ImagePath_str = L"Unknown"; } else { ImagePath_str = sourceImagePath; } if (GetImagePath(*TargetProcessId, &targetImagePath) != ERROR_SUCCESS) { targetImagePath_str = L"Unknown"; } else { targetImagePath_str = targetImagePath; } CallStack = GetCallStack(EventRecord, extendedData, hProcess); FILETIME st; GetSystemTimeAsFileTime(&st); EVENT_DATA_DESCRIPTOR EventData[11]; EventDataDescCreate(&EventData[0], &st, sizeof(st)); EventDataDescCreate(&EventData[1], CallingThreadId, 4); EventDataDescCreate(&EventData[2], CallingProcessId, 4); EventDataDescCreate(&EventData[3], TargetProcessId, 4); EventDataDescCreate(&EventData[4], CallingProcessStartKey, 8); EventDataDescCreate(&EventData[5], TargetProcessStartKey, 8); EventDataDescCreate(&EventData[6], OriginalProcessId, 4); EventDataDescCreate(&EventData[7], BaseAddress, sizeof(BaseAddress)); EventDataDescCreate(&EventData[8], ImagePath_str.c_str(), (wcslen(ImagePath_str.c_str()) + 1) * sizeof(WCHAR)); EventDataDescCreate(&EventData[9], targetImagePath_str.c_str(), (wcslen(targetImagePath_str.c_str()) + 1) * sizeof(WCHAR)); EventDataDescCreate(&EventData[10], CallStack, (wcslen(CallStack) + 1) * sizeof(WCHAR)); status = WriteETWEvents(EventData, TIRemoteAllocateVirtualMemory, 11); goto Exit; } case 4: { FILETIME st; GetSystemTimeAsFileTime(&st); PTRACE_EVENT_INFO pInfo = NULL; DWORD bufferSize = 0; UINT32 CallingThreadId, CallingProcessId, TargetProcessId, OriginalProcessId, TargetThreadId; UINT64 CallingProcessStartKey, TargetProcessStartKey, ApcRoutine, ApcArgument1; DWORD status = ERROR_SUCCESS; // // Testing out TDH APIs // status = TdhGetEventInformation(EventRecord, 0, NULL, pInfo, &bufferSize); if (ERROR_INSUFFICIENT_BUFFER == status) { pInfo = (PTRACE_EVENT_INFO)malloc(bufferSize); if (pInfo == NULL) { // Handle allocation failure OutputDebugString(L"[!] Error allocating memory for event info\n"); goto Exit; } // Get the event info status = TdhGetEventInformation(EventRecord, 0, NULL, pInfo, &bufferSize); } if (ERROR_SUCCESS != status) { // Handle error (could not obtain event info) free(pInfo); OutputDebugString(L"[!] Error getting event info\n"); goto Exit; } for (ULONG i = 0; i < pInfo->TopLevelPropertyCount; i++) { PROPERTY_DATA_DESCRIPTOR dataDescriptor; DWORD propertySize = 0; WCHAR* propertyName = (WCHAR*)((BYTE*)pInfo + pInfo->EventPropertyInfoArray[i].NameOffset); dataDescriptor.PropertyName = (ULONGLONG)propertyName; dataDescriptor.ArrayIndex = ULONG_MAX; // Determine the size of the property status = TdhGetPropertySize(EventRecord, 0, NULL, 1, &dataDescriptor, &propertySize); if (status != ERROR_SUCCESS) { // Handle error wprintf(L"Error getting size for property %ls\n", propertyName); continue; } BYTE* propertyData = (BYTE*)malloc(propertySize); if (!propertyData) { // Handle allocation failure wprintf(L"Error allocating memory for property %ls\n", propertyName); continue; } // Get the property data status = TdhGetProperty(EventRecord, 0, NULL, 1, &dataDescriptor, propertySize, propertyData); if (status != ERROR_SUCCESS) { // Handle error wprintf(L"Error getting data for property %ls\n", propertyName); free(propertyData); continue; } switch (i) { case 0: { CallingProcessId = *(UINT32*)propertyData; break; } case 2: { CallingProcessStartKey = *(UINT64*)propertyData; break; } case 6: { CallingThreadId = *(UINT32*)propertyData; break; } case 8: { TargetProcessId = *(UINT32*)propertyData; break; } case 10: { TargetProcessStartKey = *(UINT64*)propertyData; break; } case 14: { TargetThreadId = *(UINT32*)propertyData; } case 16: { OriginalProcessId = *(UINT32*)propertyData; break; } case 21: { ApcRoutine = *(UINT64*)propertyData; break; } case 22: { ApcArgument1 = *(UINT64*)propertyData; break; } default: { break; } } free(propertyData); } if (GetImagePath(CallingProcessId, &sourceImagePath) != ERROR_SUCCESS) { ImagePath_str = L"Unknown"; } else { ImagePath_str = sourceImagePath; } if (GetImagePath(TargetProcessId, &targetImagePath) != ERROR_SUCCESS) { targetImagePath_str = L"Unknown"; } else { targetImagePath_str = targetImagePath; } CallStack = GetCallStack(EventRecord, extendedData, hProcess); EVENT_DATA_DESCRIPTOR EventData[13]; EventDataDescCreate(&EventData[0], &st, sizeof(st)); EventDataDescCreate(&EventData[1], &CallingThreadId, 4); EventDataDescCreate(&EventData[2], &CallingProcessId, 4); EventDataDescCreate(&EventData[3], &TargetProcessId, 4); EventDataDescCreate(&EventData[4], &TargetThreadId, 4); EventDataDescCreate(&EventData[5], &CallingProcessStartKey, 8); EventDataDescCreate(&EventData[6], &TargetProcessStartKey, 8); EventDataDescCreate(&EventData[7], &OriginalProcessId, 4); EventDataDescCreate(&EventData[8], &ApcRoutine, sizeof(ApcRoutine)); EventDataDescCreate(&EventData[9], &ApcArgument1, sizeof(ApcArgument1)); EventDataDescCreate(&EventData[10], ImagePath_str.c_str(), (wcslen(ImagePath_str.c_str()) + 1) * sizeof(WCHAR)); EventDataDescCreate(&EventData[11], targetImagePath_str.c_str(), (wcslen(targetImagePath_str.c_str()) + 1) * sizeof(WCHAR)); EventDataDescCreate(&EventData[12], CallStack, (wcslen(CallStack) + 1) * sizeof(WCHAR)); status = WriteETWEvents(EventData, TIQueueUserAPCEvent, 13); goto Exit; } case 6: { auto data{ reinterpret_cast(EventRecord->UserData) }; auto CallingProcessId{ GetData(data) }; auto CallingProcessCreationTime{ GetData(data) }; auto CallingProcessStartKey{ GetData(data) }; auto CallingProcessSignatureLevel{ GetData(data) }; auto CallingProcessSectionSignatureLevel{ GetData(data) }; auto CallingProcessProtection{ GetData(data) }; auto CallingThreadId{ GetData(data) }; auto CallingThreadCreationTime{ GetData(data) }; auto TargetProcessId{ GetData(data) }; auto TargetProcessCreateTime{ GetData(data) }; auto TargetProcessStartKey{ GetData(data) }; auto TargetProcessSignatureLevel{ GetData(data) }; auto TargetProcessSectionSignatureLevel{ GetData(data) }; auto TargetProcessProtection{ GetData(data) }; auto OriginalProcessId{ GetData(data) }; auto OriginalProcessCreateTime{ GetData(data) }; auto OriginalProcessStartKey{ GetData(data) }; auto OriginalProcessSignatureLevel{ GetData(data) }; auto OriginalProcessProtection{ GetData(data) }; auto BaseAddress{ GetData(data) }; if (*CallingProcessId == *TargetProcessId) { goto Exit; } if (GetImagePath(*CallingProcessId, &sourceImagePath) != ERROR_SUCCESS) { ImagePath_str = L"Unknown"; } else { ImagePath_str = sourceImagePath; } if (GetImagePath(*TargetProcessId, &targetImagePath) != ERROR_SUCCESS) { targetImagePath_str = L"Unknown"; } else { targetImagePath_str = targetImagePath; } CallStack = GetCallStack(EventRecord, extendedData, hProcess); FILETIME st; GetSystemTimeAsFileTime(&st); EVENT_DATA_DESCRIPTOR EventData[11]; EventDataDescCreate(&EventData[0], &st, sizeof(st)); EventDataDescCreate(&EventData[1], CallingThreadId, 4); EventDataDescCreate(&EventData[2], CallingProcessId, 4); EventDataDescCreate(&EventData[3], TargetProcessId, 4); EventDataDescCreate(&EventData[4], CallingProcessStartKey, 8); EventDataDescCreate(&EventData[5], TargetProcessStartKey, 8); EventDataDescCreate(&EventData[6], OriginalProcessId, 4); EventDataDescCreate(&EventData[7], BaseAddress, sizeof(BaseAddress)); EventDataDescCreate(&EventData[8], ImagePath_str.c_str(), (wcslen(ImagePath_str.c_str()) + 1) * sizeof(WCHAR)); EventDataDescCreate(&EventData[9], targetImagePath_str.c_str(), (wcslen(targetImagePath_str.c_str()) + 1) * sizeof(WCHAR)); EventDataDescCreate(&EventData[10], CallStack, (wcslen(CallStack) + 1) * sizeof(WCHAR)); status = WriteETWEvents(EventData, TIRemoteAllocateVirtualMemory, 11); goto Exit; } case 13: { auto data{ reinterpret_cast(EventRecord->UserData) }; auto OperationStatus{ GetData(data) }; auto CallingProcessId{ GetData(data) }; auto CallingProcessCreationTime{ GetData(data) }; auto CallingProcessStartKey{ GetData(data) }; auto CallingProcessSignatureLevel{ GetData(data) }; auto CallingProcessSectionSignatureLevel{ GetData(data) }; auto CallingProcessProtection{ GetData(data) }; auto CallingThreadId{ GetData(data) }; auto CallingThreadCreationTime{ GetData(data) }; auto TargetProcessId{ GetData(data) }; auto TargetProcessCreationTime{ GetData(data) }; auto TargetProcessStartKey{ GetData(data) }; FILETIME st; GetSystemTimeAsFileTime(&st); CallStack = GetCallStack(EventRecord, extendedData, hProcess); // //Getting ImagePath // if (GetImagePath(*CallingProcessId, &sourceImagePath) != ERROR_SUCCESS) { ImagePath_str = L"Unknown"; } else { ImagePath_str = sourceImagePath; } // //Put C:\Windows\System32\lsass.exe in a variable // std::wstring lsassPath = L"C:\\Windows\\System32\\lsass.exe"; EVENT_DATA_DESCRIPTOR EventData[9]; EventDataDescCreate(&EventData[0], &st, sizeof(st)); EventDataDescCreate(&EventData[1], CallingProcessId, 4); EventDataDescCreate(&EventData[2], CallingThreadId, 4); EventDataDescCreate(&EventData[3], ImagePath_str.c_str(), (wcslen(ImagePath_str.c_str()) + 1) * sizeof(WCHAR)); EventDataDescCreate(&EventData[4], TargetProcessId, 4); EventDataDescCreate(&EventData[5], lsassPath.c_str(), (wcslen(lsassPath.c_str()) + 1) * sizeof(WCHAR)); EventDataDescCreate(&EventData[6], CallingProcessStartKey, sizeof(CallingProcessStartKey)); EventDataDescCreate(&EventData[7], TargetProcessStartKey, sizeof(TargetProcessStartKey)); EventDataDescCreate(&EventData[8], CallStack, (wcslen(CallStack) + 1) * sizeof(WCHAR)); NTSTATUS status = WriteETWEvents(EventData, TIReadProcessMemory, 9); goto Exit; } case 14: { auto data{ reinterpret_cast(EventRecord->UserData) }; auto OperationStatus{ GetData(data) }; auto CallingProcessId{ GetData(data) }; auto CallingProcessCreationTime{ GetData(data) }; auto CallingProcessStartKey{ GetData(data) }; auto CallingProcessSignatureLevel{ GetData(data) }; auto CallingProcessSectionSignatureLevel{ GetData(data) }; auto CallingProcessProtection{ GetData(data) }; auto CallingThreadId{ GetData(data) }; auto CallingThreadCreationTime{ GetData(data) }; auto TargetProcessId{ GetData(data) }; auto TargetProcessCreationTime{ GetData(data) }; auto TargetProcessStartKey{ GetData(data) }; FILETIME st; GetSystemTimeAsFileTime(&st); CallStack = GetCallStack(EventRecord, extendedData, hProcess); if (GetImagePath(*CallingProcessId, &sourceImagePath) != ERROR_SUCCESS) { ImagePath_str = L"Unknown"; } else { ImagePath_str = sourceImagePath; } if (GetImagePath(*TargetProcessId, &targetImagePath) != ERROR_SUCCESS) { targetImagePath_str = L"Unknown"; } else { targetImagePath_str = targetImagePath; } EVENT_DATA_DESCRIPTOR EventData[9]; EventDataDescCreate(&EventData[0], &st, sizeof(st)); EventDataDescCreate(&EventData[1], CallingProcessId, 4); EventDataDescCreate(&EventData[2], CallingThreadId, 4); EventDataDescCreate(&EventData[3], ImagePath_str.c_str(), (wcslen(ImagePath_str.c_str()) + 1) * sizeof(WCHAR)); EventDataDescCreate(&EventData[4], TargetProcessId, 4); EventDataDescCreate(&EventData[5], targetImagePath_str.c_str(), (wcslen(targetImagePath_str.c_str()) + 1) * sizeof(WCHAR)); EventDataDescCreate(&EventData[6], CallingProcessStartKey, sizeof(CallingProcessStartKey)); EventDataDescCreate(&EventData[7], TargetProcessStartKey, sizeof(TargetProcessStartKey)); EventDataDescCreate(&EventData[8], CallStack, (wcslen(CallStack) + 1) * sizeof(WCHAR)); NTSTATUS status = WriteETWEvents(EventData, TIWriteProcessMemory, 9); goto Exit; } case 21: { auto data{ reinterpret_cast(EventRecord->UserData) }; auto CallingProcessId{ GetData(data) }; auto CallingProcessCreationTime{ GetData(data) }; auto CallingProcessStartKey{ GetData(data) }; auto CallingProcessSignatureLevel{ GetData(data) }; auto CallingProcessSectionSignatureLevel{ GetData(data) }; auto CallingProcessProtection{ GetData(data) }; auto CallingThreadId{ GetData(data) }; auto CallingThreadCreationTime{ GetData(data) }; auto TargetProcessId{ GetData(data) }; auto TargetProcessCreateTime{ GetData(data) }; auto TargetProcessStartKey{ GetData(data) }; auto TargetProcessSignatureLevel{ GetData(data) }; auto TargetProcessSectionSignatureLevel{ GetData(data) }; auto TargetProcessProtection{ GetData(data) }; auto OriginalProcessId{ GetData(data) }; auto OriginalProcessCreateTime{ GetData(data) }; auto OriginalProcessStartKey{ GetData(data) }; auto OriginalProcessSignatureLevel{ GetData(data) }; auto OriginalProcessProtection{ GetData(data) }; auto BaseAddress{ GetData(data) }; if (*CallingProcessId == *TargetProcessId) { goto Exit; } if (GetImagePath(*CallingProcessId, &sourceImagePath) != ERROR_SUCCESS) { ImagePath_str = L"Unknown"; } else { ImagePath_str = sourceImagePath; } if (GetImagePath(*TargetProcessId, &targetImagePath) != ERROR_SUCCESS) { targetImagePath_str = L"Unknown"; } else { targetImagePath_str = targetImagePath; } CallStack = GetCallStack(EventRecord, extendedData, hProcess); FILETIME st; GetSystemTimeAsFileTime(&st); EVENT_DATA_DESCRIPTOR EventData[11]; EventDataDescCreate(&EventData[0], &st, sizeof(st)); EventDataDescCreate(&EventData[1], CallingThreadId, 4); EventDataDescCreate(&EventData[2], CallingProcessId, 4); EventDataDescCreate(&EventData[3], TargetProcessId, 4); EventDataDescCreate(&EventData[4], CallingProcessStartKey, 8); EventDataDescCreate(&EventData[5], TargetProcessStartKey, 8); EventDataDescCreate(&EventData[6], OriginalProcessId, 4); EventDataDescCreate(&EventData[7], BaseAddress, sizeof(BaseAddress)); EventDataDescCreate(&EventData[8], ImagePath_str.c_str(), (wcslen(ImagePath_str.c_str()) + 1) * sizeof(WCHAR)); EventDataDescCreate(&EventData[9], targetImagePath_str.c_str(), (wcslen(targetImagePath_str.c_str()) + 1) * sizeof(WCHAR)); EventDataDescCreate(&EventData[10], CallStack, (wcslen(CallStack) + 1) * sizeof(WCHAR)); status = WriteETWEvents(EventData, TIRemoteAllocateVirtualMemory, 11); goto Exit; } case 24: { FILETIME st; GetSystemTimeAsFileTime(&st); PTRACE_EVENT_INFO pInfo = NULL; DWORD bufferSize = 0; UINT32 CallingThreadId, CallingProcessId, TargetProcessId, OriginalProcessId, TargetThreadId; UINT64 CallingProcessStartKey, TargetProcessStartKey, ApcRoutine, ApcArgument1; DWORD status = ERROR_SUCCESS; // // Testing out TDH APIs // status = TdhGetEventInformation(EventRecord, 0, NULL, pInfo, &bufferSize); if (ERROR_INSUFFICIENT_BUFFER == status) { pInfo = (PTRACE_EVENT_INFO)malloc(bufferSize); if (pInfo == NULL) { // Handle allocation failure OutputDebugString(L"[!] Error allocating memory for event info\n"); goto Exit; } // Get the event info status = TdhGetEventInformation(EventRecord, 0, NULL, pInfo, &bufferSize); } if (ERROR_SUCCESS != status) { // Handle error (could not obtain event info) free(pInfo); OutputDebugString(L"[!] Error getting event info\n"); goto Exit; } for (ULONG i = 0; i < pInfo->TopLevelPropertyCount; i++) { PROPERTY_DATA_DESCRIPTOR dataDescriptor; DWORD propertySize = 0; WCHAR* propertyName = (WCHAR*)((BYTE*)pInfo + pInfo->EventPropertyInfoArray[i].NameOffset); dataDescriptor.PropertyName = (ULONGLONG)propertyName; dataDescriptor.ArrayIndex = ULONG_MAX; // Determine the size of the property status = TdhGetPropertySize(EventRecord, 0, NULL, 1, &dataDescriptor, &propertySize); if (status != ERROR_SUCCESS) { // Handle error wprintf(L"Error getting size for property %ls\n", propertyName); continue; } BYTE* propertyData = (BYTE*)malloc(propertySize); if (!propertyData) { // Handle allocation failure wprintf(L"Error allocating memory for property %ls\n", propertyName); continue; } // Get the property data status = TdhGetProperty(EventRecord, 0, NULL, 1, &dataDescriptor, propertySize, propertyData); if (status != ERROR_SUCCESS) { // Handle error wprintf(L"Error getting data for property %ls\n", propertyName); free(propertyData); continue; } switch (i) { case 0: { CallingProcessId = *(UINT32*)propertyData; break; } case 2: { CallingProcessStartKey = *(UINT64*)propertyData; break; } case 6: { CallingThreadId = *(UINT32*)propertyData; break; } case 8: { TargetProcessId = *(UINT32*)propertyData; break; } case 10: { TargetProcessStartKey = *(UINT64*)propertyData; break; } case 14: { TargetThreadId = *(UINT32*)propertyData; } case 16: { OriginalProcessId = *(UINT32*)propertyData; break; } case 21: { ApcRoutine = *(UINT64*)propertyData; break; } case 22: { ApcArgument1 = *(UINT64*)propertyData; break; } default: { break; } } free(propertyData); } if (GetImagePath(CallingProcessId, &sourceImagePath) != ERROR_SUCCESS) { ImagePath_str = L"Unknown"; } else { ImagePath_str = sourceImagePath; } if (GetImagePath(TargetProcessId, &targetImagePath) != ERROR_SUCCESS) { targetImagePath_str = L"Unknown"; } else { targetImagePath_str = targetImagePath; } CallStack = GetCallStack(EventRecord, extendedData, hProcess); EVENT_DATA_DESCRIPTOR EventData[13]; EventDataDescCreate(&EventData[0], &st, sizeof(st)); EventDataDescCreate(&EventData[1], &CallingThreadId, 4); EventDataDescCreate(&EventData[2], &CallingProcessId, 4); EventDataDescCreate(&EventData[3], &TargetProcessId, 4); EventDataDescCreate(&EventData[4], &TargetThreadId, 4); EventDataDescCreate(&EventData[5], &CallingProcessStartKey, 8); EventDataDescCreate(&EventData[6], &TargetProcessStartKey, 8); EventDataDescCreate(&EventData[7], &OriginalProcessId, 4); EventDataDescCreate(&EventData[8], &ApcRoutine, sizeof(ApcRoutine)); EventDataDescCreate(&EventData[9], &ApcArgument1, sizeof(ApcArgument1)); EventDataDescCreate(&EventData[10], ImagePath_str.c_str(), (wcslen(ImagePath_str.c_str()) + 1) * sizeof(WCHAR)); EventDataDescCreate(&EventData[11], targetImagePath_str.c_str(), (wcslen(targetImagePath_str.c_str()) + 1) * sizeof(WCHAR)); EventDataDescCreate(&EventData[12], CallStack, (wcslen(CallStack) + 1) * sizeof(WCHAR)); status = WriteETWEvents(EventData, TIQueueUserAPCEvent, 13); goto Exit; } case 26: { auto data{ reinterpret_cast(EventRecord->UserData) }; auto CallingProcessId{ GetData(data) }; auto CallingProcessCreationTime{ GetData(data) }; auto CallingProcessStartKey{ GetData(data) }; auto CallingProcessSignatureLevel{ GetData(data) }; auto CallingProcessSectionSignatureLevel{ GetData(data) }; auto CallingProcessProtection{ GetData(data) }; auto CallingThreadId{ GetData(data) }; auto CallingThreadCreationTime{ GetData(data) }; auto TargetProcessId{ GetData(data) }; auto TargetProcessCreateTime{ GetData(data) }; auto TargetProcessStartKey{ GetData(data) }; auto TargetProcessSignatureLevel{ GetData(data) }; auto TargetProcessSectionSignatureLevel{ GetData(data) }; auto TargetProcessProtection{ GetData(data) }; auto OriginalProcessId{ GetData(data) }; auto OriginalProcessCreateTime{ GetData(data) }; auto OriginalProcessStartKey{ GetData(data) }; auto OriginalProcessSignatureLevel{ GetData(data) }; auto OriginalProcessProtection{ GetData(data) }; auto BaseAddress{ GetData(data) }; if (*CallingProcessId == *TargetProcessId) { goto Exit; } if (GetImagePath(*CallingProcessId, &sourceImagePath) != ERROR_SUCCESS) { ImagePath_str = L"Unknown"; } else { ImagePath_str = sourceImagePath; } if (GetImagePath(*TargetProcessId, &targetImagePath) != ERROR_SUCCESS) { targetImagePath_str = L"Unknown"; } else { targetImagePath_str = targetImagePath; } CallStack = GetCallStack(EventRecord, extendedData, hProcess); FILETIME st; GetSystemTimeAsFileTime(&st); EVENT_DATA_DESCRIPTOR EventData[11]; EventDataDescCreate(&EventData[0], &st, sizeof(st)); EventDataDescCreate(&EventData[1], CallingThreadId, 4); EventDataDescCreate(&EventData[2], CallingProcessId, 4); EventDataDescCreate(&EventData[3], TargetProcessId, 4); EventDataDescCreate(&EventData[4], CallingProcessStartKey, 8); EventDataDescCreate(&EventData[5], TargetProcessStartKey, 8); EventDataDescCreate(&EventData[6], OriginalProcessId, 4); EventDataDescCreate(&EventData[7], BaseAddress, sizeof(BaseAddress)); EventDataDescCreate(&EventData[8], ImagePath_str.c_str(), (wcslen(ImagePath_str.c_str()) + 1) * sizeof(WCHAR)); EventDataDescCreate(&EventData[9], targetImagePath_str.c_str(), (wcslen(targetImagePath_str.c_str()) + 1) * sizeof(WCHAR)); EventDataDescCreate(&EventData[10], CallStack, (wcslen(CallStack) + 1) * sizeof(WCHAR)); status = WriteETWEvents(EventData, TIRemoteAllocateVirtualMemory, 11); goto Exit; } default: { goto Exit; } } Exit: if (sourceImagePath != nullptr) { delete[] sourceImagePath; } if (targetImagePath != nullptr) { delete[] targetImagePath; } if (CallStack != nullptr) { delete[] CallStack; } return 0; } BOOL WriteNetworkEvents( _In_ PEVENT_RECORD EventRecord, _In_ PEVENT_HEADER EventHeader, _In_ wchar_t* Initiated ) { WCHAR wide_deststring_ip[INET_ADDRSTRLEN]; WCHAR wide_sourcestring_ip[INET_ADDRSTRLEN]; struct in_addr srceaddr = {}; struct in_addr destaddr = {}; UINT16 sourcePort, destPort; wchar_t* username = nullptr; wchar_t* pImagePath = nullptr; std::wstring ImagePath_str; std::wstring username_str; std::wstring sourcePort_str; std::wstring destPort_str; BOOL status = FALSE; REGHANDLE RegistrationHandle = NULL; auto data{ reinterpret_cast(EventRecord->UserData) }; auto PID{ GetData(data) }; auto size{ GetData(data) }; auto daddr{ GetData(data) }; auto saddr{ GetData(data) }; auto dport{ GetData(data) }; auto sport{ GetData(data) }; if (*PID == 4) { goto Exit; } if (Initiated == L"True") { destaddr.s_addr = *daddr; srceaddr.s_addr = *saddr; sourcePort == *sport; destPort == *dport; sourcePort_str = std::to_wstring(*sport); destPort_str = std::to_wstring(*dport); } if (Initiated == L"False") { destaddr.s_addr = *saddr; srceaddr.s_addr = *daddr; sourcePort = *dport; destPort = *sport; sourcePort_str = std::to_wstring(*dport); destPort_str = std::to_wstring(*sport); } // // convert port to widestring // // // add null terminator to wide string // sourcePort_str += L'\0'; destPort_str += L'\0'; if (&destaddr == NULL) { wide_deststring_ip[0] = '\0'; } else { InetNtop(AF_INET, &destaddr, wide_deststring_ip, INET_ADDRSTRLEN); } if (&srceaddr == NULL) { wide_sourcestring_ip[0] = '\0'; } else { InetNtop(AF_INET, &srceaddr, wide_sourcestring_ip, INET_ADDRSTRLEN); } // // removing ip addr 127.0.0.1 // if (wcscmp(wide_deststring_ip, L"127.0.0.1") == 0) { goto Exit; } // //Getting UserName // if (GetTokenUser(*PID, &username) != 0) { username_str = L"Unknown"; } else { username_str = username; } // //Getting ImagePath // if (GetImagePath(*PID, &pImagePath) != ERROR_SUCCESS) { ImagePath_str = L"Unknown"; } else { ImagePath_str = pImagePath; } FILETIME st; GetSystemTimeAsFileTime(&st); EVENT_DATA_DESCRIPTOR EventData[9]; EventDataDescCreate(&EventData[0], &st, sizeof(st)); EventDataDescCreate(&EventData[1], PID, 4); EventDataDescCreate(&EventData[2], &wide_sourcestring_ip, (wcslen(wide_sourcestring_ip) + 1) * sizeof(WCHAR)); EventDataDescCreate(&EventData[3], &wide_deststring_ip, (wcslen(wide_deststring_ip) + 1) * sizeof(WCHAR)); EventDataDescCreate(&EventData[4], &sourcePort, sizeof(UINT16)); EventDataDescCreate(&EventData[5], &destPort, sizeof(UINT16)); EventDataDescCreate(&EventData[6], Initiated, (wcslen(Initiated) + 1) * sizeof(WCHAR)); EventDataDescCreate(&EventData[7], username_str.c_str(), (wcslen(username_str.c_str()) + 1) * sizeof(WCHAR)); EventDataDescCreate(&EventData[8], ImagePath_str.c_str(), (wcslen(ImagePath_str.c_str()) + 1) * sizeof(WCHAR)); status = WriteETWEvents(EventData, NetworkConnectionAccepted, 9); Exit: if (pImagePath != nullptr) { delete[] pImagePath; } if (username != nullptr) { delete[] username; } return status; } BOOL WriteAMSIEvents( _In_ PEVENT_RECORD EventRecord, _In_ PEVENT_HEADER EventHeader ) { auto data{ reinterpret_cast(EventRecord->UserData) }; auto Session{ GetData(data) }; auto ScanStatus = GetData(data); auto ScanResult = GetData(data); auto AppName{ GetWideString(data) }; auto ContentName = GetData(data); auto ContentSize = GetData(data); auto OriginalSize = GetData(data); auto Content = GetData(data); FILETIME st; GetSystemTimeAsFileTime(&st); //Writing Event to ETW EVENT_DATA_DESCRIPTOR EventData[5]; EventDataDescCreate(&EventData[0], &st, sizeof(st)); EventDataDescCreate(&EventData[1], &EventHeader->ProcessId, 4); EventDataDescCreate(&EventData[2], AppName, (wcslen(AppName) + 1) * sizeof(WCHAR)); EventDataDescCreate(&EventData[3], ScanResult, 4); EventDataDescCreate(&EventData[4], ContentSize, 4); NTSTATUS status = WriteETWEvents(EventData, AMSIEvents, 5); return TRUE; } BOOL WriteDotNetEvents( _In_ PEVENT_RECORD EventRecord, _In_ PEVENT_HEADER EventHeader ) { auto data{ reinterpret_cast(EventRecord->UserData) }; auto AssemblyID{ GetData(data) }; auto AppDomainID{ GetData(data) }; auto BindingID{ GetData(data) }; auto AssemblyFlags{ GetData(data) }; auto FullyQualifiedAssemblyName{ GetWideString(data) }; auto ClrInstanceID{ GetData(data) }; wchar_t* username = nullptr; wchar_t* pImagePath = nullptr; std::wstring ImagePath_str; std::wstring username_str; REGHANDLE RegistrationHandle = NULL; if (EventHeader->ProcessId == 4) { return FALSE; } std::wistringstream wiss(FullyQualifiedAssemblyName); std::vector tokens; std::wstring token; while (std::getline(wiss, token, L',')) { tokens.push_back(token); } //Getting UserName if (GetTokenUser(EventHeader->ProcessId, &username) != 0) { username_str = L"Unknown - process potentially died"; } else { username_str = username; } //Getting ImagePath if (GetImagePath(EventHeader->ProcessId, &pImagePath) != ERROR_SUCCESS) { ImagePath_str = L"Unknown - process potentially died"; } else { ImagePath_str = pImagePath; } FILETIME st; GetSystemTimeAsFileTime(&st); //Writing Event to ETW EVENT_DATA_DESCRIPTOR EventData[6]; EventDataDescCreate(&EventData[0], &st, sizeof(st)); EventDataDescCreate(&EventData[1], &EventHeader->ProcessId, sizeof(ULONG)); EventDataDescCreate(&EventData[2], tokens[0].c_str(), (wcslen(tokens[0].c_str()) + 1) * sizeof(WCHAR)); EventDataDescCreate(&EventData[3], username_str.c_str(), (wcslen(username_str.c_str()) + 1) * sizeof(WCHAR)); EventDataDescCreate(&EventData[4], ImagePath_str.c_str(), (wcslen(ImagePath_str.c_str()) + 1) * sizeof(WCHAR)); EventDataDescCreate(&EventData[5], ClrInstanceID, sizeof(ClrInstanceID)); NTSTATUS status = WriteETWEvents(EventData, DotNetLoad, 6); Exit: if (pImagePath != nullptr) { delete[] pImagePath; } if (username != nullptr) { delete[] username; } return TRUE; } BOOL WriteTaskSchedEvents( _In_ PEVENT_RECORD EventRecord, _In_ PEVENT_HEADER EventHeader ) { switch (EventHeader->EventDescriptor.Id) { case 106: { auto data{ reinterpret_cast(EventRecord->UserData) }; auto TaskName{ GetWideString(data) }; auto UserContext{ GetWideString(data) }; FILETIME st; GetSystemTimeAsFileTime(&st); EVENT_DATA_DESCRIPTOR EventData[4]; EventDataDescCreate(&EventData[0], &st, sizeof(st)); EventDataDescCreate(&EventData[1], TaskName, (wcslen(TaskName) + 1) * sizeof(WCHAR)); EventDataDescCreate(&EventData[2], UserContext, (wcslen(UserContext) + 1) * sizeof(WCHAR)); EventDataDescCreate(&EventData[3], &EventHeader->ProcessId, 4); NTSTATUS status = WriteETWEvents(EventData, SchedTaskCreation, 4); break; } case 129: { auto data{ reinterpret_cast(EventRecord->UserData) }; auto TaskName{ GetWideString(data) }; auto Path{ GetWideString(data) }; auto ProcessId = GetData(data); FILETIME st; GetSystemTimeAsFileTime(&st); EVENT_DATA_DESCRIPTOR EventData[4]; EventDataDescCreate(&EventData[0], &st, sizeof(st)); EventDataDescCreate(&EventData[1], TaskName, (wcslen(TaskName) + 1) * sizeof(WCHAR)); EventDataDescCreate(&EventData[2], Path, (wcslen(Path) + 1) * sizeof(WCHAR)); EventDataDescCreate(&EventData[3], ProcessId, 4); NTSTATUS status = WriteETWEvents(EventData, SchedTaskStarted, 4); break; } default: { break; } } return TRUE; } BOOL WriteWMIEvents( _In_ PEVENT_RECORD EventRecord, _In_ PEVENT_HEADER EventHeader ) { switch (EventHeader->EventDescriptor.Id) { case 5861: { auto data{ reinterpret_cast(EventRecord->UserData) }; auto Namespace{ GetWideString(data) }; auto ESS{ GetWideString(data) }; auto Consumer{ GetWideString(data) }; auto PossibleCause{ GetWideString(data) }; FILETIME st; GetSystemTimeAsFileTime(&st); EVENT_DATA_DESCRIPTOR EventData[5]; EventDataDescCreate(&EventData[0], &st, sizeof(st)); EventDataDescCreate(&EventData[1], Namespace, (wcslen(Namespace) + 1) * sizeof(WCHAR)); EventDataDescCreate(&EventData[2], ESS, (wcslen(ESS) + 1) * sizeof(WCHAR)); EventDataDescCreate(&EventData[3], Consumer, (wcslen(Consumer) + 1) * sizeof(WCHAR)); EventDataDescCreate(&EventData[4], PossibleCause, (wcslen(PossibleCause) + 1) * sizeof(WCHAR)); NTSTATUS status = WriteETWEvents(EventData, WMIFilterToConsumerBinding, 5); break; } } return TRUE; } wchar_t* GetCallStack( _In_ PEVENT_RECORD EventRecord, _In_ PEVENT_HEADER_EXTENDED_DATA_ITEM extendedData, _In_ HANDLE hProcess ) { std::string sSymSearchPathBuf; const char* szSymSearchPath = nullptr; szSymSearchPath = "srv*http://msdl.microsoft.com/download/symbols"; SymSetOptions(SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS | SYMOPT_INCLUDE_32BIT_MODULES | SYMOPT_CASE_INSENSITIVE | SYMOPT_ALLOW_ZERO_ADDRESS | SYMOPT_ALLOW_ABSOLUTE_SYMBOLS); BOOL ret = SymInitialize(hProcess, szSymSearchPath, TRUE); if (!ret) { printf("[!] SymInitialize failed: %d\n", GetLastError()); } if (EventRecord->ExtendedDataCount != 0) { const int MAX_SYM_NAME_LEN = 1024; std::wstring wtext; for (USHORT i = 0; i < EventRecord->ExtendedDataCount; i++) { if (extendedData[i].ExtType == EVENT_HEADER_EXT_TYPE_STACK_TRACE64) { auto stacktrace = reinterpret_cast(extendedData[i].DataPtr); int stack_length = extendedData[i].DataSize / sizeof(ULONG64); for (int j = 0; j < stack_length; j++) { DWORD64 dwDisplacement; DWORD temp; DWORD64 dwAddress = stacktrace->Address[j]; char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME_LEN * sizeof(TCHAR)]; PSYMBOL_INFOW pSymbol = (PSYMBOL_INFOW)buffer; pSymbol->SizeOfStruct = sizeof(SYMBOL_INFOW); pSymbol->MaxNameLen = MAX_SYM_NAME_LEN; if (SymFromAddrW(hProcess, dwAddress, &dwDisplacement, pSymbol)) { wtext += pSymbol->Name; } else { wtext += L""; } wtext += L" "; } } } wtext.erase(wtext.size() - 2); size_t wtext_len = wtext.length() + 1; wchar_t* result = new wchar_t[wtext_len]; wcscpy_s(result, wtext_len, wtext.c_str()); return result; } SymCleanup(hProcess); } BOOL WriteRPCEvent( _In_ PEVENT_RECORD EventRecord, _In_ PEVENT_HEADER EventHeader, _In_ EVENT_DESCRIPTOR RPCEvent, _In_ wchar_t* InterfaceString, _In_ wchar_t* MethodString, _In_ wchar_t* szInterfaceUUID, _In_ wchar_t* CallStack ) { //Getting Data wchar_t* username = nullptr; std::wstring username_str; wchar_t* pImagePath = nullptr; std::wstring ImagePath_str; PEVENT_HEADER_EXTENDED_DATA_ITEM extendedData = EventRecord->ExtendedData; HANDLE hProcess = GetCurrentProcess(); auto data{ reinterpret_cast(EventRecord->UserData) }; auto interfaceUUID{ GetData(data) }; auto procNum{ GetData(data) }; auto protocol{ GetData(data) }; auto networkAddress{ GetWideString(data) }; auto endpoint{ GetWideString(data) }; auto options{ GetWideString(data) }; auto authenticationLevel{ GetData(data) }; auto authenticationService{ GetData(data) }; auto impersonationLevel{ GetData(data) }; //Getting UserName if (GetTokenUser(EventHeader->ProcessId, &username) != 0) { username_str = L"Unknown"; } else { username_str = username; } //Getting ImagePath if (GetImagePath((DWORD)EventHeader->ProcessId, &pImagePath) != 0) { ImagePath_str = L"Unknown - process potentially died"; } else { ImagePath_str = pImagePath; } FILETIME st; GetSystemTimeAsFileTime(&st); //Writing Event to ETW EVENT_DATA_DESCRIPTOR EventData[12]; EventDataDescCreate(&EventData[0], &st, sizeof(st)); EventDataDescCreate(&EventData[1], szInterfaceUUID, (wcslen(szInterfaceUUID) + 1) * sizeof(WCHAR)); EventDataDescCreate(&EventData[2], procNum, 4); EventDataDescCreate(&EventData[3], protocol, 4); EventDataDescCreate(&EventData[4], &EventHeader->ProcessId, 4); EventDataDescCreate(&EventData[5], networkAddress, (wcslen(networkAddress) + 1) * sizeof(WCHAR)); EventDataDescCreate(&EventData[6], endpoint, (wcslen(endpoint) + 1) * sizeof(WCHAR)); EventDataDescCreate(&EventData[7], InterfaceString, (wcslen(InterfaceString) + 1) * sizeof(WCHAR)); EventDataDescCreate(&EventData[8], MethodString, (wcslen(MethodString) + 1) * sizeof(WCHAR)); EventDataDescCreate(&EventData[9], username_str.c_str(), (wcslen(username_str.c_str()) + 1) * sizeof(WCHAR)); EventDataDescCreate(&EventData[10], ImagePath_str.c_str(), (wcslen(ImagePath_str.c_str()) + 1) * sizeof(WCHAR)); EventDataDescCreate(&EventData[11], CallStack, (wcslen(CallStack) + 1) * sizeof(WCHAR)); NTSTATUS status = WriteETWEvents(EventData, RPCEvent, 12); return TRUE; } BOOL RpcEvent( _In_ PEVENT_RECORD EventRecord, _In_ PEVENT_HEADER EventHeader, _In_ EVENT_DESCRIPTOR RPCEvent ) { PEVENT_HEADER_EXTENDED_DATA_ITEM extendedData = EventRecord->ExtendedData; HANDLE hProcess = GetCurrentProcess(); auto data{ reinterpret_cast(EventRecord->UserData) }; auto interfaceUUID{ GetData(data) }; auto procNum{ GetData(data) }; wchar_t szInterfaceUUID[64] = { 0 }; StringFromGUID2(*interfaceUUID, szInterfaceUUID, 64); //MS-SCMR {367ABB81-9844-35F1-AD32-98F038001003} if (wcscmp(szInterfaceUUID, L"{367ABB81-9844-35F1-AD32-98F038001003}") == 0) { const wchar_t* InterfaceString = L"MS-SCMR"; switch (*procNum) { case 12: { const wchar_t* MethodString = L"RCreateServiceW"; wchar_t* CallStack = GetCallStack(EventRecord, extendedData, hProcess); BOOL WriteEvent = WriteRPCEvent(EventRecord, EventHeader, RPCEvent, (wchar_t*)InterfaceString, (wchar_t*)MethodString, szInterfaceUUID, CallStack); delete[] CallStack; break; } default: { break; } } return TRUE; } //MS-DRSR {E3514235-4B06-11D1-AB04-00C04FC2DCD2} if (wcscmp(szInterfaceUUID, L"{E3514235-4B06-11D1-AB04-00C04FC2DCD2}") == 0) { const wchar_t* InterfaceString = L"MS-DRSR"; switch (*procNum) { case 3: { const wchar_t* MethodString = L"GetNCChanges"; wchar_t* CallStack = GetCallStack(EventRecord, extendedData, hProcess); BOOL WriteEvent = WriteRPCEvent(EventRecord, EventHeader, RPCEvent, (wchar_t*)InterfaceString, (wchar_t*)MethodString, szInterfaceUUID, CallStack); delete[] CallStack; break; } default: { break; } } return TRUE; } //MS-RRP {338CD001-2244-31F1-AAAA-900038001003} if (wcscmp(szInterfaceUUID, L"{338CD001-2244-31F1-AAAA-900038001003}") == 0) { const wchar_t* InterfaceString = L"MS-RRP"; switch (*procNum) { case 6: { const wchar_t* MethodString = L"BaseRegCreateKey"; wchar_t* CallStack = GetCallStack(EventRecord, extendedData, hProcess); BOOL WriteEvent = WriteRPCEvent(EventRecord, EventHeader, RPCEvent, (wchar_t*)InterfaceString, (wchar_t*)MethodString, szInterfaceUUID, CallStack); delete[] CallStack; break; } case 22: { const wchar_t* MethodString = L"BaseRegSetValue"; wchar_t* CallStack = GetCallStack(EventRecord, extendedData, hProcess); BOOL WriteEvent = WriteRPCEvent(EventRecord, EventHeader, RPCEvent, (wchar_t*)InterfaceString, (wchar_t*)MethodString, szInterfaceUUID, CallStack); delete[] CallStack; break; } default: { break; } } return TRUE; } //MS-SRVS {4B324FC8-1670-01D3-1278-5A47BF6EE188} if (wcscmp(szInterfaceUUID, L"{4B324FC8-1670-01D3-1278-5A47BF6EE188}") == 0) { const wchar_t* InterfaceString = L"MS-SRVS"; switch (*procNum) { case 12: { const wchar_t* MethodString = L"NetrSessionEnum"; wchar_t* CallStack = GetCallStack(EventRecord, extendedData, hProcess); BOOL WriteEvent = WriteRPCEvent(EventRecord, EventHeader, RPCEvent, (wchar_t*)InterfaceString, (wchar_t*)MethodString, szInterfaceUUID, CallStack); delete[] CallStack; break; } default: { break; } } return TRUE; } //MS-RPRN {12345678-1234-ABCD-EF00-0123456789AB} if (wcscmp(szInterfaceUUID, L"{12345678-1234-ABCD-EF00-0123456789AB}") == 0) { const wchar_t* InterfaceString = L"MS-RPRN"; switch (*procNum) { case 89: { const wchar_t* MethodString = L"RpcAddPrinterDriverEx"; wchar_t* CallStack = GetCallStack(EventRecord, extendedData, hProcess); BOOL WriteEvent = WriteRPCEvent(EventRecord, EventHeader, RPCEvent, (wchar_t*)InterfaceString, (wchar_t*)MethodString, szInterfaceUUID, CallStack); delete[] CallStack; break; } default: { break; } } return TRUE; } //MS-PAR 76F03F96-CDFD-44FC-A22C-64950A001209 if (wcscmp(szInterfaceUUID, L"{76F03F96-CDFD-44FC-A22C-64950A001209}") == 0) { const wchar_t* InterfaceString = L"MS-PAR"; switch (*procNum) { case 39: { const wchar_t* MethodString = L"RpcAsyncAddPrinterDriver"; wchar_t* CallStack = GetCallStack(EventRecord, extendedData, hProcess); BOOL WriteEvent = WriteRPCEvent(EventRecord, EventHeader, RPCEvent, (wchar_t*)InterfaceString, (wchar_t*)MethodString, szInterfaceUUID, CallStack); delete[] CallStack; break; } default: { break; } } return TRUE; } // MS-EFSR {D9A0A0C0-150F-11D1-8C7A-00C04FC297EB} || {C681D488-D850-11D0-8C52-00C04FD90F7E}" if ((wcscmp(szInterfaceUUID, L"{C681D488-D850-11D0-8C52-00C04FD90F7E}") == 0) || (wcscmp(szInterfaceUUID, L"{DF1941C5-FE89-4E79-BF10-463657ACF44D}") == 0)) { const wchar_t* InterfaceString = L"MS-EFSR"; switch (*procNum) { case 0: { const wchar_t* MethodString = L"EfsRpcOpenFileRaw"; wchar_t* CallStack = GetCallStack(EventRecord, extendedData, hProcess); BOOL WriteEvent = WriteRPCEvent(EventRecord, EventHeader, RPCEvent, (wchar_t*)InterfaceString, (wchar_t*)MethodString, szInterfaceUUID, CallStack); delete[] CallStack; break; } case 4: { const wchar_t* MethodString = L"EfsRpcEncryptFileSrv"; wchar_t* CallStack = GetCallStack(EventRecord, extendedData, hProcess); BOOL WriteEvent = WriteRPCEvent(EventRecord, EventHeader, RPCEvent, (wchar_t*)InterfaceString, (wchar_t*)MethodString, szInterfaceUUID, CallStack); delete[] CallStack; break; } case 5: { const wchar_t* MethodString = L"EfsRpcDecryptFileSrv"; wchar_t* CallStack = GetCallStack(EventRecord, extendedData, hProcess); BOOL WriteEvent = WriteRPCEvent(EventRecord, EventHeader, RPCEvent, (wchar_t*)InterfaceString, (wchar_t*)MethodString, szInterfaceUUID, CallStack); delete[] CallStack; break; } default: { break; } } return TRUE; } } BOOL DPAPIEvents( _In_ PEVENT_RECORD EventRecord, _In_ PEVENT_HEADER EventHeader ) { switch (EventHeader->EventDescriptor.Id) { case 16385: { auto data{ reinterpret_cast(EventRecord->UserData) }; auto OperationType{ GetWideString(data) }; auto DataDescription{ GetWideString(data) }; auto MasterKeyGUID = GetData(data); auto Flags = GetData(data); auto ProtectionFlags = GetData(data); auto ReturnValue = GetData(data); auto CallerProcessStartKey = GetData(data); auto CallerProcessID = GetData(data); auto CallerProcessCreationTime = GetData(data); auto PlainTextDataSize = GetData(data); FILETIME st; GetSystemTimeAsFileTime(&st); // //Seeing if OperationType == SPCryptUnprotect // if (wcscmp(OperationType, L"SPCryptUnprotect") == 0) { EVENT_DATA_DESCRIPTOR EventData[6]; EventDataDescCreate(&EventData[0], &st, sizeof(st)); EventDataDescCreate(&EventData[1], OperationType, (wcslen(OperationType) + 1) * sizeof(WCHAR)); EventDataDescCreate(&EventData[2], DataDescription, (wcslen(DataDescription) + 1) * sizeof(WCHAR)); EventDataDescCreate(&EventData[3], CallerProcessID, 4); EventDataDescCreate(&EventData[4], Flags, 4); EventDataDescCreate(&EventData[5], ProtectionFlags, 4); NTSTATUS status = WriteETWEvents(EventData, DPAPIEvent, 6); break; } break; } default: { break; } } Exit: return TRUE; }