diff --git a/CMakeLists.txt b/CMakeLists.txt index 065b404..ec16c00 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -69,11 +69,13 @@ if(USE_ETW) set (srcs ${srcs} etw_listener.cpp + etw_settings.cpp ) set (hdrs ${hdrs} etw_listener.h + etw_settings.h krabsetw/krabs/krabs.hpp ) endif() diff --git a/etw_listener.cpp b/etw_listener.cpp index 2b78e7c..687463f 100644 --- a/etw_listener.cpp +++ b/etw_listener.cpp @@ -13,6 +13,7 @@ #define EXECUTABLE_FLAGS (PAGE_EXECUTE | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY) #define MAX_PROCESSES 65536 + // Global var for ETW thread struct ProceesStat diff --git a/etw_listener.h b/etw_listener.h index acbea65..e2a7b53 100644 --- a/etw_listener.h +++ b/etw_listener.h @@ -19,28 +19,8 @@ // ETW includes #include "krabsetw/krabs/krabs.hpp" +#include "etw_settings.h" -struct ETWProfile { - bool process_start; - bool img_load; - bool allocation; - bool tcpip; - bool obj_mgr; - - ETWProfile(bool _process_start = false, bool _img_load = false, bool _allocation = false, bool _tcpip = false, bool _obj_mgr = false) - : process_start(_process_start), img_load(_img_load), allocation(_allocation), tcpip(_tcpip), obj_mgr(_obj_mgr) - { - } - - void setAll() - { - this->process_start = true; - this->img_load = true; - this->allocation = true; - this->tcpip = true; - this->obj_mgr = true; - } -}; bool ETWstart(ETWProfile &settings); diff --git a/etw_settings.cpp b/etw_settings.cpp new file mode 100644 index 0000000..8c626e3 --- /dev/null +++ b/etw_settings.cpp @@ -0,0 +1,177 @@ +#include "etw_settings.h" + +#include +#include +#include +#include + +#define WATCH_PROCESS_START "WATCH_PROCESS_START" +#define WATCH_IMG_LOAD "WATCH_IMG_LOAD" +#define WATCH_ALLOCATION "WATCH_ALLOCATION" +#define WATCH_TCP_IP "WATCH_TCP_IP" +#define WATCH_OBJ_MGR "WATCH_OBJ_MGR" + +namespace util { + + static inline void ltrim(std::string& s) + { + s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](unsigned char ch) { + return !std::isspace(ch); + })); + } + + static inline void rtrim(std::string& s) + { + s.erase(std::find_if(s.rbegin(), s.rend(), [](unsigned char ch) { + return !std::isspace(ch); + }).base(), s.end()); + } + + void trim(std::string& s) + { + ltrim(s); + rtrim(s); + } + + bool iequals(const std::string& a, const std::string& b) + { + size_t aLen = a.size(); + if (b.size() != aLen) return false; + + for (size_t i = 0; i < aLen; ++i) { + if (tolower(a[i]) != tolower(b[i])) return false; + } + return true; + } + + size_t splitList(const std::string& sline, const char delimiter, std::vector& args) + { + std::istringstream f(sline); + std::string s; + while (getline(f, s, delimiter)) { + args.push_back(s); + } + return args.size(); + } + + + int loadInt(const std::string& str, bool as_hex=false) + { + int intVal = 0; + + std::stringstream ss; + ss << (as_hex ? std::hex : std::dec) << str; + ss >> intVal; + + return intVal; + } + + bool loadBoolean(const std::string& str, bool defaultVal) + { + if (util::iequals(str, "True") || util::iequals(str, "on") || util::iequals(str, "yes")) { + return true; + } + if (util::iequals(str, "False") || util::iequals(str, "off") || util::iequals(str, "no")) { + return false; + } + const int val = loadInt(str); + if (val == 0) return false; + return true; + } + + std::string booleanToStr(bool val) + { + return (val) ? "True": "False"; + } + + +}; // util + +//--- +const char ETWProfile::DELIM = '='; + +void ETWProfile::stripComments(std::string& str) +{ + size_t found = str.find_first_of(";#"); + if (found != std::string::npos) { + str.resize(found); + } +} + +bool ETWProfile::fillSettings(std::string line) +{ + using namespace util; + + std::vector args; + util::splitList(line, DELIM, args); + + if (args.size() < 2) { + return false; + } + bool isFilled = false; + std::string valName = args[0]; + std::string valStr = args[1]; + util::trim(valName); + util::trim(valStr); + + if (util::iequals(valName, WATCH_PROCESS_START)) { + this->process_start = loadBoolean(valStr, this->process_start); + isFilled = true; + } + if (util::iequals(valName, WATCH_IMG_LOAD)) { + this->img_load = loadBoolean(valStr, this->img_load); + isFilled = true; + } + if (util::iequals(valName, WATCH_ALLOCATION)) { + this->allocation = loadBoolean(valStr, this->allocation); + isFilled = true; + } + if (util::iequals(valName, WATCH_TCP_IP)) { + this->tcpip = loadBoolean(valStr, this->tcpip); + isFilled = true; + } + if (util::iequals(valName, WATCH_OBJ_MGR)) { + this->obj_mgr = loadBoolean(valStr, this->obj_mgr); + isFilled = true; + } + return isFilled; +} + +bool ETWProfile::loadIni(const std::string& filename) +{ + std::ifstream myfile(filename.c_str()); + if (!myfile.is_open()) { + return false; + } + const size_t MAX_LINE = 300; + char line[MAX_LINE] = { 0 }; + bool filledAny = false; + + while (!myfile.eof()) { + myfile.getline(line, MAX_LINE); + std::string lineStr = line; + stripComments(lineStr); + + if (fillSettings(lineStr)) { + filledAny = true; + } + } + myfile.close(); + return filledAny; +} + +bool ETWProfile::saveIni(const std::string& filename) +{ + using namespace util; + std::ofstream myfile(filename.c_str()); + if (!myfile.is_open()) { + return false; + } + myfile << WATCH_PROCESS_START << DELIM << booleanToStr(this->process_start) << "\n"; + myfile << WATCH_IMG_LOAD << DELIM << booleanToStr(this->img_load) << "\n"; + myfile << WATCH_ALLOCATION << DELIM << booleanToStr(this->allocation) << "\n"; + myfile << WATCH_TCP_IP << DELIM << booleanToStr(this->tcpip) << "\n"; + myfile << WATCH_OBJ_MGR << DELIM << booleanToStr(this->obj_mgr) << "\n"; + myfile.close(); + return true; +} diff --git a/etw_settings.h b/etw_settings.h new file mode 100644 index 0000000..fc280cc --- /dev/null +++ b/etw_settings.h @@ -0,0 +1,59 @@ +#pragma once + +#include + +struct ETWProfile { +public: + bool process_start; + bool img_load; + bool allocation; + bool tcpip; + bool obj_mgr; + + ETWProfile(bool _process_start = false, bool _img_load = false, bool _allocation = false, bool _tcpip = false, bool _obj_mgr = false) + : process_start(_process_start), img_load(_img_load), allocation(_allocation), tcpip(_tcpip), obj_mgr(_obj_mgr) + { + } + + bool initProfile(const std::string& fileName) + { + bool isOk = loadIni(fileName); + if (!isOk) { + setAll(); + isOk = saveIni(fileName); + } + return isOk; + } + + bool loadIni(const std::string& fileName); + bool saveIni(const std::string& fileName); + + void setAll() + { + this->process_start = true; + this->img_load = true; + this->allocation = true; + this->tcpip = true; + this->obj_mgr = true; + } + + bool isEnabled() + { + if (this->process_start + || this->img_load + || this->allocation + || this->tcpip + || this->obj_mgr + ) + { + return true; + } + return false; + } + +protected: + static const char DELIM; + + bool fillSettings(std::string line); + void stripComments(std::string& str); +}; diff --git a/main.cpp b/main.cpp index b6bcf62..2bd33cc 100644 --- a/main.cpp +++ b/main.cpp @@ -47,8 +47,13 @@ t_pesieve_res deploy_scan() if (g_hh_args.etw_scan) { #ifdef USE_ETW + const char profileIni[] = "ETWProfile.ini"; ETWProfile profile; - profile.setAll(); + profile.initProfile(profileIni); + if (!profile.isEnabled()) { + std::cerr << "Cannot start ETW: the profile (\"" << profileIni << "\") is empty\n"; + return PESIEVE_ERROR; + } if (!ETWstart(profile)) { return PESIEVE_ERROR; }