From 93d1fc6c5447c60d6c0e691147b57933eb122e41 Mon Sep 17 00:00:00 2001 From: JeffreyZhang512 Date: Sun, 7 May 2023 22:05:35 +0800 Subject: [PATCH] Change the class EvtxDecoder to fit for the revised evtx_dump tool --- README.md | 6 +- common/version.h | 2 +- .../src/DecoderCtrl/EvtxDecoder.cpp | 66 +++++-------------- .../src/DecoderCtrl/EvtxDecoder.h | 3 +- tools/winlogdecoder/winlogdecoder.rc | 8 +-- 5 files changed, 28 insertions(+), 57 deletions(-) diff --git a/README.md b/README.md index 0dce8a0..9492c23 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ This is a Qt based tool to decode Windows log files(.etl and .evtx) to txt files For the binary release, please goto: https://github.com/JeffreyZhang512/winlogdecoder/releases -The latest release version is v0.4.0.0. +The latest release version is v0.5.0.0 which also includes the revised evtx_dump tool. To run the binary, you need install the Microsoft Visual C++ Redistributable as well. You can download it from Microsoft website. ## etl files @@ -20,10 +20,10 @@ Notes: ## evtx files The purpose of decoding evtx files is to show the events recorded by Windows. The process is as following: - Call the evtx_dump tool (https://github.com/omerbenamram/evtx) to convert the evtx files to xml files. -- The xml files converted by the evtx_dump tool can't be completely parsed by the Qt class QXmlStreamReader, so I have to revise the format. - Then parse the revised xml files and extract the information to .txt files. +- The problem is that the output of the evtx_dump tool is in XML format but not a valid xml file which can't be completely parsed by the Qt class QXmlStreamReader, so I have to change the evtx_dump tool to make the output file as a valid xml file. Notes: - The format of the generated txt file is like this: [level] timestamp {guid of the provider}or[name of the provider][process id][thread id] eventID (Task Category) -- Currently, all events are printed to the txt file. You can modify the class EvtxDecoder to print the eventIDs you are interested only. +- Currently, all events are printed to the txt file. You can modify the class EvtxDecoder to print the eventIDs you are interested only. diff --git a/common/version.h b/common/version.h index 1f9589f..bcc9837 100644 --- a/common/version.h +++ b/common/version.h @@ -19,7 +19,7 @@ #define VERSION_H #ifndef APP_VERSION -#define APP_VERSION "0.4.0.0" +#define APP_VERSION "0.5.0.0" #endif #ifndef APP_ORGANIZATION_NAME diff --git a/tools/winlogdecoder/src/DecoderCtrl/EvtxDecoder.cpp b/tools/winlogdecoder/src/DecoderCtrl/EvtxDecoder.cpp index 0d96e85..23df943 100644 --- a/tools/winlogdecoder/src/DecoderCtrl/EvtxDecoder.cpp +++ b/tools/winlogdecoder/src/DecoderCtrl/EvtxDecoder.cpp @@ -13,59 +13,29 @@ EvtxDecoder::~EvtxDecoder() } -bool EvtxDecoder::ParseXml(QString xmlFileName) +void EvtxDecoder::ParseNoOfRecords() { - if (cancel) - return true; - - QFile xmlFile(xmlFileName); - if (!xmlFile.open(QIODevice::ReadOnly | QIODevice::Text)) + QRegularExpressionMatch match = reRecords.match(extProcessMessage); + if (match.hasMatch()) { - emit log(QString("Decoder: Open %1 failed").arg(xmlFileName).toStdString(), LOG_ERROR); - return false; + noOfEvents = match.captured(1).toULongLong(); } +} - QFile xmlFileRevised(xmlFileName + QString(".xml")); - if (!xmlFileRevised.open(QIODevice::WriteOnly | QIODevice::Text)) - return false; - QTextStream xmlRevisedOut(&xmlFileRevised); - xmlRevisedOut << QString("\n"); - QString recordString; - while (!cancel && !xmlFile.atEnd()) - { - QString line = xmlFile.readLine(); - if (line == QString("\n")) - continue; - else if (line.left(7) == QString("Record ")) - { - recordString = line; - continue; - } - xmlRevisedOut << line; - } +bool EvtxDecoder::ParseXml(QString xmlFileName) +{ if (cancel) return true; - xmlRevisedOut << QString("\n"); - - xmlFile.close(); - xmlFileRevised.close(); - - // Get noOfEvents - QRegularExpressionMatch matchRecord = reRecord.match(recordString); - if (matchRecord.hasMatch()) - { - noOfEvents = matchRecord.captured(1).toULongLong(); - } - - if (!xmlFileRevised.open(QIODevice::ReadOnly | QIODevice::Text)) + QFile xmlFile(xmlFileName); + if (!xmlFile.open(QIODevice::ReadOnly | QIODevice::Text)) { - emit log(QString("Decoder: Open %1 failed").arg(xmlFileName + QString(".xml")).toStdString(), LOG_ERROR); + emit log(QString("Decoder: Open %1 failed").arg(xmlFileName).toStdString(), LOG_ERROR); return false; } - reader.setDevice(&xmlFileRevised); + reader.setDevice(&xmlFile); QFile txtFile(xmlFileName + QString(".txt")); if (!txtFile.open(QIODevice::WriteOnly | QIODevice::Text)) @@ -111,9 +81,9 @@ bool EvtxDecoder::ParseXml(QString xmlFileName) emit log(QString("Decoder: failed to parse %1, error = %2 ").arg(xmlFileName, reader.errorString()).toStdString(), LOG_ERROR); return false; } - if (xmlFileRevised.error() != QFile::NoError) + if (xmlFile.error() != QFile::NoError) { - emit log(QString("Decoder: error happens in reading %1").arg(xmlFileName + QString(".xml")).toStdString(), LOG_ERROR); + emit log(QString("Decoder: error happens in reading %1").arg(xmlFileName).toStdString(), LOG_ERROR); return false; } if (txtFile.error() != QFile::NoError) @@ -160,7 +130,7 @@ void EvtxDecoder::doDecoding(QString evtxFileName, QString destFolder) { // long long threadId = reinterpret_cast(QThread::currentThreadId()); this->fileName = evtxFileName; - QString evtxdump = "evtx_dump-v0.8.1.exe"; + QString evtxdump = "evtx_dump-v0.8.1_revised.exe"; extProcess = new QProcess(this); // slotes for process @@ -174,9 +144,9 @@ void EvtxDecoder::doDecoding(QString evtxFileName, QString destFolder) QFileInfo fileInfo = QFileInfo(evtxFileName); QString xmlFileName = QString("%1/%2.xml").arg(destFolder, fileInfo.fileName()); - extProcessCommand = evtxdump + QString(" -f ") + xmlFileName.replace("/", "\\") + QString(" --no-confirm-overwrite -t 1 ") + evtxFileName.replace("/", "\\"); + extProcessCommand = evtxdump + QString(" -f ") + xmlFileName.replace("/", "\\") + QString(" --no-confirm-overwrite --dont-show-record-number ") + evtxFileName.replace("/", "\\"); QStringList arguments; - arguments << "-f" << xmlFileName << "--no-confirm-overwrite" << "-t" << "1" << evtxFileName; + arguments << "-f" << xmlFileName << "--no-confirm-overwrite" << "--dont-show-record-number" << evtxFileName; extProcess->start(evtxdump, arguments); extProcess->waitForFinished(-1); @@ -186,8 +156,8 @@ void EvtxDecoder::doDecoding(QString evtxFileName, QString destFolder) { // evtx_dump returns success emit log(QString("Decoder: converted to %1 successfully").arg(xmlFileName).toStdString(), LOG_OK); - // Parse the summary file to get the total number of events - // ParseSummary(summaryFileName); + // Get the total number of events + ParseNoOfRecords(); // Then parser the xml file and generate the txt file if (ParseXml(xmlFileName)) { diff --git a/tools/winlogdecoder/src/DecoderCtrl/EvtxDecoder.h b/tools/winlogdecoder/src/DecoderCtrl/EvtxDecoder.h index 041afba..ab8109d 100644 --- a/tools/winlogdecoder/src/DecoderCtrl/EvtxDecoder.h +++ b/tools/winlogdecoder/src/DecoderCtrl/EvtxDecoder.h @@ -17,8 +17,9 @@ class EvtxDecoder : public EtlDecoder ~EvtxDecoder(); private: - QRegularExpression reRecord = QRegularExpression("^Record\\s+(\\d+)\n"); + QRegularExpression reRecords = QRegularExpression("^Records:\\s+(\\d+)$", QRegularExpression::MultilineOption); + void ParseNoOfRecords(); bool ParseXml(QString xmlFileName); bool ParseEvent(QTextStream& txtOut); diff --git a/tools/winlogdecoder/winlogdecoder.rc b/tools/winlogdecoder/winlogdecoder.rc index a1e28db..5a65800 100644 --- a/tools/winlogdecoder/winlogdecoder.rc +++ b/tools/winlogdecoder/winlogdecoder.rc @@ -3,8 +3,8 @@ IDI_ICON1 ICON "resource/winlogdecoder.ico" VS_VERSION_INFO VERSIONINFO - FILEVERSION 0,4,0,0 - PRODUCTVERSION 0,4,0,0 + FILEVERSION 0,5,0,0 + PRODUCTVERSION 0,5,0,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -21,12 +21,12 @@ BEGIN BEGIN VALUE "CompanyName", "" VALUE "FileDescription", "Windows Log Decoder" - VALUE "FileVersion", "0.4.0.0" + VALUE "FileVersion", "0.5.0.0" VALUE "InternalName", "WinLogDecoder.exe" VALUE "LegalCopyright", "2023 Zhang, Jeffrey" VALUE "OriginalFilename", "WinLogDecoder.exe" VALUE "ProductName", "Windows Log Decoder" - VALUE "ProductVersion", "0.4.0.0" + VALUE "ProductVersion", "0.5.0.0" END END BLOCK "VarFileInfo"