From 33b87b87a37b1ccf3c9865967f82016fc7977deb Mon Sep 17 00:00:00 2001 From: bwall Date: Mon, 23 Nov 2015 10:48:58 -0800 Subject: [PATCH 1/4] Resolving improper value returns for #2 and #3 --- README.md | 2 +- getnetguids.py | 35 +++++++++++++++++++++++++++++++---- setup.py | 2 +- 3 files changed, 33 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 9f362c6..ef906b1 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,6 @@ optional arguments: -v, --version show program's version number and exit -r, --recursive Scan paths recursively -getnetguids v1.3.0 by Brian Wallace (@botnet_hunter) +getnetguids v1.4.0 by Brian Wallace (@botnet_hunter) ``` \ No newline at end of file diff --git a/getnetguids.py b/getnetguids.py index 769b124..cd2186f 100644 --- a/getnetguids.py +++ b/getnetguids.py @@ -36,6 +36,13 @@ def get_assembly_guids(assembly_path): try: try: pe = pefile.PE(assembly_path) + + txt_start = None + txt_end = None + for section in pe.sections: + if section.Name.startswith(".text\x00"): + txt_start = section.PointerToRawData + txt_end = txt_start + section.SizeOfRawData except pefile.PEFormatError: return None if not is_dot_net_assembly(pe): @@ -44,10 +51,28 @@ def get_assembly_guids(assembly_path): # Removed strict parsing and opted for simple searching method to support malformed assemblies with open(assembly_path, "rb") as assembly_file_handler: file_data = assembly_file_handler.read() - for i in [file_data[l.start():] for l in re.finditer("\x42\x53\x4a\x42", file_data)]: + + text_section = file_data[txt_start:][:txt_end] + + + mdo = pe.get_offset_from_rva(struct.unpack(" Date: Fri, 29 Apr 2016 17:44:22 -0700 Subject: [PATCH 2/4] Updates (#5) * add compile time to output very useful when comparing a large set from same family * fix typo * format output cleaner to read * output to CSV option CSV output and version 1.4.1 --- getnetguids.py | 47 ++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 38 insertions(+), 9 deletions(-) diff --git a/getnetguids.py b/getnetguids.py index cd2186f..790df69 100644 --- a/getnetguids.py +++ b/getnetguids.py @@ -2,6 +2,9 @@ import pefile import struct import re +import datetime +import csv +import hashlib guid_regex = re.compile("[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}") @@ -47,6 +50,12 @@ def get_assembly_guids(assembly_path): return None if not is_dot_net_assembly(pe): return None + + #Compile TimeDateStamp + try: + compiled = get_compiletime(pe) + except Exception: + compiled = "Error" # Removed strict parsing and opted for simple searching method to support malformed assemblies with open(assembly_path, "rb") as assembly_file_handler: @@ -178,9 +187,9 @@ def get_assembly_guids(assembly_path): blob_index = struct.unpack(" Date: Tue, 14 Jun 2016 17:45:08 -0700 Subject: [PATCH 3/4] Handle coded index variable sizes (#7) * Detect when coded indices are 4 bytes rather than 2 * Be more careful about what attribute might be typelib id Since typelib ids are recorded as a GuidAttribute on an assembly, any guids from other CustomAttribute entries that are not on an assembly and are not constructed from a MemberRef can be discarded. MemberRef can be used to filter because GuidAttribute comes from mscorlib, so unless we're looking at mscorlib itself GuidAttribute will always be constructed using a MemberRef into another assembly. * Tables that are not present should have a row count of 0 If higher-index tables were not present, but their row count affects a coded index, the row_count array may not have been large enough to index for all tables the coded index can reach. As a fix, ensure the row_count table is always 64 entries. --- getnetguids.py | 107 +++++++++++++++++++++++++++++++++++-------------- 1 file changed, 76 insertions(+), 31 deletions(-) diff --git a/getnetguids.py b/getnetguids.py index 790df69..d91b4cc 100644 --- a/getnetguids.py +++ b/getnetguids.py @@ -122,6 +122,39 @@ def get_assembly_guids(assembly_path): guid_heap_index_length = 2 if ord(tilde[6:7]) & 0x02 == 0x00 else 4 blob_heap_index_length = 2 if ord(tilde[6:7]) & 0x04 == 0x00 else 4 + # print "Reserved 0x01: {0}".format([tilde[7:8]]) + # print "Table list: {0}".format([tilde[8:16]]) + + tables_present = [x == "1" for x in bin(struct.unpack("= 2**(16 - 5) for x in has_custom_attribute_tables]) + big_custom_attribute_type = any([row_counts[x] >= 2**(16 - 3) for x in custom_attribute_type_tables]) + big_resolution_scope = any([row_counts[x] >= 2**(16 - 2) for x in resolution_scope_tables]) + big_type_def_or_ref = any([row_counts[x] >= 2**(16 - 2) for x in type_def_or_ref_tables]) + big_member_ref_parent = any([row_counts[x] >= 2**(16 - 3) for x in member_ref_tables]) + # Build row length for each type up to CustomAttr row_type_widths = [ # 0x00 Module = Generation (2 bytes) + Name (String heap index) + Mvid (Guid heap index) + @@ -130,11 +163,11 @@ def get_assembly_guids(assembly_path): # 0x01 TypeRef = ResolutionScope (ResolutionScope index) + TypeName (String heap) + # TypeNamespace (String heap) - 2 + (strings_heap_index_length * 2), + (4 if big_resolution_scope else 2) + (strings_heap_index_length * 2), # 0x02 TypeDef = Flags(2 bytes) + TypeName(String heap index) +TypeNamespace(String heap index)+ # Extends (TypeDefOrRef index) + FieldList (index into field table) + # MethodList (index into MethodDef table) + ? - 10 + (strings_heap_index_length * 2), + 8 + (4 if big_type_def_or_ref else 2) + (strings_heap_index_length * 2), 0, # 0x03 None # 0x04 Field = Flags (2 bytes) + Name (String heap index) + Signature (Blob heap index) 2 + strings_heap_index_length + blob_heap_index_length, @@ -146,48 +179,60 @@ def get_assembly_guids(assembly_path): # 0x08 Param = Flags (2 bytes) + Sequence (2 bytes) + Name (String heap index) 4 + strings_heap_index_length, # 0x09 InterfaceImpl = Class (TypeDef index) + Interface (TypeDefOrRef index) - 4, + 2 + (4 if big_type_def_or_ref else 2), # 0x0a MemberRef = Class(MemberRefParent) + Name(String heap index) + Signature(Blob heap index) - 2 + strings_heap_index_length + blob_heap_index_length, + (4 if big_member_ref_parent else 2) + strings_heap_index_length + blob_heap_index_length, # 0x0b Constant = Type (?) + Parent + Value (Blob heap index) 4 + blob_heap_index_length, # 0x0c CustomAttr = Parent + Type (CustomAttributeType) + Value (Blob heap index) - 4 + blob_heap_index_length, + (4 if big_has_custom_attribute else 2) + (4 if big_custom_attribute_type else 2) + blob_heap_index_length, # Don't care about the rest ] - # print "Reserved 0x01: {0}".format([tilde[7:8]]) - # print "Table list: {0}".format([tilde[8:16]]) - - tables_present = [x == "1" for x in bin(struct.unpack(" Date: Wed, 15 Jun 2016 17:52:39 +0200 Subject: [PATCH 4/4] Minor updates (#8) * Update version number * Update version number * Update README.md --- README.md | 7 ++++--- getnetguids.py | 2 +- setup.py | 4 ++-- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index ef906b1..1e8539b 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ http://blog.cylance.com/you-me-and-.net-guids ``` $ getnetguids -h -usage: getnetguids [-h] [-v] [-r] [path [path ...]] +usage: getnetguids [-h] [-v] [-r] [-c] [path [path ...]] Extracts Typelib IDs and MVIDs from .NET assemblies. @@ -19,7 +19,8 @@ optional arguments: -h, --help show this help message and exit -v, --version show program's version number and exit -r, --recursive Scan paths recursively + -c, --csv Save to CSV -getnetguids v1.4.0 by Brian Wallace (@botnet_hunter) +getnetguids v1.4.2 by Brian Wallace (@botnet_hunter) -``` \ No newline at end of file +``` diff --git a/getnetguids.py b/getnetguids.py index d91b4cc..b989aac 100644 --- a/getnetguids.py +++ b/getnetguids.py @@ -249,7 +249,7 @@ def get_assembly_guids(assembly_path): if __name__ == "__main__": from argparse import ArgumentParser - version = "1.4.1" + version = "1.4.2" parser = ArgumentParser( prog=__file__, diff --git a/setup.py b/setup.py index 7b6be4f..31e8467 100644 --- a/setup.py +++ b/setup.py @@ -3,11 +3,11 @@ from distutils.core import setup setup(name='getnetguids', - version='1.4.0', + version='1.4.2', description='Extracts Typelib IDs and MVIDs from .NET assemblies.', author='Brian Wallace', url='https://github.com/bwall/getnetguids', py_modules=['getnetguids'], scripts=['getnetguids.py'], install_requires=['pefile', 'argparse'], - ) \ No newline at end of file + )