mirror of
https://github.com/dobin/RedEdr
synced 2026-08-09 12:30:51 +00:00
136 lines
4.5 KiB
C++
136 lines
4.5 KiB
C++
#include <Windows.h>
|
|
#include <iostream>
|
|
#include <string>
|
|
#include <sstream>
|
|
#include <krabs.hpp>
|
|
#include "json.hpp"
|
|
|
|
#include "etw_krabs.h"
|
|
#include "utils.h"
|
|
|
|
|
|
nlohmann::json KrabsEtwEventToJsonStr(const EVENT_RECORD& record, krabs::schema schema) {
|
|
krabs::parser parser(schema);
|
|
|
|
// To construct a JSON, we use nlohmann::json, which works in std::string
|
|
// (utf-8). We need to convert all data several times.
|
|
|
|
nlohmann::json j;
|
|
|
|
j["type"] = "etw";
|
|
j["event_time"] = static_cast<__int64>(record.EventHeader.TimeStamp.QuadPart);
|
|
j["etw_pid"] = record.EventHeader.ProcessId;
|
|
j["etw_tid"] = record.EventHeader.ThreadId;
|
|
|
|
// Construct the event string, like "ImageLoad"
|
|
std::wstring a = std::wstring(schema.task_name());
|
|
std::wstring b = std::wstring(schema.opcode_name());
|
|
std::wstring c = a + b;
|
|
std::string d = wstring2string(c);
|
|
j["event"] = d;
|
|
|
|
//j["opcode_id"] = schema.event_opcode();
|
|
j["etw_event_id"] = schema.event_id();
|
|
|
|
// The ProviderId is just the UID of the provider, which is not very useful
|
|
// This is a workaround. Alternative would be to use TdhGetEventInformation()?
|
|
//j["provider_name"] = std::to_string(record.EventHeader.ProviderId);
|
|
j["etw_provider_name"] = wchar2string(schema.provider_name());
|
|
|
|
// Iterate over all properties defined in the schema
|
|
for (const auto& property : parser.properties()) {
|
|
try {
|
|
// Get the name and type of the property
|
|
const std::wstring& propertyName = property.name();
|
|
const auto propertyType = property.type();
|
|
|
|
/*
|
|
* Reserved1":"0","Reserved2":"0","Reserved3":"0","Reserved4":"0",
|
|
* "SignatureLevel":"(Unsupported type)\n","SignatureType":"(Unsupported type)\n
|
|
*/
|
|
if (wstring_starts_with(propertyName, L"Reserved") || wstring_starts_with(propertyName, L"Signature")) {
|
|
continue;
|
|
}
|
|
std::string jsonKey = wstring2string((std::wstring&)propertyName);
|
|
std::transform(jsonKey.begin(), jsonKey.end(), jsonKey.begin(), ::tolower); // lowercase
|
|
|
|
// Special cases
|
|
if (propertyName == L"ProtectionMask" || propertyName == L"LastProtectionMask") {
|
|
uint32_t protection_mask = parser.parse<uint32_t>(propertyName);
|
|
j[jsonKey] = getMemoryRegionProtect(protection_mask);
|
|
continue;
|
|
}
|
|
|
|
switch (propertyType) {
|
|
case TDH_INTYPE_UINT32:
|
|
j[jsonKey] = (uint32_t) parser.parse<uint32_t>(propertyName);
|
|
//j[jsonKey + "_vartype"] = "TDH_INTYPE_UINT32";
|
|
break;
|
|
|
|
case TDH_INTYPE_UINT64:
|
|
j[jsonKey] = (uint64_t) parser.parse<uint64_t>(propertyName);
|
|
//j[jsonKey + "_vartype"] = "TDH_INTYPE_UINT64";
|
|
break;
|
|
|
|
case TDH_INTYPE_UNICODESTRING:
|
|
{
|
|
std::wstringstream ss;
|
|
ss << parser.parse<std::wstring>(propertyName);
|
|
std::string s = wstring2string((std::wstring&)ss.str());
|
|
j[jsonKey] = s;
|
|
}
|
|
break;
|
|
|
|
case TDH_INTYPE_ANSISTRING:
|
|
j[jsonKey] = parser.parse<std::string>(propertyName);
|
|
break;
|
|
|
|
case TDH_INTYPE_POINTER:
|
|
j[jsonKey] = (uint64_t) parser.parse<PVOID>(propertyName);
|
|
//j[jsonKey + "_vartype"] = "TDH_INTYPE_POINTER";
|
|
break;
|
|
|
|
case TDH_INTYPE_FILETIME:
|
|
{
|
|
// Not a PFILETIME!
|
|
FILETIME fileTime = parser.parse<FILETIME>(propertyName);
|
|
|
|
// As int
|
|
ULARGE_INTEGER uli;
|
|
uli.LowPart = fileTime.dwLowDateTime;
|
|
uli.HighPart = fileTime.dwHighDateTime;
|
|
|
|
j[jsonKey] = uli.QuadPart;
|
|
break;
|
|
}
|
|
|
|
default:
|
|
j[jsonKey] = "unsupported";
|
|
break;
|
|
}
|
|
|
|
}
|
|
catch (const std::exception& ex) {
|
|
std::wcout << L"Failed to parse property: " << ex.what() << L"\n";
|
|
}
|
|
}
|
|
|
|
// Callstack
|
|
j["stack_trace"] = nlohmann::json::array();
|
|
auto stack_trace = schema.stack_trace();
|
|
int idx = 0;
|
|
for (auto& return_address : stack_trace)
|
|
{
|
|
// Only add non-kernelspace addresses
|
|
if (return_address < 0xFFFF080000000000) {
|
|
j["stack_trace"].push_back({
|
|
{ "addr", return_address},
|
|
{ "idx", idx }
|
|
});
|
|
idx++;
|
|
}
|
|
}
|
|
|
|
return j;
|
|
}
|