Add in padding support and TypeProperties.

This commit is contained in:
Mike Auty
2019-07-30 22:14:19 +01:00
committed by ikelos
parent c90e57470f
commit af92cd4d6c
2 changed files with 205 additions and 16 deletions
+176 -2
View File
@@ -22,6 +22,180 @@
"kind": "struct",
"size": 2
},
"Type_Properties": {
"fields": {
"packed": {
"offset": 0,
"type": {
"bit_length": 1,
"bit_position": 0,
"kind": "bitfield",
"type": {
"kind": "base",
"name": "unsigned short"
}
}
},
"constructors": {
"offset": 0,
"type": {
"bit_length": 1,
"bit_position": 1,
"kind": "bitfield",
"type": {
"kind": "base",
"name": "unsigned short"
}
}
},
"overloaded_operators": {
"offset": 0,
"type": {
"bit_length": 1,
"bit_position": 2,
"kind": "bitfield",
"type": {
"kind": "base",
"name": "unsigned short"
}
}
},
"nested_type": {
"offset": 0,
"type": {
"bit_length": 1,
"bit_position": 3,
"kind": "bitfield",
"type": {
"kind": "base",
"name": "unsigned short"
}
}
},
"contains_nested": {
"offset": 0,
"type": {
"bit_length": 1,
"bit_position": 4,
"kind": "bitfield",
"type": {
"kind": "base",
"name": "unsigned short"
}
}
},
"overloaded_assignment": {
"offset": 0,
"type": {
"bit_length": 1,
"bit_position": 5,
"kind": "bitfield",
"type": {
"kind": "base",
"name": "unsigned short"
}
}
},
"overloaded_casting": {
"offset": 0,
"type": {
"bit_length": 1,
"bit_position": 6,
"kind": "bitfield",
"type": {
"kind": "base",
"name": "unsigned short"
}
}
},
"forward_reference": {
"offset": 0,
"type": {
"bit_length": 1,
"bit_position": 7,
"kind": "bitfield",
"type": {
"kind": "base",
"name": "unsigned short"
}
}
},
"scoped_definition": {
"offset": 0,
"type": {
"bit_length": 1,
"bit_position": 8,
"kind": "bitfield",
"type": {
"kind": "base",
"name": "unsigned short"
}
}
},
"unique_name": {
"offset": 0,
"type": {
"bit_length": 1,
"bit_position": 9,
"kind": "bitfield",
"type": {
"kind": "base",
"name": "unsigned short"
}
}
},
"sealed": {
"offset": 0,
"type": {
"bit_length": 1,
"bit_position": 10,
"kind": "bitfield",
"type": {
"kind": "base",
"name": "unsigned short"
}
}
},
"hfa": {
"offset": 0,
"type": {
"bit_length": 2,
"bit_position": 11,
"kind": "bitfield",
"type": {
"kind": "base",
"name": "unsigned short"
}
}
},
"intrinsic_type": {
"offset": 0,
"type": {
"bit_length": 1,
"bit_position": 12,
"kind": "bitfield",
"type": {
"kind": "base",
"name": "unsigned short"
}
}
},
"mocom": {
"offset": 0,
"type": {
"bit_length": 2,
"bit_position": 13,
"kind": "bitfield",
"type": {
"kind": "base",
"name": "unsigned short"
}
}
}
},
"kind": "struct",
"size": 2
},
"SI_PERSIST": {
"fields": {
"StreamInfoSize": {
@@ -255,8 +429,8 @@
"properties": {
"offset": 2,
"type": {
"kind": "base",
"name": "unsigned short"
"kind": "struct",
"name": "Type_Properties"
}
},
"fields": {
+29 -14
View File
@@ -10,8 +10,11 @@ from volatility.framework.layers import physical, msf
class PdbReader:
"""Class to read Microsoft PDB files"""
sub_resolvers = {""}
def __init__(self, context: interfaces.context.ContextInterface, location: str):
self._layer_name, self._context = self.load_pdb_layer(context, location)
self.types = []
@property
def context(self):
@@ -66,20 +69,22 @@ class PdbReader:
raise ValueError("Maximum TPI index is smaller than minimum TPI index, found: {} < {} ".format(
header.index_max, header.index_min))
types = {}
self.types = []
offset = header.header_size
# Ensure we use the same type everywhere
length_type = "unsigned short"
length_len = module.get_type(length_type).size
type_index = 1
while tpi_layer.maximum_address - offset > 0:
length = module.object(type_name = length_type, offset = offset)
if not isinstance(length, int):
raise ValueError("Non-integer length provided")
offset += length_len
output, consumed = self.consume_type(module, offset, length)
types.update(output)
self.types.append(output)
offset += length
type_index += 1
# Since types can only refer to earlier types, assigning the name at this point is fine
if tpi_layer.maximum_address - offset != 0:
@@ -90,6 +95,7 @@ class PdbReader:
def consume_type(self, module: interfaces.context.ModuleInterface, offset: int, length: int,
no_output = False) -> Tuple[Dict[str, Dict], int]:
"""Returns the dictionary for the type, and the number of bytes consumed"""
result = {}
leaf_type = self.context.object(
module.get_enumeration("LEAF_TYPE"), layer_name = module._layer_name, offset = offset)
consumed = leaf_type.vol.base_type.size
@@ -102,26 +108,29 @@ class PdbReader:
structure = module.object(type_name = "LF_STRUCTURE", offset = offset)
name = self.parse_string(leaf_type, structure.name, size = length - structure.vol.size - consumed)
consumed = length
result[name] = structure
elif leaf_type in [leaf_type.LF_MEMBER, leaf_type.LF_MEMBER_ST]:
member = module.object(type_name = "LF_MEMBER", offset = offset)
name = self.parse_string(leaf_type, member.name, size = length - member.vol.size - consumed)
consumed = length
result[name] = member
print(name)
consumed += member.vol.size + len(name) + 1
elif leaf_type in [leaf_type.LF_MODIFIER, leaf_type.LF_POINTER, leaf_type.LF_PROCEDURE]:
# TODO: Subresolve sub-types
obj = module.object(type_name = leaf_type.lookup(), offset = offset)
consumed = length
# Lookup and return the modified type
elif leaf_type in [leaf_type.LF_FIELDLIST]:
sub_length = length - consumed
sub_offset = offset
field = []
fields = []
while length > consumed:
subfield, sub_consumed = self.consume_type(module, sub_offset, sub_length, True)
sub_consumed += self.consume_padding(module.layer_name, sub_offset + sub_consumed)
sub_length -= sub_consumed
sub_offset += sub_consumed
consumed += sub_consumed
field.append(subfield)
pass
fields.append(subfield)
result = fields
elif leaf_type in [leaf_type.LF_BITFIELD]:
consumed = length
elif leaf_type in [leaf_type.LF_ARRAY, leaf_type.LF_ARRAY_ST, leaf_type.LF_STRIDED_ARRAY]:
@@ -131,17 +140,22 @@ class PdbReader:
else:
raise ValueError("Unhandled leaf_type: {}".format(leaf_type))
if consumed != length:
print("CONSUMED != length", hex(consumed), hex(length), leaf_type.lookup())
if not no_output:
print(leaf_type.lookup())
return {"leaf_type": leaf_type}, consumed
return result, consumed
def consume_padding(self, layer_name: str, offset: int) -> int:
"""Returns the amount of padding used between fields"""
val = self.context.layers[layer_name].read(offset, 1)
if not (int(val[0]) & 0xf0):
return 0
return (int(val[0]) & 0x0f)
def parse_string(self,
leaf_type: interfaces.objects.ObjectInterface,
structure: interfaces.objects.ObjectInterface,
size = 0) -> str:
"""Consumes either a c-string or a pascal string depending on the leaf_type"""
if leaf_type > leaf_type.LF_ST_MAX:
name = structure.cast("string", max_length = size, encoding = "latin-1")
else:
@@ -167,6 +181,7 @@ if __name__ == '__main__':
# x = ctx.object('pdb1!BIG_MSF_HDR', reader.pdb_layer_name, 0)
header = reader.read_tpi_stream()
# import pdb
#
# pdb.set_trace()
import pdb
pdb.set_trace()
print(reader.types)