diff --git a/volatility/framework/symbols/windows/mspdb.json b/volatility/framework/symbols/windows/mspdb.json index 99cc34b19..cea1ea2ec 100644 --- a/volatility/framework/symbols/windows/mspdb.json +++ b/volatility/framework/symbols/windows/mspdb.json @@ -863,11 +863,11 @@ "offset": 8, "type": { "kind": "base", - "name": "unsigned long" + "name": "unsigned short" } }, "name": { - "offset": 12, + "offset": 10, "type": { "kind": "base", "name": "string" diff --git a/volatility/framework/symbols/windows/mspdb.py b/volatility/framework/symbols/windows/mspdb.py index 20cb32133..e451ca9f3 100644 --- a/volatility/framework/symbols/windows/mspdb.py +++ b/volatility/framework/symbols/windows/mspdb.py @@ -42,13 +42,13 @@ primatives = { 0x70: ("rchar", { "endian": "little", "kind": "char", - "signed": False, + "signed": True, "size": 1 }), 0x71: ("wchar", { "endian": "little", "kind": "int", - "signed": False, + "signed": True, "size": 2 }), # 0x7a: ("rchar16", {}), @@ -99,7 +99,7 @@ primatives = { "endian": "little", "kind": "int", "signed": False, - "size": 2 + "size": 4 }), 0x13: ("int64", { "endian": "little", @@ -152,43 +152,43 @@ primatives = { 0x46: ("f16", { "endian": "little", "kind": "float", - "signed": False, + "signed": True, "size": 2 }), 0x40: ("f32", { "endian": "little", "kind": "float", - "signed": False, + "signed": True, "size": 4 }), 0x45: ("f32pp", { "endian": "little", "kind": "float", - "signed": False, + "signed": True, "size": 4 }), 0x44: ("f48", { "endian": "little", "kind": "float", - "signed": False, + "signed": True, "size": 6 }), - 0x41: ("f64", { + 0x41: ("double", { "endian": "little", "kind": "float", - "signed": False, + "signed": True, "size": 8 }), 0x42: ("f80", { "endian": "little", "kind": "float", - "signed": False, + "signed": True, "size": 10 }), 0x43: ("f128", { "endian": "little", "kind": "float", - "signed": False, + "signed": True, "size": 16 }) } @@ -200,13 +200,13 @@ indirections = { "signed": False, "size": 2 }), - 0x400: ("pointer", { + 0x400: ("pointer32", { "endian": "little", "kind": "int", "signed": False, "size": 4 }), - 0x600: ("pointer64", { + 0x600: ("pointer", { "endian": "little", "kind": "int", "signed": False, @@ -215,6 +215,13 @@ indirections = { } +class ForwardArrayCount: + + def __init__(self, size, element_type): + self.element_type = element_type + self.size = size + + class PdbReader: """Class to read Microsoft PDB files""" @@ -282,6 +289,8 @@ class PdbReader: self.bases = {} self.user_types = {} + type_references = {} + offset = header.header_size # Ensure we use the same type everywhere length_type = "unsigned short" @@ -293,7 +302,11 @@ class PdbReader: raise ValueError("Non-integer length provided") offset += length_len output, consumed = self.consume_type(module, offset, length) - self.types.append(output) + leaf_type, name, value = output + if name == '': + name = '__unnamed_' + hex(len(self.types) + 0x1000)[2:] + type_references[name] = len(self.types) + self.types.append((leaf_type, name, value)) offset += length type_index += 1 # Since types can only refer to earlier types, assigning the name at this point is fine @@ -302,32 +315,58 @@ class PdbReader: raise ValueError("Type values did not fill the TPI stream correctly") for index in range(len(self.types)): - if isinstance(self.types[index], Tuple): - leaf_type, name, value = self.types[index] - 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 - ]: - if not value.properties.forward_reference: - self.user_types[name] = { - "kind": "struct", - "size": 0, - "fields": self.convert_fields(value.fields - 0x1000) - } - if leaf_type in [leaf_type.LF_UNION]: - if not value.properties.forward_reference: - # Deal with UNION types - self.user_types[name] = { - "kind": "union", - "size": 0, - "fields": self.convert_fields(value.fields - 0x1000) - } + leaf_type, name, value = self.types[index] + 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 + ]: + if not value.properties.forward_reference: + self.user_types[name] = { + "kind": "struct", + "size": value.size, + "fields": self.convert_fields(value.fields - 0x1000) + } + if leaf_type in [leaf_type.LF_UNION]: + if not value.properties.forward_reference: + # Deal with UNION types + self.user_types[name] = { + "kind": "union", + "size": value.size, + "fields": self.convert_fields(value.fields - 0x1000) + } + + # Re-run through for ForwardSizeReferences + self.user_types = self.replace_forward_size_references(self.user_types, type_references) with open("file.out", "w") as f: json.dump({"user_types": self.user_types, "base_types": self.bases}, f, indent = 2, sort_keys = True) return header + def get_json(self): + return {"user_types": self.user_types, "base_types": self.bases} + + def replace_forward_size_references(self, types, type_references): + """Finds all ForwardArrayCounts and calculates them one ForwardReferences have been resolved""" + if isinstance(types, dict): + for k, v in types.items(): + types[k] = self.replace_forward_size_references(v, type_references) + elif isinstance(types, list): + new_types = [] + for v in types: + new_types.append(self.replace_forward_size_references(v, type_references)) + types = new_types + elif isinstance(types, ForwardArrayCount): + element_type = types.element_type + # If we're a forward array count, we need to do the calculation now after all the types have been processed + if element_type > 0x1000: + _, name, _ = self.types[types.element_type - 0x1000] + # If there's no name, the original size is probably fine + if name: + element_type = type_references[name] + 0x1000 + return types.size // self.get_size_from_index(element_type) + return types + def get_type_from_index(self, index: int) -> Dict[str, Any]: """Takes a type index and returns appropriate dictionary""" if index < 0x1000: @@ -346,7 +385,11 @@ class PdbReader: if leaf_type in [leaf_type.LF_MODIFIER]: result = self.get_type_from_index(value.subtype_index) elif leaf_type in [leaf_type.LF_ARRAY, leaf_type.LF_ARRAY_ST, leaf_type.LF_STRIDED_ARRAY]: - pass + result = { + "count": ForwardArrayCount(value.size, value.element_type), + "kind": "array", + "subtype": self.get_type_from_index(value.element_type) + } elif leaf_type in [leaf_type.LF_BITFIELD]: result = { "kind": "bitfield", @@ -357,14 +400,44 @@ class PdbReader: elif leaf_type in [leaf_type.LF_POINTER]: result = {"kind": "pointer", "subtype": self.get_type_from_index(value.subtype_index)} elif leaf_type in [leaf_type.LF_PROCEDURE]: - return {} + return {"kind": "function"} elif leaf_type in [leaf_type.LF_UNION]: result = {"kind": "union", "name": name} + elif leaf_type in [leaf_type.LF_ENUM]: + result = {"kind": "enum", "name": name} elif not name: import pdb pdb.set_trace() return result + def get_size_from_index(self, index: int) -> int: + if index < 0x1000: + _, base = primatives[index & 0xff] + return base['size'] + else: + leaf_type, name, value = self.types[index - 0x1000] + if leaf_type in [ + leaf_type.LF_UNION, leaf_type.LF_CLASS, leaf_type.LF_CLASS_ST, leaf_type.LF_STRUCTURE, + leaf_type.LF_STRUCTURE_ST, leaf_type.LF_INTERFACE + ]: + if not value.properties.forward_reference: + return value.size + elif leaf_type in [leaf_type.LF_ARRAY, leaf_type.LF_ARRAY_ST, leaf_type.LF_STRIDED_ARRAY]: + return value.size + elif leaf_type in [leaf_type.LF_MODIFIER, leaf_type.LF_ENUM]: + return self.get_size_from_index(value.subtype_index) + elif leaf_type in [leaf_type.LF_MEMBER]: + return self.get_size_from_index(value.field_type) + elif leaf_type in [leaf_type.LF_BITFIELD]: + return self.get_size_from_index(value.underlying_type) + elif leaf_type in [leaf_type.LF_POINTER]: + return value.size + elif leaf_type in [leaf_type.LF_PROCEDURE]: + return -1 + else: + raise ValueError("Unable to determine size of leaf_type {}".format(leaf_type.lookup())) + return 1 + def consume_type( self, module: interfaces.context.ModuleInterface, offset: int, length: int ) -> Tuple[Tuple[Optional[interfaces.objects.ObjectInterface], Optional[str], Optional[interfaces.objects. @@ -475,7 +548,3 @@ if __name__ == '__main__': ### TESTING # x = ctx.object('pdb1!BIG_MSF_HDR', reader.pdb_layer_name, 0) header = reader.read_tpi_stream() - - import pdb - - pdb.set_trace()