From 7f534ca7244fb09940c0a9a93813ab52367338d9 Mon Sep 17 00:00:00 2001 From: Andy Wortman Date: Tue, 14 Jun 2016 17:05:31 -0700 Subject: [PATCH 1/3] Detect when coded indices are 4 bytes rather than 2 --- getnetguids.py | 59 ++++++++++++++++++++++++++++++++------------------ 1 file changed, 38 insertions(+), 21 deletions(-) diff --git a/getnetguids.py b/getnetguids.py index 790df69..ed41369 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,32 +179,16 @@ 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: Tue, 14 Jun 2016 17:06:35 -0700 Subject: [PATCH 2/3] 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. --- getnetguids.py | 48 ++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 38 insertions(+), 10 deletions(-) diff --git a/getnetguids.py b/getnetguids.py index ed41369..73720bd 100644 --- a/getnetguids.py +++ b/getnetguids.py @@ -192,19 +192,47 @@ def get_assembly_guids(assembly_path): for index in xrange(0x0c): t_offset += row_type_widths[index] * row_counts[index] - # todo Resolve type indexes - # todo Add identification by parent and type for index in xrange(row_counts[0x0c]): - parent_index = struct.unpack(" Date: Tue, 14 Jun 2016 17:30:00 -0700 Subject: [PATCH 3/3] 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 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/getnetguids.py b/getnetguids.py index 73720bd..d91b4cc 100644 --- a/getnetguids.py +++ b/getnetguids.py @@ -131,10 +131,10 @@ def get_assembly_guids(assembly_path): # print "Which tables are sorted list: {0}".format([tilde[16:24]]) - row_counts = [0] * len(tables_present) + row_counts = [0] * 64 t_offset = 24 for index in xrange(len(tables_present)): - if tables_present[index]: + if index < len(tables_present) and tables_present[index]: row_counts[index] = struct.unpack("