diff --git a/volatility/framework/symbols/windows/mspdb.json b/volatility/framework/symbols/windows/mspdb.json index d2a6f1866..922acc9a8 100644 --- a/volatility/framework/symbols/windows/mspdb.json +++ b/volatility/framework/symbols/windows/mspdb.json @@ -2,6 +2,26 @@ "symbols": { }, "user_types": { + "pascal_string": { + "fields": { + "length": { + "offset": 0, + "type": { + "kind": "base", + "name": "unsigned char" + } + }, + "string": { + "offset": 1, + "type": { + "kind": "base", + "name": "string" + } + } + }, + "kind": "struct", + "size": 2 + }, "SI_PERSIST": { "fields": { "StreamInfoSize": { @@ -259,10 +279,24 @@ "kind": "base", "name": "unsigned long" } + }, + "size": { + "offset": 16, + "type": { + "kind": "base", + "name": "unsigned short" + } + }, + "name": { + "offset": 18, + "type": { + "kind": "base", + "name": "string" + } } }, "kind": "struct", - "size": 16 + "size": 18 }, "LF_MEMBER": { "fields": { @@ -356,11 +390,11 @@ "name": "unsigned long" } }, - "constant": { + "pointer_type": { "offset": 4, "type": { - "bit_length": 1, - "bit_position": 7, + "bit_length": 5, + "bit_position": 0, "kind": "bitfield", "type": { "kind": "base", @@ -368,7 +402,7 @@ } } }, - "reference": { + "mode": { "offset": 4, "type": { "bit_length": 3, @@ -380,11 +414,59 @@ } } }, - "pointer_type": { + "flat32": { "offset": 4, "type": { - "bit_length": 5, - "bit_position": 0, + "bit_length": 1, + "bit_position": 8, + "kind": "bitfield", + "type": { + "kind": "base", + "name": "unsigned long" + } + } + }, + "volatile": { + "offset": 4, + "type": { + "bit_length": 1, + "bit_position": 9, + "kind": "bitfield", + "type": { + "kind": "base", + "name": "unsigned long" + } + } + }, + "constant": { + "offset": 4, + "type": { + "bit_length": 1, + "bit_position": 10, + "kind": "bitfield", + "type": { + "kind": "base", + "name": "unsigned long" + } + } + }, + "unaligned": { + "offset": 4, + "type": { + "bit_length": 1, + "bit_position": 11, + "kind": "bitfield", + "type": { + "kind": "base", + "name": "unsigned long" + } + } + }, + "restricted": { + "offset": 4, + "type": { + "bit_length": 1, + "bit_position": 12, "kind": "bitfield", "type": { "kind": "base", @@ -403,10 +485,80 @@ "name": "unsigned long" } } + }, + "mocom": { + "offset": 4, + "type": { + "bit_length": 1, + "bit_position": 19, + "kind": "bitfield", + "type": { + "kind": "base", + "name": "unsigned long" + } + } + }, + "lref": { + "offset": 4, + "type": { + "bit_length": 1, + "bit_position": 20, + "kind": "bitfield", + "type": { + "kind": "base", + "name": "unsigned long" + } + } + }, + "rref": { + "offset": 4, + "type": { + "bit_length": 1, + "bit_position": 21, + "kind": "bitfield", + "type": { + "kind": "base", + "name": "unsigned long" + } + } } }, "kind": "struct", - "size": 8 + "size": 6 + }, + "LF_PROCEDURE": { + "fields": { + "return_type": { + "offset": 0, + "type": { + "kind": "base", + "name": "unsigned long" + } + }, + "attributes": { + "offset": 4, + "type": { + "kind": "base", + "name": "unsigned short" + } + }, + "parameter_count": { + "offset": 6, + "type": { + "kind": "base", + "name": "unsigned short" + } + }, + "argument_list": { + "offset": 8, + "type": { + "kind": "base", + "name": "unsigned long" + } + } + }, + "kind": "struct", + "size": 12 } }, "enums": { diff --git a/volatility/framework/symbols/windows/mspdb.py b/volatility/framework/symbols/windows/mspdb.py index 04910a84d..0646e26a2 100644 --- a/volatility/framework/symbols/windows/mspdb.py +++ b/volatility/framework/symbols/windows/mspdb.py @@ -74,11 +74,11 @@ class PdbReader: length_len = module.get_type(length_type).size 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) - # if consumed != length: - # raise ValueError("Bytes unconsumed") offset += length # Since types can only refer to earlier types, assigning the name at this point is fine @@ -87,54 +87,67 @@ class PdbReader: return header - def consume_type(self, module: interfaces.context.ModuleInterface, offset: int, - length: int) -> Tuple[Dict[str, Dict], int]: + 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""" - LeafType = self.context.object( + leaf_type = self.context.object( module.get_enumeration("LEAF_TYPE"), layer_name = module._layer_name, offset = offset) - consumed = LeafType.vol.base_type.size + consumed = leaf_type.vol.base_type.size offset += consumed - length -= consumed - if LeafType in [ - LeafType.LF_CLASS, LeafType.LF_CLASS_ST, LeafType.LF_STRUCTURE, LeafType.LF_STRUCTURE_ST, - LeafType.LF_INTERFACE + if leaf_type in [ + leaf_type.LF_CLASS, leaf_type.LF_CLASS_ST, leaf_type.LF_STRUCTURE, leaf_type.LF_STRUCTURE_ST, + leaf_type.LF_INTERFACE ]: structure = module.object(type_name = "LF_STRUCTURE", offset = offset) - consumed = structure.vol.size - elif LeafType in [LeafType.LF_MEMBER, LeafType.LF_MEMBER_ST]: + name = self.parse_string(leaf_type, structure.name, size = length - structure.vol.size - consumed) + consumed = length + elif leaf_type in [leaf_type.LF_MEMBER, leaf_type.LF_MEMBER_ST]: member = module.object(type_name = "LF_MEMBER", offset = offset) - name = member.name.cast("string", max_length = 256, encoding = "latin-1") - consumed += member.vol.size + len(name) + 1 - elif LeafType in [LeafType.LF_MODIFIER]: - modifier = module.object(type_name = "LF_MODIFIER", offset = offset) - consumed += modifier.vol.size + name = self.parse_string(leaf_type, member.name, size = length - member.vol.size - consumed) + consumed = length + 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 LeafType in [LeafType.LF_POINTER]: - pointer = module.object(type_name = "LF_POINTER", offset = offset) - consumed += pointer.vol.size - elif LeafType in [LeafType.LF_FIELDLIST]: - sub_length = length + elif leaf_type in [leaf_type.LF_FIELDLIST]: + sub_length = length - consumed sub_offset = offset field = [] while length > consumed: - subfield, sub_consumed = self.consume_type(module, sub_offset, sub_length) + subfield, sub_consumed = self.consume_type(module, sub_offset, sub_length, True) sub_length -= sub_consumed sub_offset += sub_consumed consumed += sub_consumed field.append(subfield) pass - elif LeafType in [LeafType.LF_ARGLIST]: - pass + 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]: + consumed = length + elif leaf_type in [leaf_type.LF_ARGLIST, leaf_type.LF_ENUMERATE, leaf_type.LF_ENUM, leaf_type.LF_UNION]: + consumed = length else: - raise ValueError("Unhandled leaf_type: {}".format(LeafType)) + raise ValueError("Unhandled leaf_type: {}".format(leaf_type)) - # if consumed != length: - # import pdb - # pdb.set_trace() + if consumed != length: + print("CONSUMED != length", hex(consumed), hex(length), leaf_type.lookup()) - print("LEAF_TYPE", LeafType.lookup()) - return {"leaf_type": LeafType}, consumed + if not no_output: + print(leaf_type.lookup()) + return {"leaf_type": leaf_type}, consumed + + def parse_string(self, + leaf_type: interfaces.objects.ObjectInterface, + structure: interfaces.objects.ObjectInterface, + size = 0) -> str: + if leaf_type > leaf_type.LF_ST_MAX: + name = structure.cast("string", max_length = size, encoding = "latin-1") + else: + name = structure.cast("pascal_string") + name = name.string.cast("string", max_length = name.length, encoding = "latin-1") + return name if __name__ == '__main__': @@ -154,6 +167,6 @@ 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()