diff --git a/.gitmodules b/.gitmodules index 65ee92521..1f7402658 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,3 +4,6 @@ [submodule "paramkit"] path = paramkit url = https://github.com/hasherezade/paramkit +[submodule "sig_finder"] + path = sig_finder + url = https://github.com/hasherezade/sig_finder diff --git a/CMakeLists.txt b/CMakeLists.txt index ea24a80bb..ce88706de 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -34,15 +34,21 @@ set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT") # modules: set ( M_PARSER "libpeconv/libpeconv" ) +set ( M_SIGFIND "sig_finder/sig_finder" ) # modules paths: -set (PECONV_DIR "${PROJECT_SOURCE_DIR}/${M_PARSER}" CACHE PATH "PEConv main path") +set ( PECONV_DIR "${PROJECT_SOURCE_DIR}/${M_PARSER}" CACHE PATH "PEConv main path") +set ( SIGFIND_DIR "${PROJECT_SOURCE_DIR}/${M_SIGFIND}" CACHE PATH "SigFinder main path") # modules headers: include_directories ( ${PECONV_DIR}/include ) +include_directories ( ${SIGFIND_DIR}/include ) + # libs -add_subdirectory (libpeconv/libpeconv) +add_subdirectory (${M_PARSER}) set ( PECONV_LIB $ CACHE PATH "PEConvLib library path" ) +add_subdirectory(${M_SIGFIND}) +set ( SIGFIND_LIB $ CACHE PATH "SigFinder library path" ) if( NOT PESIEVE_AS_STATIC_LIB AND NOT PESIEVE_AS_DLL) set ( M_PARAMKIT_LIB "paramkit" ) @@ -168,7 +174,6 @@ set (utils_hdrs utils/workingset_enum.h utils/modules_enum.h utils/artefacts_util.h - utils/pattern_tree.h utils/process_reflection.h utils/console_color.h utils/strings_util.h @@ -275,11 +280,12 @@ if(PESIEVE_AS_STATIC_LIB OR PESIEVE_AS_DLL) ) set_source_files_properties(main.def PROPERTIES HEADER_FILE_ONLY TRUE) else() - add_executable ( ${PROJECT_NAME} ${hdrs} ${srcs} ${rsrc} pe_sieve_res_icon.rc main.cpp params.h ) + add_executable ( ${PROJECT_NAME} ${hdrs} ${srcs} ${rsrc} pe_sieve_res_icon.rc main.cpp params.h ) endif() set (used_libs ${PECONV_LIB} + ${SIGFIND_LIB} psapi.lib ntdll.lib shlwapi @@ -287,7 +293,7 @@ set (used_libs ) # dependencies -add_dependencies(${PROJECT_NAME} libpeconv ) +add_dependencies( ${PROJECT_NAME} libpeconv sig_finder ) if(PESIEVE_AS_STATIC_LIB OR PESIEVE_AS_DLL) include(GNUInstallDirs) diff --git a/pe_sieve_ver_short.h b/pe_sieve_ver_short.h index 3769feee4..1e729760f 100644 --- a/pe_sieve_ver_short.h +++ b/pe_sieve_ver_short.h @@ -3,6 +3,6 @@ #define PESIEVE_MAJOR_VERSION 0 #define PESIEVE_MINOR_VERSION 3 #define PESIEVE_MICRO_VERSION 8 -#define PESIEVE_PATCH_VERSION 3 +#define PESIEVE_PATCH_VERSION 5 -#define PESIEVE_VERSION_STR "0.3.8.3" +#define PESIEVE_VERSION_STR "0.3.8.6" diff --git a/sig_finder b/sig_finder new file mode 160000 index 000000000..9f88b8baf --- /dev/null +++ b/sig_finder @@ -0,0 +1 @@ +Subproject commit 9f88b8bafe99c117577b4eb5dedabe9df2452795 diff --git a/utils/artefacts_util.cpp b/utils/artefacts_util.cpp index a1876027d..ee308b1ba 100644 --- a/utils/artefacts_util.cpp +++ b/utils/artefacts_util.cpp @@ -1,13 +1,12 @@ #include "artefacts_util.h" #include -#include "pattern_tree.h" +#include +using namespace sig_finder; #ifdef _DEBUG #include #endif -using namespace pattern_tree; - BYTE* pesieve::util::find_pattern(BYTE* buffer, size_t buf_size, BYTE* pattern_buf, size_t pattern_size, size_t max_iter) { for (size_t i = 0; (i + pattern_size) < buf_size; i++) { @@ -38,9 +37,9 @@ bool init_32_patterns(Node* rootN) 0x89, 0xE5 // MOV EBP, ESP }; - Node::addPattern(rootN, "prolog32_1", prolog32_pattern, sizeof(prolog32_pattern)); - Node::addPattern(rootN, "prolog32_2", prolog32_2_pattern, sizeof(prolog32_2_pattern)); - Node::addPattern(rootN, "prolog32_3", prolog32_3_pattern, sizeof(prolog32_3_pattern)); + rootN->addPattern("prolog32_1", prolog32_pattern, sizeof(prolog32_pattern)); + rootN->addPattern("prolog32_2", prolog32_2_pattern, sizeof(prolog32_2_pattern)); + rootN->addPattern("prolog32_3", prolog32_3_pattern, sizeof(prolog32_3_pattern)); return true; } @@ -86,19 +85,19 @@ bool init_64_patterns(Node* rootN64) 0x41, 0x57 // PUSH R15 }; - Node::addPattern(rootN64, "prolog64_1", prolog64_pattern, sizeof(prolog64_pattern)); - Node::addPattern(rootN64, "prolog64_2", prolog64_2_pattern, sizeof(prolog64_2_pattern)); - Node::addPattern(rootN64, "prolog64_3", prolog64_3_pattern, sizeof(prolog64_3_pattern)); - Node::addPattern(rootN64, "prolog64_4", prolog64_4_pattern, sizeof(prolog64_4_pattern)); - Node::addPattern(rootN64, "prolog64_5", prolog64_5_pattern, sizeof(prolog64_5_pattern)); - Node::addPattern(rootN64, "prolog64_6", prolog64_6_pattern, sizeof(prolog64_6_pattern)); - Node::addPattern(rootN64, "prolog64_7", prolog64_7_pattern, sizeof(prolog64_7_pattern)); + rootN64->addPattern("prolog64_1", prolog64_pattern, sizeof(prolog64_pattern)); + rootN64->addPattern("prolog64_2", prolog64_2_pattern, sizeof(prolog64_2_pattern)); + rootN64->addPattern("prolog64_3", prolog64_3_pattern, sizeof(prolog64_3_pattern)); + rootN64->addPattern("prolog64_4", prolog64_4_pattern, sizeof(prolog64_4_pattern)); + rootN64->addPattern("prolog64_5", prolog64_5_pattern, sizeof(prolog64_5_pattern)); + rootN64->addPattern("prolog64_6", prolog64_6_pattern, sizeof(prolog64_6_pattern)); + rootN64->addPattern("prolog64_7", prolog64_7_pattern, sizeof(prolog64_7_pattern)); return true; } -size_t search_till_pattern(Node& rootN, const BYTE* loadedData, size_t loadedSize) +size_t search_till_pattern(sig_finder::Node& rootN, const BYTE* loadedData, size_t loadedSize) { - Match m = pattern_tree::find_first_match(rootN, loadedData, loadedSize); + Match m = sig_finder::find_first_match(rootN, loadedData, loadedSize); if (!m.sign) { return CODE_PATTERN_NOT_FOUND; } @@ -107,7 +106,7 @@ size_t search_till_pattern(Node& rootN, const BYTE* loadedData, size_t loadedSiz size_t pesieve::util::is_32bit_code(BYTE *loadedData, size_t loadedSize) { - static Node rootN; + static sig_finder::Node rootN; if(rootN.isEnd()) { init_32_patterns(&rootN); } @@ -116,7 +115,7 @@ size_t pesieve::util::is_32bit_code(BYTE *loadedData, size_t loadedSize) size_t pesieve::util::is_64bit_code(BYTE* loadedData, size_t loadedSize) { - static Node rootN; + static sig_finder::Node rootN; if (rootN.isEnd()) { init_64_patterns(&rootN); } diff --git a/utils/pattern_tree.h b/utils/pattern_tree.h deleted file mode 100644 index b8d5e396d..000000000 --- a/utils/pattern_tree.h +++ /dev/null @@ -1,296 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include - -namespace pattern_tree { - - class Signature - { - public: - Signature(std::string _name, const BYTE* _pattern, size_t _pattern_size) - : name(_name), pattern(nullptr), pattern_size(0) - { - this->pattern = (BYTE*)::calloc(_pattern_size, 1); - if (!this->pattern) return; - - ::memcpy(this->pattern, _pattern, _pattern_size); - this->pattern_size = _pattern_size; - } - - size_t size() - { - return pattern_size; - } - - std::string name; - - protected: - size_t pattern_size; - BYTE* pattern; - }; - - class Match - { - public: - Match() - : offset(0), sign(nullptr) - { - } - - Match(size_t _offset, Signature* _sign) - : offset(_offset), sign(_sign) - { - } - - Match(const Match& _match) // copy constructor - { - offset = _match.offset; - sign = _match.sign; - } - - size_t offset; - Signature* sign; - }; - - template class ShortList - { - public: - ShortList() - : elCount(0) - { - } - - bool push_back(Element n) - { - if (elCount >= _countof(list)) { - return false; - } - if (find(n)) { - return true; - } - list[elCount] = n; - elCount++; - return true; - } - - Element at(size_t i) - { - if (i < _countof(list)) { - return list[i]; - } - return nullptr; - } - - Element find(Element& searched) - { - for (size_t i = 0; i < elCount; i++) { - if (list[i] == searched) { - return list[i]; - } - } - return nullptr; - } - - void clear() - { - elCount = 0; - } - - size_t size() - { - return elCount; - } - - protected: - size_t elCount; - Element list[100]; - }; - - class Node - { - public: - - static bool addPattern(Node* rootN, const char* _name, const BYTE* pattern, size_t pattern_size) - { - if (!rootN || !pattern || !pattern_size) { - return false; - } - Node* next = rootN; - for (size_t i = 0; i < pattern_size; i++) { - next = next->addNext(pattern[i]); - if (!next) return false; - } - next->sign = new Signature(_name, pattern, pattern_size); - return true; - } - - static bool addTextPattern(Node* rootN, const char* pattern1) - { - return Node::addPattern(rootN, pattern1, (const BYTE*)pattern1, strlen(pattern1)); - } - - //--- - - Node() - : level(0), val(0), - sign(nullptr) - { - } - - Node(BYTE _val, size_t _level) - : val(_val), level(_level), - sign(nullptr) - { - } - - ~Node() - { - for (auto itr = immediates.begin(); itr != immediates.end(); ++itr) { - Node* next = itr->second; - delete next; - } - immediates.clear(); - if (sign) { - delete sign; - } - } - - Node* getNode(BYTE _val) - { - auto found = immediates.find(_val); - if (found != immediates.end()) { - return found->second; - } - return nullptr; - } - - Node* addNext(BYTE _val) - { - Node* nextN = getNode(_val); - if (!nextN) { - nextN = new Node(_val, this->level + 1); - immediates[_val] = nextN; - } - return nextN; - } - - void print() - { - std::cout << std::hex << (unsigned int)val << " [" << level << "]" << " [" << immediates.size() << "]"; - if (!immediates.size()) { - printf("\n"); - return; - } - for (auto itr = immediates.begin(); itr != immediates.end(); ++itr) { - itr->second->print(); - } - } - -#define SEARCH_BACK - size_t getMatching(const BYTE* data, size_t data_size, std::vector &matches, bool stopOnFirst) - { - size_t processed = 0; - // - ShortList level; - level.push_back(this); - ShortList level2; - - auto level1_ptr = &level; - auto level2_ptr = &level2; - - for (size_t i = 0; i < data_size; i++) - { - processed = i; // processed bytes - level2_ptr->clear(); - for (size_t k = 0; k < level1_ptr->size(); k++) { - Node * curr = level1_ptr->at(k); - if (curr->isSign()) { - size_t match_start = i - curr->sign->size(); - Match m(match_start, curr->sign); - matches.push_back(m); - if (stopOnFirst) { - return match_start; - } - } - Node* prev = curr; - curr = prev->getNode(data[i]); - if (curr) { - level2_ptr->push_back(curr); - } -#ifdef SEARCH_BACK - if (prev != this) { - // the current value may also be a beginning of a new pattern: - Node* start = this->getNode(data[i]); - if (start) { - level2_ptr->push_back(start); - } - } -#endif - } - if (!level2_ptr->size()) { -#ifdef SEARCH_BACK - // restart search from the beginning - level2_ptr->push_back(this); -#else - return results; -#endif //SEARCH_BACK - } - //swap: - auto tmp = level1_ptr; - level1_ptr = level2_ptr; - level2_ptr = tmp; - } - return processed; - } - - bool isEnd() - { - return this->immediates.size() ? false : true; - } - - bool isSign() - { - return sign ? true : false; - } - - protected: - Signature* sign; - BYTE val; - size_t level; - std::map immediates; - }; - - - inline size_t find_all_matches(Node& rootN, const BYTE* loadedData, size_t loadedSize, std::vector &allMatches) - { - if (!loadedData || !loadedSize) { - return 0; - } - size_t counter = 0; - rootN.getMatching(loadedData, loadedSize, allMatches, false); - if (allMatches.size()) { - counter += allMatches.size(); - } - return counter; - } - - inline Match find_first_match(Node& rootN, const BYTE* loadedData, size_t loadedSize) - { - Match empty; - if (!loadedData || !loadedSize) { - return empty; - } - std::vector allMatches; - rootN.getMatching(loadedData, loadedSize, allMatches, true); - if (allMatches.size()) { - auto itr = allMatches.begin(); - return *itr; - } - return empty; - } - -}; //namespace pattern_tree