Skip to content
Merged
Show file tree
Hide file tree
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
51 changes: 50 additions & 1 deletion minidump/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ class MINIDUMP_STREAM_TYPE(enum.Enum):
ceStreamDiagnosisList = 37
LastReservedStream = 0xffff


class MINIDUMP_TYPE(enum.IntFlag):
MiniDumpNormal = 0x00000000
MiniDumpWithDataSegs = 0x00000001
Expand All @@ -63,4 +64,52 @@ class MINIDUMP_TYPE(enum.IntFlag):
MiniDumpWithTokenInformation = 0x00040000
MiniDumpWithModuleHeaders = 0x00080000
MiniDumpFilterTriage = 0x00100000
MiniDumpValidTypeFlags = 0x001fffff
MiniDumpValidTypeFlags = 0x001fffff


OFFSETS = [
{ # x86 offsets
# _TEB offsets
"peb": 0x30,
# _PEB offsets
"being_debugged": 0x2,
"image_base_address": 0x8,
"process_parameters": 0x10,
# _RTL_USER_PROCESS_PARAMETERS offsets
"image_path": 0x38,
"command_line": 0x40,
"window_title": 0x70,
"dll_path": 0x30,
"current_directory": 0x24,
"standard_input": 0x18,
"standard_output": 0x1C,
"standard_error": 0x20,
"environment_variables": 0x48,
# _UNICODE_STRING offsets
"buffer": 0x4,
},
{ # x64 offsets
# _TEB offsets
"peb": 0x60,
# _PEB offsets
"being_debugged": 0x2,
"image_base_address": 0x10,
"process_parameters": 0x20,
# _RTL_USER_PROCESS_PARAMETERS offsets
"image_path": 0x60,
"command_line": 0x70,
"window_title": 0xB0,
"dll_path": 0x50,
"current_directory": 0x38,
"standard_input": 0x20,
"standard_output": 0x28,
"standard_error": 0x30,
"environment_variables": 0x80,
# _UNICODE_STRING offsets
"buffer": 0x8,
},
]


POINTER_SIZE = [4, 8] # x86 (32 bit size pointer) # x64 (64 bit size pointer)

78 changes: 77 additions & 1 deletion minidump/minidumpfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
from minidump.minidumpreader import MinidumpFileReader
from minidump.streams import *
from minidump.common_structs import *
from minidump.constants import MINIDUMP_STREAM_TYPE
from minidump.constants import MINIDUMP_STREAM_TYPE, OFFSETS, POINTER_SIZE
from minidump.directory import MINIDUMP_DIRECTORY
from minidump.streams.SystemInfoStream import PROCESSOR_ARCHITECTURE

Expand Down Expand Up @@ -78,6 +78,82 @@ def get_reader(self):
def _parse(self):
self.__parse_header()
self.__parse_directories()
self.__parse_peb()

def __read_unicode_string_property(self, buff_reader, addr, x64):
buff_reader.move(addr)
string_length = int.from_bytes(buff_reader.read(2), "little")
if not string_length:
return ""
buff_reader.move(addr + OFFSETS[x64]["buffer"])
buff_va = int.from_bytes(buff_reader.read(POINTER_SIZE[x64]), "little")
buff_reader.move(buff_va)
return buff_reader.read(string_length).decode("utf-16")

def __parse_peb(self):
self.x64 = (self.memory_segments_64 is not None) or (self.memory_segments and any(mem.start_virtual_address > 0xFFFFFFFF for mem in self.memory_segments))
offset_index = self.x64

reader = self.get_reader()
buff_reader = reader.get_buffered_reader()

buff_reader.move(self.threads.threads[0].Teb + OFFSETS[offset_index]["peb"])

self.peb_address = int.from_bytes(buff_reader.read(POINTER_SIZE[self.x64]), "little")

buff_reader.move(self.peb_address + OFFSETS[offset_index]["being_debugged"])
self.being_debugged = int.from_bytes(buff_reader.read(1), "little")

buff_reader.move(self.peb_address + OFFSETS[offset_index]["image_base_address"])
self.image_base_address = int.from_bytes(buff_reader.read(POINTER_SIZE[self.x64]), "little")

buff_reader.move(self.peb_address + OFFSETS[offset_index]["process_parameters"])
process_parameters = int.from_bytes(buff_reader.read(POINTER_SIZE[self.x64]), "little")

self.image_path = self.__read_unicode_string_property(
buff_reader, process_parameters + OFFSETS[offset_index]["image_path"], self.x64
)

self.command_line = self.__read_unicode_string_property(
buff_reader, process_parameters + OFFSETS[offset_index]["command_line"], self.x64
)

self.window_title = self.__read_unicode_string_property(
buff_reader, process_parameters + OFFSETS[offset_index]["window_title"], self.x64
)

self.dll_path = self.__read_unicode_string_property(buff_reader, process_parameters + OFFSETS[offset_index]["dll_path"],
self.x64)

self.current_directory = self.__read_unicode_string_property(
buff_reader, process_parameters + OFFSETS[offset_index]["current_directory"], self.x64
)

buff_reader.move(process_parameters + OFFSETS[offset_index]["standard_input"])
self.standard_input = int.from_bytes(buff_reader.read(POINTER_SIZE[self.x64]), "little")

buff_reader.move(process_parameters + OFFSETS[offset_index]["standard_output"])
self.standard_output = int.from_bytes(buff_reader.read(POINTER_SIZE[self.x64]), "little")

buff_reader.move(process_parameters + OFFSETS[offset_index]["standard_error"])
self.standard_error = int.from_bytes(buff_reader.read(POINTER_SIZE[self.x64]), "little")

# Parse Environment Variables from PEB
self.environment_variables = []
buff_reader.move(process_parameters + OFFSETS[offset_index]["environment_variables"])
environment_va = int.from_bytes(buff_reader.read(POINTER_SIZE[self.x64]), "little")
buff_reader.move(environment_va)

env_buffer = buff_reader.read(buff_reader.current_segment.end_address - buff_reader.current_position)
while (env_len := env_buffer.find(b"\x00\x00")) and (env_len != -1):
decoded_env = (env_buffer[:env_len] + b"\x00").decode("utf-16")
name = decoded_env.split("=")[0]
value = decoded_env.split("=")[1]
self.environment_variables.append({"name": name, "value": value})
environment_va += (len(decoded_env) + 1) * 2
buff_reader.move(environment_va)
env_buffer = buff_reader.read(buff_reader.current_segment.end_address - buff_reader.current_position)


def __parse_header(self):
self.header = MinidumpHeader.parse(self.file_handle)
Expand Down