From e6f3f9eefc675085122b8ad136f5384c97041325 Mon Sep 17 00:00:00 2001 From: mrexodia Date: Fri, 20 Nov 2015 21:52:13 +0100 Subject: [PATCH 1/3] added rich_version function (+ documentation) --- docs/modules/pe.rst | 10 ++++++++++ libyara/include/yara/pe.h | 9 +++++++++ libyara/modules/pe.c | 39 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 58 insertions(+) diff --git a/docs/modules/pe.rst b/docs/modules/pe.rst index b6e6f5f23d..a17bad8139 100644 --- a/docs/modules/pe.rst +++ b/docs/modules/pe.rst @@ -506,3 +506,13 @@ Reference *Example: pe.section_index(pe.entry_point)* +.. c:function:: rich_version(version) + + .. versionadded:: 3.5.0 + + Function returning true if the PE has the specified *version* in the PE's rich + signature. More information can be found here: + + http://www.ntcore.com/files/richsign.htm + + *Example: pe.rich_version(21005)* diff --git a/libyara/include/yara/pe.h b/libyara/include/yara/pe.h index 2316cc4c88..5b16eaecce 100644 --- a/libyara/include/yara/pe.h +++ b/libyara/include/yara/pe.h @@ -448,11 +448,20 @@ typedef struct _WIN_CERTIFICATE { // http://www.ntcore.com/files/richsign.htm // +#define RICH_VERSION_ID(id_version) (id_version >> 16) +#define RICH_VERSION_VERSION(id_version) (id_version & 0xFFFF) + +typedef struct _RICH_VERSION_INFO { + DWORD id_version; //tool id and version (use RICH_VERSION_ID and RICH_VERSION_VERSION macros) + DWORD times; //number of times this tool was used +} RICH_VERSION_INFO, *PRICH_VERSION_INFO; + typedef struct _RICH_SIGNATURE { DWORD dans; DWORD key1; DWORD key2; DWORD key3; + RICH_VERSION_INFO versions[0]; } RICH_SIGNATURE, *PRICH_SIGNATURE; #define RICH_DANS 0x536e6144 // "DanS" diff --git a/libyara/modules/pe.c b/libyara/modules/pe.c index 69b6684a2e..a40285b980 100644 --- a/libyara/modules/pe.c +++ b/libyara/modules/pe.c @@ -1814,6 +1814,44 @@ define_function(language) return_integer(0); } +define_function(rich_version) +{ + YR_OBJECT* module = module(); + PE* pe = (PE*)module->data; + uint64_t version = integer_argument(1); + size_t rich_len; + PRICH_SIGNATURE clear_rich_signature; + SIZED_STRING* rich_string; + int i; + + // Check if the required fields are set + if (is_undefined(module, "rich_signature.length")) + return_integer(UNDEFINED); + + // If not a PE file, return UNDEFINED + if (pe == NULL) + return_integer(UNDEFINED); + + rich_len = get_integer(module, "rich_signature.length"); + rich_string = get_string(module, "rich_signature.clear_data"); + + // If the clear_data was not set, return UNDEFINED + if (rich_string == NULL) + return_integer(UNDEFINED); + + clear_rich_signature = (PRICH_SIGNATURE)rich_string->c_string; + + // Loop over the versions in the rich signature + for (i = 0; + i < (rich_len - sizeof(RICH_SIGNATURE)) / sizeof(RICH_VERSION_INFO); + i++) + { + if(version == RICH_VERSION_VERSION(clear_rich_signature->versions[i].id_version)) + return_integer(1); + } + + return_integer(0); +} begin_declarations; @@ -1961,6 +1999,7 @@ begin_declarations; declare_function("imports", "s", "i", imports_dll); declare_function("locale", "i", "i", locale); declare_function("language", "i", "i", language); + declare_function("rich_version", "i", "i", rich_version); declare_integer("resource_timestamp") begin_struct("resource_version"); From 7d224dd37b5d474dc5ad4603704e5bc5d4769e29 Mon Sep 17 00:00:00 2001 From: mrexodia Date: Thu, 26 Nov 2015 16:50:41 +0100 Subject: [PATCH 2/3] moved rich_version to rich_signature.version and added a rich_signature.toolid version for checking toolid's --- docs/modules/pe.rst | 33 ++++++++++++++++++++++----------- libyara/modules/pe.c | 40 +++++++++++++++++++++++++++++++++++----- 2 files changed, 57 insertions(+), 16 deletions(-) diff --git a/docs/modules/pe.rst b/docs/modules/pe.rst index a17bad8139..292c6ddb87 100644 --- a/docs/modules/pe.rst +++ b/docs/modules/pe.rst @@ -425,6 +425,28 @@ Reference Data after being decrypted by XORing it with the key. + .. c:function:: version(version) + + .. versionadded:: 3.5.0 + + Function returning true if the PE has the specified *version* in the PE's rich + signature. More information can be found here: + + http://www.ntcore.com/files/richsign.htm + + *Example: pe.rich_signature.version(21005)* + + .. c:function:: toolid(id) + + .. versionadded:: 3.5.0 + + Function returning true if the PE has the specified *id* in the PE's rich + signature. More information can be found here: + + http://www.ntcore.com/files/richsign.htm + + *Example: pe.rich_signature.toolid(222)* + .. c:function:: exports(function_name) Function returning true if the PE exports *function_name* or @@ -505,14 +527,3 @@ Reference *addr*. *addr* can be an offset into the file or a memory address. *Example: pe.section_index(pe.entry_point)* - -.. c:function:: rich_version(version) - - .. versionadded:: 3.5.0 - - Function returning true if the PE has the specified *version* in the PE's rich - signature. More information can be found here: - - http://www.ntcore.com/files/richsign.htm - - *Example: pe.rich_version(21005)* diff --git a/libyara/modules/pe.c b/libyara/modules/pe.c index a40285b980..297db404f9 100644 --- a/libyara/modules/pe.c +++ b/libyara/modules/pe.c @@ -1817,7 +1817,6 @@ define_function(language) define_function(rich_version) { YR_OBJECT* module = module(); - PE* pe = (PE*)module->data; uint64_t version = integer_argument(1); size_t rich_len; PRICH_SIGNATURE clear_rich_signature; @@ -1828,8 +1827,38 @@ define_function(rich_version) if (is_undefined(module, "rich_signature.length")) return_integer(UNDEFINED); - // If not a PE file, return UNDEFINED - if (pe == NULL) + rich_len = get_integer(module, "rich_signature.length"); + rich_string = get_string(module, "rich_signature.clear_data"); + + // If the clear_data was not set, return UNDEFINED + if (rich_string == NULL) + return_integer(UNDEFINED); + + clear_rich_signature = (PRICH_SIGNATURE)rich_string->c_string; + + // Loop over the versions in the rich signature + for (i = 0; + i < (rich_len - sizeof(RICH_SIGNATURE)) / sizeof(RICH_VERSION_INFO); + i++) + { + if (version == RICH_VERSION_VERSION(clear_rich_signature->versions[i].id_version)) + return_integer(1); + } + + return_integer(0); +} + +define_function(rich_toolid) +{ + YR_OBJECT* module = module(); + uint64_t toolid = integer_argument(1); + size_t rich_len; + PRICH_SIGNATURE clear_rich_signature; + SIZED_STRING* rich_string; + int i; + + // Check if the required fields are set + if (is_undefined(module, "rich_signature.length")) return_integer(UNDEFINED); rich_len = get_integer(module, "rich_signature.length"); @@ -1846,7 +1875,7 @@ define_function(rich_version) i < (rich_len - sizeof(RICH_SIGNATURE)) / sizeof(RICH_VERSION_INFO); i++) { - if(version == RICH_VERSION_VERSION(clear_rich_signature->versions[i].id_version)) + if (toolid == RICH_VERSION_ID(clear_rich_signature->versions[i].id_version)) return_integer(1); } @@ -1985,6 +2014,8 @@ begin_declarations; declare_integer("key"); declare_string("raw_data"); declare_string("clear_data"); + declare_function("version", "i", "i", rich_version); + declare_function("toolid", "i", "i", rich_toolid); end_struct("rich_signature"); #if defined(HAVE_LIBCRYPTO) @@ -1999,7 +2030,6 @@ begin_declarations; declare_function("imports", "s", "i", imports_dll); declare_function("locale", "i", "i", locale); declare_function("language", "i", "i", language); - declare_function("rich_version", "i", "i", rich_version); declare_integer("resource_timestamp") begin_struct("resource_version"); From 23485b4d4c57d39f49b804d11245143e1c672984 Mon Sep 17 00:00:00 2001 From: mrexodia Date: Fri, 27 Nov 2015 21:44:20 +0100 Subject: [PATCH 3/3] implemented suggestions (now both rich_signature.version and rich_signature.toolid have overloads) --- docs/modules/pe.rst | 10 +++--- libyara/modules/pe.c | 77 +++++++++++++++++++++++--------------------- 2 files changed, 47 insertions(+), 40 deletions(-) diff --git a/docs/modules/pe.rst b/docs/modules/pe.rst index 292c6ddb87..41ead7089a 100644 --- a/docs/modules/pe.rst +++ b/docs/modules/pe.rst @@ -425,23 +425,25 @@ Reference Data after being decrypted by XORing it with the key. - .. c:function:: version(version) + .. c:function:: version(version, [toolid]) .. versionadded:: 3.5.0 Function returning true if the PE has the specified *version* in the PE's rich - signature. More information can be found here: + signature. Provide the optional *toolid* argument to only match when both match + for one entry. More information can be found here: http://www.ntcore.com/files/richsign.htm *Example: pe.rich_signature.version(21005)* - .. c:function:: toolid(id) + .. c:function:: toolid(toolid, [version]) .. versionadded:: 3.5.0 Function returning true if the PE has the specified *id* in the PE's rich - signature. More information can be found here: + signature. Provide the optional *version* argument to only match when both + match for one entry. More information can be found here: http://www.ntcore.com/files/richsign.htm diff --git a/libyara/modules/pe.c b/libyara/modules/pe.c index 297db404f9..a3dc7e3829 100644 --- a/libyara/modules/pe.c +++ b/libyara/modules/pe.c @@ -1814,10 +1814,8 @@ define_function(language) return_integer(0); } -define_function(rich_version) +static uint64_t rich_internal(YR_OBJECT* module, uint64_t version, uint64_t toolid) { - YR_OBJECT* module = module(); - uint64_t version = integer_argument(1); size_t rich_len; PRICH_SIGNATURE clear_rich_signature; SIZED_STRING* rich_string; @@ -1825,14 +1823,17 @@ define_function(rich_version) // Check if the required fields are set if (is_undefined(module, "rich_signature.length")) - return_integer(UNDEFINED); + return UNDEFINED; rich_len = get_integer(module, "rich_signature.length"); rich_string = get_string(module, "rich_signature.clear_data"); // If the clear_data was not set, return UNDEFINED if (rich_string == NULL) - return_integer(UNDEFINED); + return UNDEFINED; + + if (version == UNDEFINED && toolid == UNDEFINED) + return 0; clear_rich_signature = (PRICH_SIGNATURE)rich_string->c_string; @@ -1841,45 +1842,47 @@ define_function(rich_version) i < (rich_len - sizeof(RICH_SIGNATURE)) / sizeof(RICH_VERSION_INFO); i++) { - if (version == RICH_VERSION_VERSION(clear_rich_signature->versions[i].id_version)) - return_integer(1); + DWORD id_version = clear_rich_signature->versions[i].id_version; + bool matchVersion = version == RICH_VERSION_VERSION(id_version); + bool matchToolid = toolid == RICH_VERSION_ID(id_version); + if (version != UNDEFINED && toolid != UNDEFINED) //check version and toolid + { + if (matchVersion && matchToolid) + return 1; + } + else if (version != UNDEFINED) //check only version + { + if (matchVersion) + return 1; + } + else if (toolid != UNDEFINED) //check only toolid + { + if (matchToolid) + return 1; + } } - return_integer(0); + return 0; } -define_function(rich_toolid) +define_function(rich_version) { - YR_OBJECT* module = module(); - uint64_t toolid = integer_argument(1); - size_t rich_len; - PRICH_SIGNATURE clear_rich_signature; - SIZED_STRING* rich_string; - int i; - - // Check if the required fields are set - if (is_undefined(module, "rich_signature.length")) - return_integer(UNDEFINED); - - rich_len = get_integer(module, "rich_signature.length"); - rich_string = get_string(module, "rich_signature.clear_data"); - - // If the clear_data was not set, return UNDEFINED - if (rich_string == NULL) - return_integer(UNDEFINED); + return_integer(rich_internal(module(), integer_argument(1), UNDEFINED)); +} - clear_rich_signature = (PRICH_SIGNATURE)rich_string->c_string; +define_function(rich_version_toolid) +{ + return_integer(rich_internal(module(), integer_argument(1), integer_argument(2))); +} - // Loop over the versions in the rich signature - for (i = 0; - i < (rich_len - sizeof(RICH_SIGNATURE)) / sizeof(RICH_VERSION_INFO); - i++) - { - if (toolid == RICH_VERSION_ID(clear_rich_signature->versions[i].id_version)) - return_integer(1); - } +define_function(rich_toolid) +{ + return_integer(rich_internal(module(), UNDEFINED, integer_argument(1))); +} - return_integer(0); +define_function(rich_toolid_version) +{ + return_integer(rich_internal(module(), integer_argument(2), integer_argument(1))); } begin_declarations; @@ -2015,7 +2018,9 @@ begin_declarations; declare_string("raw_data"); declare_string("clear_data"); declare_function("version", "i", "i", rich_version); + declare_function("version", "ii", "i", rich_version_toolid); declare_function("toolid", "i", "i", rich_toolid); + declare_function("toolid", "ii", "i", rich_toolid_version); end_struct("rich_signature"); #if defined(HAVE_LIBCRYPTO)