From 759a62699497301b0ae1468c8a1c02b0a7faca3f Mon Sep 17 00:00:00 2001 From: Frank Poz Date: Fri, 23 Sep 2016 01:07:37 +0000 Subject: [PATCH 1/2] meta_pe: fix rich header length check for hash calculation The original Rich Signature write-up: http://www.ntcore.com/files/richsign.htm searches 400 bytes for the "Rich" string. The pefile module searches 128 bytes for the string. I have found that 128 is sometimes not enough, and 400 feels rather large, so I have choosen a round (hex) value in between. I also take a lesson from the original write-up and search for NULL values, but added a search for the PE header as well. Note that because we rely on pefile module for the Rich Header Values, that array will be incomplete, and thus differ from that used for hash calculation, until pefile itself is fixed. --- laikaboss/modules/meta_pe.py | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/laikaboss/modules/meta_pe.py b/laikaboss/modules/meta_pe.py index 673685f..15f10bc 100644 --- a/laikaboss/modules/meta_pe.py +++ b/laikaboss/modules/meta_pe.py @@ -244,7 +244,9 @@ def parseRich(self, pe): result['Rich Header Values'] = data result['Checksum'] = pe.RICH_HEADER.checksum - result['Hashes'] = self.richHeaderHashes(pe) + hashes = self.richHeaderHashes(pe) + if hashes: + result['Hashes'] = hashes return result @@ -253,10 +255,28 @@ def richHeaderHashes(pe): """ Returns hashes of the Rich PE header """ - rich_data = pe.get_data(0x80, 0x80) - data = list(struct.unpack('<32I', rich_data)) + rich_data = pe.get_data(0x80, 0xc0) + data = list(struct.unpack('<48I', rich_data)) checksum = data[1] - rich_end = data.index(0x68636952) + try: + # look for Rich string + rich_end = data.index(0x68636952) + except ValueError: + # if that doesn't work, then look for PE header + try: + rich_end = data.index(0x4550) + # check if it ends sooner than the PE header + if 0 in data: + i = data.index(0) + if i < rich_end: + rich_end = i + except ValueError: + # if no PE header in range, then try just NULLs + if 0 in data: + rich_end = data.index(0) + else: + logging.debug('Unable to identify end of richheader') + return None md5 = hashlib.md5() sha1 = hashlib.sha1() sha256 = hashlib.sha256() From d99c8197bb4ab3c741de7777a6e8c90f355a15c8 Mon Sep 17 00:00:00 2001 From: Frank Poz Date: Sat, 2 Sep 2017 03:08:19 +0000 Subject: [PATCH 2/2] Simplify rich header hash calculation with latest pefile. The latest version of pefile provides easy access to the deobfuscated rich header by accessing the 'clear_data' key of the parsed rich header. --- laikaboss/modules/meta_pe.py | 38 +++++++++--------------------------- 1 file changed, 9 insertions(+), 29 deletions(-) diff --git a/laikaboss/modules/meta_pe.py b/laikaboss/modules/meta_pe.py index 15f10bc..f1573d8 100644 --- a/laikaboss/modules/meta_pe.py +++ b/laikaboss/modules/meta_pe.py @@ -255,35 +255,15 @@ def richHeaderHashes(pe): """ Returns hashes of the Rich PE header """ - rich_data = pe.get_data(0x80, 0xc0) - data = list(struct.unpack('<48I', rich_data)) - checksum = data[1] - try: - # look for Rich string - rich_end = data.index(0x68636952) - except ValueError: - # if that doesn't work, then look for PE header - try: - rich_end = data.index(0x4550) - # check if it ends sooner than the PE header - if 0 in data: - i = data.index(0) - if i < rich_end: - rich_end = i - except ValueError: - # if no PE header in range, then try just NULLs - if 0 in data: - rich_end = data.index(0) - else: - logging.debug('Unable to identify end of richheader') - return None - md5 = hashlib.md5() - sha1 = hashlib.sha1() - sha256 = hashlib.sha256() - for i in range(rich_end): - md5.update(struct.pack('