Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle coded index variable sizes #7

Merged
3 commits merged into from
Jun 15, 2016
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
107 changes: 76 additions & 31 deletions getnetguids.py
Original file line number Diff line number Diff line change
Expand Up @@ -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("<Q", tilde[8:16])[0])[2:][::-1]]
# tables_present_count = len([a for a in tables_present if a])
# print "Tables present count: {0}".format(tables_present_count)

# print "Which tables are sorted list: {0}".format([tilde[16:24]])

row_counts = [0] * 64
t_offset = 24
for index in xrange(len(tables_present)):
if index < len(tables_present) and tables_present[index]:
row_counts[index] = struct.unpack("<I", tilde[t_offset:t_offset + 4])[0]
t_offset += 4

has_custom_attribute_tables = [
0x06, 0x04, 0x01, 0x02, 0x08, 0x09, 0x0A, 0x00,
0x0E, # Permission aka DeclSecurity (typo in the spec)
0x17, 0x14, 0x11, 0x1A, 0x1B, 0x20, 0x23, 0x26,
0x27, 0x2A, 0x2C, 0x2B
]
custom_attribute_type_tables = [0x06, 0x0A]
resolution_scope_tables = [0x00, 0x1A, 0x23, 0x01]
type_def_or_ref_tables = [0x02, 0x01, 0x1B]
member_ref_tables = [0x02, 0x01, 0x1A, 0x06, 0x1B]

big_has_custom_attribute = any([row_counts[x] >= 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) +
Expand All @@ -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,
Expand All @@ -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("<Q", tilde[8:16])[0])[2:][::-1]]
# tables_present_count = len([a for a in tables_present if a])
# print "Tables present count: {0}".format(tables_present_count)

# print "Which tables are sorted list: {0}".format([tilde[16:24]])

row_counts = [0] * len(tables_present)
t_offset = 24
for index in xrange(len(tables_present)):
if tables_present[index]:
row_counts[index] = struct.unpack("<I", tilde[t_offset:t_offset + 4])[0]
t_offset += 4

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("<H", tilde[t_offset:t_offset + 2])[0]
# type_index = struct.unpack("<H", tilde[t_offset + 2:t_offset + 4])[0]
if blob_heap_index_length == 2:
blob_index = struct.unpack("<H", tilde[t_offset + 4:t_offset + 6])[0]
data_value = read_blob(heaps["#Blob"][blob_index:])
# In the most strict interpretation, a typelib id is expressed as a
# GuidAttribute on the current assembly.
# To check that it's actually a GuidAttribute we'd have to support parsing
# .NET signatures, so it's safer to assume a MemberRef attribute owned by a
# TypeRef on an AssemblyRow with a value matching a guid is PROBABLY the typelib id

row_offset = t_offset

if big_has_custom_attribute:
parent_index = struct.unpack("<I", tilde[row_offset:row_offset + 4])[0]
row_offset += 4
else:
parent_index = struct.unpack("<H", tilde[row_offset:row_offset + 2])[0]
row_offset += 2

if big_custom_attribute_type:
type_index = struct.unpack("<I", tilde[row_offset:row_offset + 4])[0]
row_offset += 4
else:
blob_index = struct.unpack("<I", tilde[t_offset + 4:t_offset + 8])[0]
type_index = struct.unpack("<H", tilde[row_offset:row_offset + 2])[0]
row_offset += 2

parent_index_table = parent_index & 0x1f
type_index_table = type_index & 0x07

# We only really care if the parent is an Assembly and the attribute is constructed
# using a MemberRef. MemberRef because a MethodDef is never going to be used for a
# GuidAttribute. This is because GuidAttribute is from mscorlib, so always an external
# assembly, so always reached via TypeRef/MemberRef.
if parent_index_table == 0x0e and type_index_table == 0x03:
if blob_heap_index_length == 2:
blob_index = struct.unpack("<H", tilde[row_offset:row_offset + 2])[0]
row_offset += 2
else:
blob_index = struct.unpack("<I", tilde[row_offset:row_offset + 4])[0]
row_offset += 4

data_value = read_blob(heaps["#Blob"][blob_index:])
if guid_regex.match(data_value):
return {"mvid": extracted_mvid.lower(), "typelib_id": data_value.lower(), "compiled": compiled}
if guid_regex.match(data_value):
return {"mvid": extracted_mvid.lower(), "typelib_id": data_value.lower(), "compiled": compiled}
t_offset += row_type_widths[0x0c]
return {"mvid": extracted_mvid.lower(), "compiled": compiled}
except KeyboardInterrupt:
Expand Down