diff --git a/docs/modules/pe.rst b/docs/modules/pe.rst index b6e6f5f23d..41ead7089a 100644 --- a/docs/modules/pe.rst +++ b/docs/modules/pe.rst @@ -425,6 +425,30 @@ Reference Data after being decrypted by XORing it with the key. + .. 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. 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(toolid, [version]) + + .. versionadded:: 3.5.0 + + Function returning true if the PE has the specified *id* in the PE's rich + 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 + + *Example: pe.rich_signature.toolid(222)* + .. c:function:: exports(function_name) Function returning true if the PE exports *function_name* or @@ -505,4 +529,3 @@ Reference *addr*. *addr* can be an offset into the file or a memory address. *Example: pe.section_index(pe.entry_point)* - 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 a8542eb99f..7a07e912d1 100644 --- a/libyara/modules/pe.c +++ b/libyara/modules/pe.c @@ -1859,6 +1859,76 @@ define_function(language) return_integer(0); } +static uint64_t rich_internal(YR_OBJECT* module, uint64_t version, uint64_t toolid) +{ + 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 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 UNDEFINED; + + if (version == UNDEFINED && toolid == UNDEFINED) + return 0; + + 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++) + { + 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 0; +} + +define_function(rich_version) +{ + return_integer(rich_internal(module(), integer_argument(1), UNDEFINED)); +} + +define_function(rich_version_toolid) +{ + return_integer(rich_internal(module(), integer_argument(1), integer_argument(2))); +} + +define_function(rich_toolid) +{ + return_integer(rich_internal(module(), UNDEFINED, integer_argument(1))); +} + +define_function(rich_toolid_version) +{ + return_integer(rich_internal(module(), integer_argument(2), integer_argument(1))); +} begin_declarations; @@ -1992,6 +2062,10 @@ begin_declarations; declare_integer("key"); 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)