diff --git a/README.md b/README.md index 9f362c6..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.3.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 769b124..b989aac 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}") @@ -36,18 +39,49 @@ 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): 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: 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("= 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) + @@ -96,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, @@ -112,48 +179,62 @@ 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("