|
9 | 9 | import enum |
10 | 10 | import struct |
11 | 11 | import logging |
| 12 | +from typing import List |
12 | 13 |
|
13 | 14 | from minidump.header import MinidumpHeader |
14 | 15 | from minidump.minidumpreader import MinidumpFileReader |
15 | 16 | from minidump.streams import * |
16 | 17 | from minidump.common_structs import * |
17 | | -from minidump.constants import MINIDUMP_STREAM_TYPE, OFFSETS, POINTER_SIZE |
| 18 | +from minidump.constants import MINIDUMP_STREAM_TYPE |
18 | 19 | from minidump.directory import MINIDUMP_DIRECTORY |
19 | 20 | from minidump.streams.SystemInfoStream import PROCESSOR_ARCHITECTURE |
| 21 | +from minidump.structures.peb import PEB |
20 | 22 |
|
21 | 23 |
|
22 | 24 | class MinidumpFile: |
23 | 25 | def __init__(self): |
24 | | - self.filename = None |
| 26 | + self.filename:str = None |
25 | 27 | self.file_handle = None |
26 | | - self.header = None |
27 | | - self.directories = [] |
28 | | - |
29 | | - self.threads_ex = None |
30 | | - self.threads = None |
31 | | - self.modules = None |
32 | | - self.memory_segments = None |
33 | | - self.memory_segments_64 = None |
34 | | - self.sysinfo = None |
35 | | - self.comment_a = None |
36 | | - self.comment_w = None |
37 | | - self.exception = None |
38 | | - self.handles = None |
39 | | - self.unloaded_modules = None |
40 | | - self.misc_info = None |
41 | | - self.memory_info = None |
42 | | - self.thread_info = None |
| 28 | + self.header:MinidumpHeader = None |
| 29 | + self.directories: List[MINIDUMP_DIRECTORY] = [] |
| 30 | + |
| 31 | + self.threads_ex:MinidumpThreadExList = None |
| 32 | + self.threads:MinidumpThreadList = None |
| 33 | + self.modules:MinidumpModuleList = None |
| 34 | + self.memory_segments:MinidumpMemoryList = None |
| 35 | + self.memory_segments_64:MinidumpMemory64List = None |
| 36 | + self.sysinfo:MinidumpSystemInfo = None |
| 37 | + self.comment_a:CommentStreamA = None |
| 38 | + self.comment_w:CommentStreamW = None |
| 39 | + self.exception:ExceptionList = None |
| 40 | + self.handles:MinidumpHandleDataStream = None |
| 41 | + self.unloaded_modules:MinidumpUnloadedModuleList = None |
| 42 | + self.misc_info:MinidumpMiscInfo = None |
| 43 | + self.memory_info:MinidumpMemoryInfoList = None |
| 44 | + self.thread_info:MinidumpThreadInfoList = None |
| 45 | + |
| 46 | + self.peb:PEB = None |
43 | 47 |
|
44 | 48 | @staticmethod |
45 | 49 | def parse(filename): |
@@ -78,82 +82,10 @@ def get_reader(self): |
78 | 82 | def _parse(self): |
79 | 83 | self.__parse_header() |
80 | 84 | self.__parse_directories() |
81 | | - self.__parse_peb() |
82 | | - |
83 | | - def __read_unicode_string_property(self, buff_reader, addr, x64): |
84 | | - buff_reader.move(addr) |
85 | | - string_length = int.from_bytes(buff_reader.read(2), "little") |
86 | | - if not string_length: |
87 | | - return "" |
88 | | - buff_reader.move(addr + OFFSETS[x64]["buffer"]) |
89 | | - buff_va = int.from_bytes(buff_reader.read(POINTER_SIZE[x64]), "little") |
90 | | - buff_reader.move(buff_va) |
91 | | - return buff_reader.read(string_length).decode("utf-16") |
92 | | - |
93 | | - def __parse_peb(self): |
94 | | - 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)) |
95 | | - offset_index = self.x64 |
96 | | - |
97 | | - reader = self.get_reader() |
98 | | - buff_reader = reader.get_buffered_reader() |
99 | | - |
100 | | - buff_reader.move(self.threads.threads[0].Teb + OFFSETS[offset_index]["peb"]) |
101 | | - |
102 | | - self.peb_address = int.from_bytes(buff_reader.read(POINTER_SIZE[self.x64]), "little") |
103 | | - |
104 | | - buff_reader.move(self.peb_address + OFFSETS[offset_index]["being_debugged"]) |
105 | | - self.being_debugged = int.from_bytes(buff_reader.read(1), "little") |
106 | | - |
107 | | - buff_reader.move(self.peb_address + OFFSETS[offset_index]["image_base_address"]) |
108 | | - self.image_base_address = int.from_bytes(buff_reader.read(POINTER_SIZE[self.x64]), "little") |
109 | | - |
110 | | - buff_reader.move(self.peb_address + OFFSETS[offset_index]["process_parameters"]) |
111 | | - process_parameters = int.from_bytes(buff_reader.read(POINTER_SIZE[self.x64]), "little") |
112 | | - |
113 | | - self.image_path = self.__read_unicode_string_property( |
114 | | - buff_reader, process_parameters + OFFSETS[offset_index]["image_path"], self.x64 |
115 | | - ) |
116 | | - |
117 | | - self.command_line = self.__read_unicode_string_property( |
118 | | - buff_reader, process_parameters + OFFSETS[offset_index]["command_line"], self.x64 |
119 | | - ) |
120 | | - |
121 | | - self.window_title = self.__read_unicode_string_property( |
122 | | - buff_reader, process_parameters + OFFSETS[offset_index]["window_title"], self.x64 |
123 | | - ) |
124 | | - |
125 | | - self.dll_path = self.__read_unicode_string_property(buff_reader, process_parameters + OFFSETS[offset_index]["dll_path"], |
126 | | - self.x64) |
127 | | - |
128 | | - self.current_directory = self.__read_unicode_string_property( |
129 | | - buff_reader, process_parameters + OFFSETS[offset_index]["current_directory"], self.x64 |
130 | | - ) |
131 | | - |
132 | | - buff_reader.move(process_parameters + OFFSETS[offset_index]["standard_input"]) |
133 | | - self.standard_input = int.from_bytes(buff_reader.read(POINTER_SIZE[self.x64]), "little") |
134 | | - |
135 | | - buff_reader.move(process_parameters + OFFSETS[offset_index]["standard_output"]) |
136 | | - self.standard_output = int.from_bytes(buff_reader.read(POINTER_SIZE[self.x64]), "little") |
137 | | - |
138 | | - buff_reader.move(process_parameters + OFFSETS[offset_index]["standard_error"]) |
139 | | - self.standard_error = int.from_bytes(buff_reader.read(POINTER_SIZE[self.x64]), "little") |
140 | | - |
141 | | - # Parse Environment Variables from PEB |
142 | | - self.environment_variables = [] |
143 | | - buff_reader.move(process_parameters + OFFSETS[offset_index]["environment_variables"]) |
144 | | - environment_va = int.from_bytes(buff_reader.read(POINTER_SIZE[self.x64]), "little") |
145 | | - buff_reader.move(environment_va) |
146 | | - |
147 | | - env_buffer = buff_reader.read(buff_reader.current_segment.end_address - buff_reader.current_position) |
148 | | - while (env_len := env_buffer.find(b"\x00\x00")) and (env_len != -1): |
149 | | - decoded_env = (env_buffer[:env_len] + b"\x00").decode("utf-16") |
150 | | - name = decoded_env.split("=")[0] |
151 | | - value = decoded_env.split("=")[1] |
152 | | - self.environment_variables.append({"name": name, "value": value}) |
153 | | - environment_va += (len(decoded_env) + 1) * 2 |
154 | | - buff_reader.move(environment_va) |
155 | | - env_buffer = buff_reader.read(buff_reader.current_segment.end_address - buff_reader.current_position) |
156 | | - |
| 85 | + try: |
| 86 | + self.__parse_peb() |
| 87 | + except Exception as e: |
| 88 | + logging.exception('PEB parsing error!') |
157 | 89 |
|
158 | 90 | def __parse_header(self): |
159 | 91 | self.header = MinidumpHeader.parse(self.file_handle) |
@@ -296,6 +228,13 @@ def __parse_thread_context(self): |
296 | 228 | elif self.sysinfo.ProcessorArchitecture == PROCESSOR_ARCHITECTURE.INTEL: |
297 | 229 | thread.ContextObject = WOW64_CONTEXT.parse(self.file_handle) |
298 | 230 |
|
| 231 | + def __parse_peb(self): |
| 232 | + if not self.sysinfo or not self.threads: |
| 233 | + return |
| 234 | + |
| 235 | + self.peb = PEB.from_minidump(self) |
| 236 | + |
| 237 | + |
299 | 238 |
|
300 | 239 | def __str__(self): |
301 | 240 | t = '== Minidump File ==\n' |
|
0 commit comments