Rizin
unix-like reverse engineering framework and cli tools
mdmp.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2016-2017 Davis
2 // SPDX-FileCopyrightText: 2016-2017 Alex Kornitzer <alex.kornitzer@countercept.com>
3 // SPDX-License-Identifier: LGPL-3.0-only
4 
5 #include <rz_util.h>
6 
7 #include "mdmp.h"
8 // XXX: this is a random number, no idea how long it should be.
9 #define COMMENTS_SIZE 32
10 
12  /* FIXME: Will only resolve exact matches, probably no need to fix as
13  ** this function will become redundant on the optimisation stage */
14  struct minidump_memory_descriptor64 *memory;
15  ut64 index, paddr = 0;
16  RzListIter *it;
17 
18  /* Loop through the memories sections looking for a match */
19  index = obj->streams.memories64.base_rva;
20  rz_list_foreach (obj->streams.memories64.memories, it, memory) {
21  if (vaddr == memory->start_of_memory_range) {
22  paddr = index;
23  break;
24  }
25  index += memory->data_size;
26  }
27  return paddr;
28 }
29 
30 struct minidump_memory_info *rz_bin_mdmp_get_mem_info(struct rz_bin_mdmp_obj *obj, ut64 vaddr) {
31  struct minidump_memory_info *mem_info;
32  RzListIter *it;
33 
34  if (!obj) {
35  return NULL;
36  }
37 
38  rz_list_foreach (obj->streams.memory_infos, it, mem_info) {
39  if (mem_info->allocation_base && vaddr == mem_info->base_address) {
40  return mem_info;
41  }
42  }
43 
44  return NULL;
45 }
46 
48  struct minidump_memory_info *mem_info;
49 
50  if (!(mem_info = rz_bin_mdmp_get_mem_info(obj, vaddr))) {
51  /* if there is no mem info in the dump, assume default permission */
52  return RZ_PERM_R;
53  }
54 
55  /* FIXME: Have I got these mappings right, I am not sure I have!!! */
56 
57  switch (mem_info->protect) {
59  return RZ_PERM_R;
61  return RZ_PERM_RW;
63  return RZ_PERM_X;
65  return RZ_PERM_RX;
67  return RZ_PERM_RWX;
74  default:
75  return 0;
76  }
77 }
78 
79 static void rz_bin_mdmp_free_pe32_bin(void *pe_bin_) {
80  struct Pe32_rz_bin_mdmp_pe_bin *pe_bin = pe_bin_;
81  if (pe_bin) {
82  sdb_free(pe_bin->bin->kv);
83  Pe32_rz_bin_pe_free(pe_bin->bin);
84  RZ_FREE(pe_bin);
85  }
86 }
87 
88 static void rz_bin_mdmp_free_pe64_bin(void *pe_bin_) {
89  struct Pe64_rz_bin_mdmp_pe_bin *pe_bin = pe_bin_;
90  if (pe_bin) {
91  sdb_free(pe_bin->bin->kv);
92  Pe64_rz_bin_pe_free(pe_bin->bin);
93  RZ_FREE(pe_bin);
94  }
95 }
96 
97 void rz_bin_mdmp_free(struct rz_bin_mdmp_obj *obj) {
98  if (!obj) {
99  return;
100  }
101 
112  free(obj->streams.exception);
113  free(obj->streams.system_info);
114  free(obj->streams.comments_a);
115  free(obj->streams.comments_w);
116  free(obj->streams.handle_data);
119 
120  rz_list_free(obj->pe32_bins);
121  rz_list_free(obj->pe64_bins);
122 
123  rz_buf_free(obj->b);
124  free(obj->hdr);
125  obj->b = NULL;
126  free(obj);
127 
128  return;
129 }
130 
131 static void rz_bin_mdmp_init_parsing(struct rz_bin_mdmp_obj *obj) {
132  /* TODO: Handle unions, can we? */
133  /* FIXME: Why are we getting struct missing errors when it finds them */
134  sdb_set(obj->kv, "mdmp_mem_state.cparse",
135  "enum mdmp_mem_state { MEM_COMMIT=0x1000, "
136  "MEM_FREE=0x10000, MEM_RESERVE=0x02000 };",
137  0);
138 
139  sdb_set(obj->kv, "mdmp_mem_type.cparse",
140  "enum mdmp_mem_type { MEM_IMAGE=0x1000000, "
141  "MEM_MAPPED=0x40000, MEM_PRIVATE=0x20000 };",
142  0);
143 
144  sdb_set(obj->kv, "mdmp_page_protect.cparse",
145  "enum mdmp_page_protect { PAGE_NOACCESS=1, "
146  "PAGE_READONLY=2, PAGE_READWRITE=4, PAGE_WRITECOPY=8, "
147  "PAGE_EXECUTE=0x10, PAGE_EXECUTE_READ=0x20, "
148  "PAGE_EXECUTE_READWRITE=0x40, PAGE_EXECUTE_WRITECOPY=0x80, "
149  "PAGE_GUARD=0x100, PAGE_NOCACHE=0x200, "
150  "PAGE_WRITECOMBINE=0x400, PAGE_TARGETS_INVALID=0x40000000 };",
151  0);
152 
153  sdb_set(obj->kv, "mdmp_misc1_flags.cparse",
154  "enum mdmp_misc1_flags { MINIDUMP_MISC1_PROCESS_ID=1, "
155  "MINIDUMP_MISC1_PROCESS_TIMES=2, "
156  "MINIDUMP_MISC1_PROCESSOR_POWER_INFO=4 };",
157  0);
158 
159  sdb_set(obj->kv, "mdmp_processor_architecture.cparse",
160  "enum mdmp_processor_architecture { "
161  "PROCESSOR_ARCHITECTURE_INTEL=0, "
162  "PROCESSOR_ARCHITECTURE_ARM=5, "
163  "PROCESSOR_ARCHITECTURE_IA64=6, "
164  "PROCESSOR_ARCHITECTURE_AMD64=9, "
165  "PROCESSOR_ARCHITECTURE_UNKNOWN=0xffff };",
166  0);
167 
168  sdb_set(obj->kv, "mdmp_product_type.cparse",
169  "enum mdmp_product_type { "
170  "VER_NT_WORKSTATION=1, VER_NT_DOMAIN_CONTROLLER=2, "
171  "VER_NT_SERVER=3 };",
172  0);
173 
174  sdb_set(obj->kv, "mdmp_platform_id.cparse",
175  "enum mdmp_platform_id { "
176  "VER_PLATFORM_WIN32s=0, "
177  "VER_PLATFORM_WIN32_WINDOWS=1, "
178  "VER_PLATFORM_WIN32_NT=2 };",
179  0);
180 
181  sdb_set(obj->kv, "mdmp_suite_mask.cparse",
182  "enum mdmp_suite_mask { "
183  "VER_SUITE_SMALLBUSINESS=1, VER_SUITE_ENTERPRISE=2, "
184  "VER_SUITE_BACKOFFICE=4, VER_SUITE_TERMINAL=0x10, "
185  "VER_SUITE_SMALLBUSINESS_RESTRICTED=0x20, "
186  "VER_SUITE_EMBEDDEDNT=0x40, VER_SUITE_DATACENTER=0x80, "
187  "VER_SUITE_SINGLEUSERTS=0x100, VER_SUITE_PERSONAL=0x200, "
188  "VER_SUITE_BLADE=0x400, VER_SUITE_STORAGE_SERVER=0x2000, "
189  "VER_SUITE_COMPUTE_SERVER=0x4000 };",
190  0);
191 
192  sdb_set(obj->kv, "mdmp_callback_type.cparse",
193  "enum mdmp_callback_type { ModuleCallback=0,"
194  "ThreadCallback=1, ThreadExCallback=2, "
195  "IncludeThreadCallback=3, IncludeModuleCallback=4, "
196  "MemoryCallback=5, CancelCallback=6, "
197  "WriteKernelMinidumpCallback=7, "
198  "KernelMinidumpStatusCallback=8, "
199  "RemoveMemoryCallback=9, "
200  "IncludeVmRegionCallback=10, "
201  "IoStartCallback=11, IoWriteAllCallback=12, "
202  "IoFinishCallback=13, ReadMemoryFailureCallback=14, "
203  "SecondaryFlagsCallback=15 };",
204  0);
205 
206  sdb_set(obj->kv, "mdmp_exception_code.cparse",
207  "enum mdmp_exception_code { "
208  "DBG_CONTROL_C=0x40010005, "
209  "EXCEPTION_GUARD_PAGE_VIOLATION=0x80000001, "
210  "EXCEPTION_DATATYPE_MISALIGNMENT=0x80000002, "
211  "EXCEPTION_BREAKPOINT=0x80000003, "
212  "EXCEPTION_SINGLE_STEP=0x80000004, "
213  "EXCEPTION_ACCESS_VIOLATION=0xc0000005, "
214  "EXCEPTION_IN_PAGE_ERROR=0xc0000006, "
215  "EXCEPTION_INVALID_HANDLE=0xc0000008, "
216  "EXCEPTION_ILLEGAL_INSTRUCTION=0xc000001d, "
217  "EXCEPTION_NONCONTINUABLE_EXCEPTION=0xc0000025, "
218  "EXCEPTION_INVALID_DISPOSITION=0xc0000026, "
219  "EXCEPTION_ARRAY_BOUNDS_EXCEEDED=0xc000008c, "
220  "EXCEPTION_FLOAT_DENORMAL_OPERAND=0xc000008d, "
221  "EXCEPTION_FLOAT_DIVIDE_BY_ZERO=0xc000008e, "
222  "EXCEPTION_FLOAT_INEXACT_RESULT=0xc000008f, "
223  "EXCEPTION_FLOAT_INVALID_OPERATION=0xc0000090, "
224  "EXCEPTION_FLOAT_OVERFLOW=0xc0000091, "
225  "EXCEPTION_FLOAT_STACK_CHECK=0xc0000092, "
226  "EXCEPTION_FLOAT_UNDERFLOW=0xc0000093, "
227  "EXCEPTION_INTEGER_DIVIDE_BY_ZERO=0xc0000094, "
228  "EXCEPTION_INTEGER_OVERFLOW=0xc0000095, "
229  "EXCEPTION_PRIVILEGED_INSTRUCTION=0xc0000096, "
230  "EXCEPTION_STACK_OVERFLOW=0xc00000fd, "
231  "EXCEPTION_POSSIBLE_DEADLOCK=0xc0000194 };",
232  0);
233 
234  sdb_set(obj->kv, "mdmp_exception_flags.cparse",
235  "enum mdmp_exception_flags { "
236  "EXCEPTION_CONTINUABLE=0, "
237  "EXCEPTION_NONCONTINUABLE=1 };",
238  0);
239 
240  sdb_set(obj->kv, "mdmp_handle_object_information_type.cparse",
241  "enum mdmp_handle_object_information_type { "
242  "MiniHandleObjectInformationNone=0, "
243  "MiniThreadInformation1=1, MiniMutantInformation1=2, "
244  "MiniMutantInformation2=3, MiniMutantProcessInformation1=4, "
245  "MiniProcessInformation2=5 };",
246  0);
247 
248  sdb_set(obj->kv, "mdmp_secondary_flags.cparse",
249  "enum mdmp_secondary_flags { "
250  "MiniSecondaryWithoutPowerInfo=0 };",
251  0);
252 
253  sdb_set(obj->kv, "mdmp_stream_type.cparse",
254  "enum mdmp_stream_type { UnusedStream=0, "
255  "ReservedStream0=1, ReservedStream1=2, "
256  "ThreadListStream=3, ModuleListStream=4, "
257  "MemoryListStream=5, ExceptionStream=6, "
258  "SystemInfoStream=7, ThreadExListStream=8, "
259  "Memory64ListStream=9, CommentStreamA=10, "
260  "CommentStreamW=11, HandleDataStream=12, "
261  "FunctionTableStream=13, UnloadedModuleListStream=14, "
262  "MiscInfoStream=15, MemoryInfoListStream=16, "
263  "ThreadInfoListStream=17, "
264  "HandleOperationListStream=18, "
265  "LastReservedStream=0xffff };",
266  0);
267 
268  sdb_set(obj->kv, "mdmp_type.cparse", "enum mdmp_type { "
269  "MiniDumpNormal=0x0, "
270  "MiniDumpWithDataSegs=0x1, "
271  "MiniDumpWithFullMemory=0x2, "
272  "MiniDumpWithHandleData=0x4, "
273  "MiniDumpFilterMemory=0x8, "
274  "MiniDumpScanMemory=0x10, "
275  "MiniDumpWithUnloadedModule=0x20, "
276  "MiniDumpWihinDirectlyReferencedMemory=0x40, "
277  "MiniDumpFilterWithModulePaths=0x80,"
278  "MiniDumpWithProcessThreadData=0x100, "
279  "MiniDumpWithPrivateReadWriteMemory=0x200, "
280  "MiniDumpWithoutOptionalDate=0x400, "
281  "MiniDumpWithFullMemoryInfo=0x800, "
282  "MiniDumpWithThreadInfo=0x1000, "
283  "MiniDumpWithCodeSegs=0x2000, "
284  "MiniDumpWithoutAuxiliaryState=0x4000, "
285  "MiniDumpWithFullAuxiliaryState=0x8000, "
286  "MiniDumpWithPrivateWriteCopyMemory=0x10000, "
287  "MiniDumpIgnoreInaccessibleMemory=0x20000, "
288  "MiniDumpWithTokenInformation=0x40000, "
289  "MiniDumpWithModuleHeaders=0x80000, "
290  "MiniDumpFilterTriage=0x100000, "
291  "MiniDumpValidTypeFlags=0x1fffff };",
292  0);
293 
294  sdb_set(obj->kv, "mdmp_module_write_flags.cparse",
295  "enum mdmp_module_write_flags { "
296  "ModuleWriteModule=0, ModuleWriteDataSeg=2, "
297  "ModuleWriteMiscRecord=4, ModuleWriteCvRecord=8, "
298  "ModuleReferencedByMemory=0x10, ModuleWriteTlsData=0x20, "
299  "ModuleWriteCodeSegs=0x40 };",
300  0);
301 
302  sdb_set(obj->kv, "mdmp_thread_write_flags.cparse",
303  "enum mdmp_thread_write_flags { "
304  "ThreadWriteThread=0, ThreadWriteStack=2, "
305  "ThreadWriteContext=4, ThreadWriteBackingStore=8, "
306  "ThreadWriteInstructionWindow=0x10, "
307  "ThreadWriteThreadData=0x20, "
308  "ThreadWriteThreadInfo=0x40 };",
309  0);
310 
311  sdb_set(obj->kv, "mdmp_context_flags.cparse",
312  "enum mdmp_context_flags { CONTEXT_i386=0x10000, "
313  "CONTEXT_CONTROL=0x10001, CONTEXT_INTEGER=0x10002, "
314  "CONTEXT_SEGMENTS=0x10004, CONTEXT_FLOATING_POINT=0x10008, "
315  "CONTEXT_DEBUG_REGISTERS=0x10010, "
316  "CONTEXT_EXTENDED_REGISTERS=0x10020 };",
317  0);
318 
319  sdb_set(obj->kv, "mdmp_location_descriptor.format",
320  "dd DataSize RVA", 0);
321  sdb_set(obj->kv, "mdmp_location_descriptor64.format",
322  "qq DataSize RVA", 0);
323  sdb_set(obj->kv, "mdmp_memory_descriptor.format", "q? "
324  "StartOfMemoryRange "
325  "(mdmp_location_descriptor)Memory",
326  0);
327  sdb_set(obj->kv, "mdmp_memory_descriptor64.format", "qq "
328  "StartOfMemoryRange DataSize",
329  0);
330 
331 #if 0
332  /* TODO: Flag dependent thus not fully implemented */
333  sdb_set (obj->kv, "mdmp_context.format", "[4]B "
334  "(mdmp_context_flags)ContextFlags", 0);
335 #endif
336 
337  sdb_set(obj->kv, "mdmp_vs_fixedfileinfo.format", "ddddddddddddd "
338  "dwSignature dwStrucVersion dwFileVersionMs "
339  "dwFileVersionLs dwProductVersionMs "
340  "dwProductVersionLs dwFileFlagsMask dwFileFlags "
341  "dwFileOs dwFileType dwFileSubtype dwFileDateMs "
342  "dwFileDateLs",
343  0);
344 
345  sdb_set(obj->kv, "mdmp_string.format", "dZ Length Buffer", 0);
346 }
347 
348 static bool read_hdr(RzBuffer *b, struct minidump_header *hdr) {
350  if (tmp < 0) {
351  return false;
352  }
353 
354  if (rz_buf_seek(b, 0, RZ_BUF_SET) < 0) {
355  return false;
356  }
357 
358  bool result = true;
359 
360  ut32 signature = 0;
361  if (!rz_buf_read_le32(b, &signature)) {
362  result = false;
363  }
364  hdr->signature = signature;
365 
366  ut32 version = 0;
367  if (!rz_buf_read_le32(b, &version)) {
368  result = false;
369  }
370  hdr->version = version;
371 
372  ut32 number_of_streams = 0;
373  if (!rz_buf_read_le32(b, &number_of_streams)) {
374  result = false;
375  }
376  hdr->number_of_streams = number_of_streams;
377 
378  ut32 stream_directory_rva = 0;
379  if (!rz_buf_read_le32(b, &stream_directory_rva)) {
380  result = false;
381  }
382  hdr->stream_directory_rva = stream_directory_rva;
383 
384  ut32 check_sum = 0;
385  if (!rz_buf_read_le32(b, &check_sum)) {
386  result = false;
387  }
388  hdr->check_sum = check_sum;
389 
390  ut32 reserved = 0;
391  if (!rz_buf_read_le32(b, &reserved)) {
392  result = false;
393  }
394  hdr->reserved = reserved;
395 
396  ut64 flags = 0;
397  if (!rz_buf_read_le64(b, &flags)) {
398  result = false;
399  }
400  hdr->flags = flags;
401 
402  if (rz_buf_seek(b, tmp, RZ_BUF_SET) < 0) {
403  return false;
404  }
405 
406  return result;
407 }
408 
409 static bool rz_bin_mdmp_init_hdr(struct rz_bin_mdmp_obj *obj) {
410  obj->hdr = RZ_NEW(struct minidump_header);
411  if (!obj->hdr) {
412  return false;
413  }
414  read_hdr(obj->b, obj->hdr);
415 
416  if (obj->hdr->number_of_streams == 0) {
417  RZ_LOG_WARN("No streams present!\n");
418  return false;
419  }
420 
421  if (obj->hdr->stream_directory_rva < sizeof(struct minidump_header)) {
422  RZ_LOG_ERROR("RVA for directory resides in the header!\n");
423  return false;
424  }
425 
426  if (obj->hdr->check_sum) {
427  RZ_LOG_INFO("Checksum present but needs validating!\n");
428  return false;
429  }
430 
431  sdb_num_set(obj->kv, "mdmp.hdr.time_date_stamp", obj->hdr->time_date_stamp, 0);
432  sdb_num_set(obj->kv, "mdmp.hdr.flags", obj->hdr->flags, 0);
433  sdb_num_set(obj->kv, "mdmp_header.offset", 0, 0);
434  sdb_set(obj->kv, "mdmp_header.format", "[4]zddddt[8]B Signature "
435  "Version NumberOfStreams StreamDirectoryRVA CheckSum "
436  "TimeDateStamp (mdmp_type)Flags",
437  0);
438 
439  return true;
440 }
441 
442 static bool read_module_aux(RzBuffer *b, ut64 addr, struct minidump_module *module) {
443  ut64 base_of_image;
444  if (!rz_buf_read_le64(b, &base_of_image)) {
445  return false;
446  }
447  module->base_of_image = base_of_image;
448 
449  ut32 size_of_image;
450  if (!rz_buf_read_le32(b, &size_of_image)) {
451  return false;
452  }
453  module->size_of_image = size_of_image;
454 
455  ut32 check_sum;
456  if (!rz_buf_read_le32(b, &check_sum)) {
457  return false;
458  }
459  module->check_sum = check_sum;
460 
461  ut32 time_date_stamp;
462  if (!rz_buf_read_le32(b, &time_date_stamp)) {
463  return false;
464  }
465  module->time_date_stamp = time_date_stamp;
466 
467  ut32 module_name_rva;
468  if (!rz_buf_read_le32(b, &module_name_rva)) {
469  return false;
470  }
471  module->module_name_rva = module_name_rva;
472 
473  ut32 dw_signature;
474  if (!rz_buf_read_le32(b, &dw_signature)) {
475  return false;
476  }
477  module->version_info.dw_signature = dw_signature;
478 
479  ut32 dw_struc_version;
480  if (!rz_buf_read_le32(b, &dw_struc_version)) {
481  return false;
482  }
483  module->version_info.dw_struc_version = dw_struc_version;
484 
485  ut32 dw_file_version_ms;
486  if (!rz_buf_read_le32(b, &dw_file_version_ms)) {
487  return false;
488  }
489  module->version_info.dw_file_version_ms = dw_file_version_ms;
490 
491  ut32 dw_file_version_ls;
492  if (!rz_buf_read_le32(b, &dw_file_version_ls)) {
493  return false;
494  }
495  module->version_info.dw_file_version_ls = dw_file_version_ls;
496 
497  ut32 dw_product_version_ms;
498  if (!rz_buf_read_le32(b, &dw_product_version_ms)) {
499  return false;
500  }
501  module->version_info.dw_product_version_ms = dw_product_version_ms;
502 
503  ut32 dw_product_version_ls;
504  if (!rz_buf_read_le32(b, &dw_product_version_ls)) {
505  return false;
506  }
507  module->version_info.dw_product_version_ls = dw_product_version_ls;
508 
509  ut32 dw_file_flags_mask;
510  if (!rz_buf_read_le32(b, &dw_file_flags_mask)) {
511  return false;
512  }
513  module->version_info.dw_file_flags_mask = dw_file_flags_mask;
514 
515  ut32 dw_file_flags;
516  if (!rz_buf_read_le32(b, &dw_file_flags)) {
517  return false;
518  }
519  module->version_info.dw_file_flags = dw_file_flags;
520 
521  ut32 dw_file_os;
522  if (!rz_buf_read_le32(b, &dw_file_os)) {
523  return false;
524  }
525  module->version_info.dw_file_os = dw_file_os;
526 
527  ut32 dw_file_type;
528  if (!rz_buf_read_le32(b, &dw_file_type)) {
529  return false;
530  }
531  module->version_info.dw_file_type = dw_file_type;
532 
533  ut32 dw_file_subtype;
534  if (!rz_buf_read_le32(b, &dw_file_subtype)) {
535  return false;
536  }
537  module->version_info.dw_file_subtype = dw_file_subtype;
538 
539  ut32 dw_file_date_ms;
540  if (!rz_buf_read_le32(b, &dw_file_date_ms)) {
541  return false;
542  }
543  module->version_info.dw_file_date_ms = dw_file_date_ms;
544 
545  ut32 dw_file_date_ls;
546  if (!rz_buf_read_le32(b, &dw_file_date_ls)) {
547  return false;
548  }
549  module->version_info.dw_file_date_ls = dw_file_date_ls;
550 
551  ut32 cv_record_data_size;
552  if (!rz_buf_read_le32(b, &cv_record_data_size)) {
553  return false;
554  }
555  module->cv_record.data_size = cv_record_data_size;
556 
557  ut32 cv_record_rva;
558  if (!rz_buf_read_le32(b, &cv_record_rva)) {
559  return false;
560  }
561  module->cv_record.rva = cv_record_rva;
562 
563  ut32 misc_record_data_size;
564  if (!rz_buf_read_le32(b, &misc_record_data_size)) {
565  return false;
566  }
567  module->misc_record.data_size = misc_record_data_size;
568 
569  ut32 misc_record_rva;
570  if (!rz_buf_read_le32(b, &misc_record_rva)) {
571  return false;
572  }
573  module->misc_record.rva = misc_record_rva;
574 
575  ut64 reserved_0;
576  if (!rz_buf_read_le64(b, &reserved_0)) {
577  return false;
578  }
579  module->reserved_0 = reserved_0;
580 
581  ut64 reserved_1;
582  if (!rz_buf_read_le64(b, &reserved_1)) {
583  return false;
584  }
585  module->reserved_1 = reserved_1;
586 
587  return true;
588 }
589 
590 static bool read_module(RzBuffer *b, ut64 addr, struct minidump_module *module) {
592  if (tmp < 0) {
593  return false;
594  }
595 
596  if (rz_buf_seek(b, addr, RZ_BUF_SET) < 0) {
597  return false;
598  }
599 
600  bool result = read_module_aux(b, addr, module);
601 
602  if (rz_buf_seek(b, tmp, RZ_BUF_SET) < 0) {
603  return false;
604  }
605 
606  return result;
607 }
608 
609 static bool read_memory64_list(RzBuffer *b, ut64 addr, struct minidump_memory64_list *memory64_list) {
611  if (tmp < 0) {
612  return false;
613  }
614 
615  if (rz_buf_seek(b, addr, RZ_BUF_SET) < 0) {
616  return false;
617  }
618 
619  ut64 number_of_memory_ranges;
620  if (!rz_buf_read_le64(b, &number_of_memory_ranges)) {
621  return false;
622  }
623  memory64_list->number_of_memory_ranges = number_of_memory_ranges;
624 
625  ut64 base_rva;
626  if (!rz_buf_read_le64(b, &base_rva)) {
627  return false;
628  }
629  memory64_list->base_rva = base_rva;
630 
631  if (rz_buf_seek(b, tmp, RZ_BUF_SET) < 0) {
632  return false;
633  }
634 
635  return true;
636 }
637 
638 static bool read_desc(RzBuffer *b, ut64 addr, struct minidump_memory_descriptor64 *desc) {
640  if (tmp < 0) {
641  return false;
642  }
643 
644  if (rz_buf_seek(b, addr, RZ_BUF_SET) < 0) {
645  return false;
646  }
647 
648  ut64 start_of_memory_range;
649  if (!rz_buf_read_le64(b, &start_of_memory_range)) {
650  return false;
651  }
652  desc->start_of_memory_range = start_of_memory_range;
653 
654  ut64 data_size;
655  if (!rz_buf_read_le64(b, &data_size)) {
656  return false;
657  }
658  desc->data_size = data_size;
659 
660  if (rz_buf_seek(b, tmp, RZ_BUF_SET) < 0) {
661  return false;
662  }
663 
664  return true;
665 }
666 
667 static bool rz_bin_mdmp_init_directory_entry(struct rz_bin_mdmp_obj *obj, struct minidump_directory *entry) {
668  struct minidump_handle_operation_list handle_operation_list;
669  struct minidump_memory_list memory_list;
670  struct minidump_memory64_list memory64_list;
671  struct minidump_memory_info_list memory_info_list;
672  struct minidump_module_list module_list;
673  struct minidump_thread_list thread_list;
674  struct minidump_thread_ex_list thread_ex_list;
675  struct minidump_thread_info_list thread_info_list;
676  struct minidump_token_info_list token_info_list;
677  struct minidump_unloaded_module_list unloaded_module_list;
678  ut64 offset;
679  int i, r;
680 
681  /* We could confirm data sizes but a malcious MDMP will always get around
682  ** this! But we can ensure that the data is not outside of the file */
683  if ((ut64)entry->location.rva + entry->location.data_size > rz_buf_size(obj->b)) {
684  RZ_LOG_ERROR("Size Mismatch - Stream data is larger than file size!\n");
685  return false;
686  }
687 
688  ut32 number_of_modules;
689 
690  switch (entry->stream_type) {
691  case THREAD_LIST_STREAM:
692  r = rz_buf_read_at(obj->b, entry->location.rva, (ut8 *)&thread_list, sizeof(thread_list));
693  if (r != sizeof(thread_list)) {
694  break;
695  }
696 
697  sdb_set(obj->kv, "mdmp_thread.format", "ddddq?? "
698  "ThreadId SuspendCount PriorityClass Priority "
699  "Teb (mdmp_memory_descriptor)Stack "
700  "(mdmp_location_descriptor)ThreadContext",
701  0);
702  sdb_num_set(obj->kv, "mdmp_thread_list.offset",
703  entry->location.rva, 0);
704  sdb_set(obj->kv, "mdmp_thread_list.format",
705  sdb_fmt("d[%d]? "
706  "NumberOfThreads (mdmp_thread)Threads",
707  thread_list.number_of_threads),
708  0);
709 
710  /* TODO: Not yet fully parsed or utilised */
711  break;
712  case MODULE_LIST_STREAM:
713  if (!rz_buf_read_le32_at(obj->b, entry->location.rva, &number_of_modules)) {
714  break;
715  }
716  module_list.number_of_modules = number_of_modules;
717 
718  sdb_set(obj->kv, "mdmp_module.format", "qddtd???qq "
719  "BaseOfImage SizeOfImage CheckSum "
720  "TimeDateStamp ModuleNameRVA "
721  "(mdmp_vs_fixedfileinfo)VersionInfo "
722  "(mdmp_location_descriptor)CvRecord "
723  "(mdmp_location_descriptor)MiscRecord "
724  "Reserved0 Reserved1",
725  0);
726  sdb_num_set(obj->kv, "mdmp_module_list.offset",
727  entry->location.rva, 0);
728  sdb_set(obj->kv, "mdmp_module_list.format",
729  sdb_fmt("d[%d]? "
730  "NumberOfModule (mdmp_module)Modules",
731  module_list.number_of_modules),
732  0);
733 
734  offset = entry->location.rva + sizeof(module_list);
735  for (i = 0; i < module_list.number_of_modules; i++) {
736  struct minidump_module *module = RZ_NEW(struct minidump_module);
737  if (!module) {
738  break;
739  }
740  if (!read_module(obj->b, offset, module)) {
741  break;
742  }
744  offset += sizeof(*module);
745  }
746  break;
747  case MEMORY_LIST_STREAM:
748  r = rz_buf_read_at(obj->b, entry->location.rva, (ut8 *)&memory_list, sizeof(memory_list));
749  if (r != sizeof(memory_list)) {
750  break;
751  }
752 
753  sdb_num_set(obj->kv, "mdmp_memory_list.offset",
754  entry->location.rva, 0);
755  sdb_set(obj->kv, "mdmp_memory_list.format",
756  sdb_fmt("d[%d]? "
757  "NumberOfMemoryRanges "
758  "(mdmp_memory_descriptor)MemoryRanges ",
759  memory_list.number_of_memory_ranges),
760  0);
761 
762  offset = entry->location.rva + sizeof(memory_list);
763  for (i = 0; i < memory_list.number_of_memory_ranges; i++) {
764  struct minidump_memory_descriptor *desc = RZ_NEW(struct minidump_memory_descriptor);
765  if (!desc) {
766  break;
767  }
768  r = rz_buf_read_at(obj->b, offset, (ut8 *)desc, sizeof(*desc));
769  if (r != sizeof(*desc)) {
770  break;
771  }
773  offset += sizeof(*desc);
774  }
775  break;
776  case EXCEPTION_STREAM:
777  /* TODO: Not yet fully parsed or utilised */
778  obj->streams.exception = RZ_NEW(struct minidump_exception_stream);
779  if (!obj->streams.exception) {
780  break;
781  }
782 
783  r = rz_buf_read_at(obj->b, entry->location.rva, (ut8 *)obj->streams.exception, sizeof(*obj->streams.exception));
784  if (r != sizeof(*obj->streams.exception)) {
785  break;
786  }
787 
788  sdb_set(obj->kv, "mdmp_exception.format", "[4]E[4]Eqqdd[15]q "
789  "(mdmp_exception_code)ExceptionCode "
790  "(mdmp_exception_flags)ExceptionFlags "
791  "ExceptionRecord ExceptionAddress "
792  "NumberParameters __UnusedAlignment "
793  "ExceptionInformation",
794  0);
795  sdb_num_set(obj->kv, "mdmp_exception_stream.offset",
796  entry->location.rva, 0);
797  sdb_set(obj->kv, "mdmp_exception_stream.format", "dd?? "
798  "ThreadId __Alignment "
799  "(mdmp_exception)ExceptionRecord "
800  "(mdmp_location_descriptor)ThreadContext",
801  0);
802 
803  break;
804  case SYSTEM_INFO_STREAM:
805  obj->streams.system_info = RZ_NEW(struct minidump_system_info);
806  if (!obj->streams.system_info) {
807  break;
808  }
809  r = rz_buf_read_at(obj->b, entry->location.rva, (ut8 *)obj->streams.system_info, sizeof(*obj->streams.system_info));
810  if (r != sizeof(*obj->streams.system_info)) {
811  break;
812  }
813 
814  sdb_num_set(obj->kv, "mdmp_system_info.offset",
815  entry->location.rva, 0);
816  /* TODO: We need E as a byte! */
817  sdb_set(obj->kv, "mdmp_system_info.format", "[2]EwwbBddd[4]Ed[2]Ew[2]q "
818  "(mdmp_processor_architecture)ProcessorArchitecture "
819  "ProcessorLevel ProcessorRevision NumberOfProcessors "
820  "(mdmp_product_type)ProductType "
821  "MajorVersion MinorVersion BuildNumber (mdmp_platform_id)PlatformId "
822  "CsdVersionRva (mdmp_suite_mask)SuiteMask Reserved2 ProcessorFeatures",
823  0);
824 
825  break;
827  /* TODO: Not yet fully parsed or utilised */
828  r = rz_buf_read_at(obj->b, entry->location.rva, (ut8 *)&thread_ex_list, sizeof(thread_ex_list));
829  if (r != sizeof(thread_ex_list)) {
830  break;
831  }
832 
833  sdb_set(obj->kv, "mdmp_thread_ex.format", "ddddq??? "
834  "ThreadId SuspendCount PriorityClass Priority "
835  "Teb (mdmp_memory_descriptor)Stack "
836  "(mdmp_location_descriptor)ThreadContext "
837  "(mdmp_memory_descriptor)BackingStore",
838  0);
839  sdb_num_set(obj->kv, "mdmp_thread_ex_list.offset",
840  entry->location.rva, 0);
841  sdb_set(obj->kv, "mdmp_thread_ex_list.format",
842  sdb_fmt("d[%d]? NumberOfThreads "
843  "(mdmp_thread_ex)Threads",
844  thread_ex_list.number_of_threads),
845  0);
846 
847  offset = entry->location.rva + sizeof(thread_ex_list);
848  for (i = 0; i < thread_ex_list.number_of_threads; i++) {
849  struct minidump_thread_ex *thread = RZ_NEW(struct minidump_thread_ex);
850  if (!thread) {
851  break;
852  }
853  r = rz_buf_read_at(obj->b, offset, (ut8 *)thread, sizeof(*thread));
854  if (r != sizeof(*thread)) {
855  break;
856  }
857  rz_list_append(obj->streams.ex_threads, thread);
858  offset += sizeof(*thread);
859  }
860  break;
862  if (!read_memory64_list(obj->b, entry->location.rva, &memory64_list)) {
863  break;
864  }
865 
866  sdb_num_set(obj->kv, "mdmp_memory64_list.offset",
867  entry->location.rva, 0);
868  sdb_set(obj->kv, "mdmp_memory64_list.format",
869  sdb_fmt("qq[%" PFMT64d "]? NumberOfMemoryRanges "
870  "BaseRva "
871  "(mdmp_memory_descriptor64)MemoryRanges",
872  memory64_list.number_of_memory_ranges),
873  0);
874 
875  obj->streams.memories64.base_rva = memory64_list.base_rva;
876  offset = entry->location.rva + sizeof(memory64_list);
877  for (i = 0; i < memory64_list.number_of_memory_ranges; i++) {
878  struct minidump_memory_descriptor64 *desc = RZ_NEW(struct minidump_memory_descriptor64);
879  if (!desc) {
880  break;
881  }
882  read_desc(obj->b, offset, desc);
884  offset += sizeof(*desc);
885  }
886  break;
887  case COMMENT_STREAM_A:
888  /* TODO: Not yet fully parsed or utilised */
890  if (!obj->streams.comments_a) {
891  break;
892  }
893  r = rz_buf_read_at(obj->b, entry->location.rva, obj->streams.comments_a, COMMENTS_SIZE);
894  if (r != COMMENTS_SIZE) {
895  break;
896  }
897 
898  sdb_num_set(obj->kv, "mdmp_comment_stream_a.offset",
899  entry->location.rva, 0);
900  sdb_set(obj->kv, "mdmp_comment_stream_a.format",
901  "s CommentA", 0);
902 
903  break;
904  case COMMENT_STREAM_W:
905  /* TODO: Not yet fully parsed or utilised */
907  if (!obj->streams.comments_w) {
908  break;
909  }
910  r = rz_buf_read_at(obj->b, entry->location.rva, obj->streams.comments_w, COMMENTS_SIZE);
911  if (r != COMMENTS_SIZE) {
912  break;
913  }
914 
915  sdb_num_set(obj->kv, "mdmp_comment_stream_w.offset",
916  entry->location.rva, 0);
917  sdb_set(obj->kv, "mdmp_comment_stream_w.format",
918  "s CommentW", 0);
919 
920  break;
921  case HANDLE_DATA_STREAM:
922  /* TODO: Not yet fully parsed or utilised */
923  obj->streams.handle_data = RZ_NEW(struct minidump_handle_data_stream);
924  if (!obj->streams.handle_data) {
925  break;
926  }
927  r = rz_buf_read_at(obj->b, entry->location.rva, (ut8 *)obj->streams.handle_data, sizeof(*obj->streams.handle_data));
928  if (r != sizeof(*obj->streams.handle_data)) {
929  break;
930  }
931 
932  sdb_num_set(obj->kv, "mdmp_handle_data_stream.offset",
933  entry->location.rva, 0);
934  sdb_set(obj->kv, "mdmp_handle_data_stream.format", "dddd "
935  "SizeOfHeader SizeOfDescriptor "
936  "NumberOfDescriptors Reserved",
937  0);
938  break;
940  /* TODO: Not yet fully parsed or utilised */
941  obj->streams.function_table = RZ_NEW(struct minidump_function_table_stream);
942  if (!obj->streams.function_table) {
943  break;
944  }
945  r = rz_buf_read_at(obj->b, entry->location.rva, (ut8 *)obj->streams.function_table, sizeof(*obj->streams.function_table));
946  if (r != sizeof(*obj->streams.function_table)) {
947  break;
948  }
949 
950  sdb_num_set(obj->kv, "mdmp_function_table_stream.offset",
951  entry->location.rva, 0);
952  sdb_set(obj->kv, "mdmp_function_table_stream.format", "dddddd "
953  "SizeOfHeader SizeOfDescriptor SizeOfNativeDescriptor "
954  "SizeOfFunctionEntry NumberOfDescriptors SizeOfAlignPad",
955  0);
956  break;
958  /* TODO: Not yet fully parsed or utilised */
959  r = rz_buf_read_at(obj->b, entry->location.rva, (ut8 *)&unloaded_module_list, sizeof(unloaded_module_list));
960  if (r != sizeof(unloaded_module_list)) {
961  break;
962  }
963 
964  sdb_set(obj->kv, "mdmp_unloaded_module.format", "qddtd "
965  "BaseOfImage SizeOfImage CheckSum TimeDateStamp "
966  "ModuleNameRva",
967  0);
968  sdb_num_set(obj->kv, "mdmp_unloaded_module_list.offset",
969  entry->location.rva, 0);
970  sdb_set(obj->kv, "mdmp_unloaded_module_list.format", "ddd "
971  "SizeOfHeader SizeOfEntry NumberOfEntries",
972  0);
973 
974  offset = entry->location.rva + sizeof(unloaded_module_list);
975  for (i = 0; i < unloaded_module_list.number_of_entries; i++) {
976  struct minidump_unloaded_module *module = RZ_NEW(struct minidump_unloaded_module);
977  if (!module) {
978  break;
979  }
980  r = rz_buf_read_at(obj->b, offset, (ut8 *)module, sizeof(*module));
981  if (r != sizeof(*module)) {
982  break;
983  }
985  offset += sizeof(*module);
986  }
987  break;
988  case MISC_INFO_STREAM:
989  /* TODO: Not yet fully parsed or utilised */
990  obj->streams.misc_info.misc_info_1 = RZ_NEW(struct minidump_misc_info);
991  if (!obj->streams.misc_info.misc_info_1) {
992  break;
993  }
994  r = rz_buf_read_at(obj->b, entry->location.rva, (ut8 *)obj->streams.misc_info.misc_info_1, sizeof(*obj->streams.misc_info.misc_info_1));
995  if (r != sizeof(*obj->streams.misc_info.misc_info_1)) {
996  break;
997  }
998 
999  /* TODO: Handle different sizes */
1000  sdb_num_set(obj->kv, "mdmp_misc_info.offset",
1001  entry->location.rva, 0);
1002  sdb_set(obj->kv, "mdmp_misc_info.format", "d[4]Bdtttddddd "
1003  "SizeOfInfo (mdmp_misc1_flags)Flags1 ProcessId "
1004  "ProcessCreateTime ProcessUserTime ProcessKernelTime "
1005  "ProcessorMaxMhz ProcessorCurrentMhz "
1006  "ProcessorMhzLimit ProcessorMaxIdleState "
1007  "ProcessorCurrentIdleState",
1008  0);
1009 
1010  break;
1012  r = rz_buf_read_at(obj->b, entry->location.rva, (ut8 *)&memory_info_list, sizeof(memory_info_list));
1013  if (r != sizeof(memory_info_list)) {
1014  break;
1015  }
1016 
1017  sdb_set(obj->kv, "mdmp_memory_info.format",
1018  "qq[4]Edq[4]E[4]E[4]Ed BaseAddress AllocationBase "
1019  "(mdmp_page_protect)AllocationProtect __Alignment1 RegionSize "
1020  "(mdmp_mem_state)State (mdmp_page_protect)Protect "
1021  "(mdmp_mem_type)Type __Alignment2",
1022  0);
1023  sdb_num_set(obj->kv, "mdmp_memory_info_list.offset",
1024  entry->location.rva, 0);
1025  sdb_set(obj->kv, "mdmp_memory_info_list.format",
1026  sdb_fmt("ddq[%" PFMT64d "]? SizeOfHeader SizeOfEntry "
1027  "NumberOfEntries (mdmp_memory_info)MemoryInfo",
1028  memory_info_list.number_of_entries),
1029  0);
1030 
1031  offset = entry->location.rva + sizeof(memory_info_list);
1032  for (i = 0; i < memory_info_list.number_of_entries; i++) {
1033  struct minidump_memory_info *info = RZ_NEW(struct minidump_memory_info);
1034  if (!info) {
1035  break;
1036  }
1037  r = rz_buf_read_at(obj->b, offset, (ut8 *)info, sizeof(*info));
1038  if (r != sizeof(*info)) {
1039  break;
1040  }
1042  offset += sizeof(*info);
1043  }
1044  break;
1046  /* TODO: Not yet fully parsed or utilised */
1047  r = rz_buf_read_at(obj->b, entry->location.rva, (ut8 *)&thread_info_list, sizeof(thread_info_list));
1048  if (r != sizeof(thread_info_list)) {
1049  break;
1050  }
1051 
1052  sdb_set(obj->kv, "mdmp_thread_info.format", "ddddttttqq "
1053  "ThreadId DumpFlags DumpError ExitStatus CreateTime "
1054  "ExitTime KernelTime UserTime StartAddress Affinity",
1055  0);
1056  sdb_num_set(obj->kv, "mdmp_thread_info_list.offset",
1057  entry->location.rva, 0);
1058  sdb_set(obj->kv, "mdmp_thread_info_list.format", "ddd "
1059  "SizeOfHeader SizeOfEntry NumberOfEntries",
1060  0);
1061 
1062  offset = entry->location.rva + sizeof(thread_info_list);
1063  for (i = 0; i < thread_info_list.number_of_entries; i++) {
1064  struct minidump_thread_info *info = RZ_NEW(struct minidump_thread_info);
1065  if (!info) {
1066  break;
1067  }
1068  r = rz_buf_read_at(obj->b, offset, (ut8 *)info, sizeof(*info));
1069  if (r != sizeof(*info)) {
1070  break;
1071  }
1073  offset += sizeof(*info);
1074  }
1075  break;
1077  /* TODO: Not yet fully parsed or utilised */
1078  r = rz_buf_read_at(obj->b, entry->location.rva, (ut8 *)&handle_operation_list, sizeof(handle_operation_list));
1079  if (r != sizeof(handle_operation_list)) {
1080  break;
1081  }
1082 
1083  sdb_num_set(obj->kv, "mdmp_handle_operation_list.offset",
1084  entry->location.rva, 0);
1085  sdb_set(obj->kv, "mdmp_handle_operation_list.format", "dddd "
1086  "SizeOfHeader SizeOfEntry NumberOfEntries Reserved",
1087  0);
1088 
1089  offset = entry->location.rva + sizeof(handle_operation_list);
1090  for (i = 0; i < handle_operation_list.number_of_entries; i++) {
1091  struct avrf_handle_operation *op = RZ_NEW(struct avrf_handle_operation);
1092  if (!op) {
1093  break;
1094  }
1095  r = rz_buf_read_at(obj->b, offset, (ut8 *)op, sizeof(*op));
1096  if (r != sizeof(*op)) {
1097  break;
1098  }
1100  offset += sizeof(*op);
1101  }
1102 
1103  break;
1104  case TOKEN_STREAM:
1105  /* TODO: Not fully parsed or utilised */
1106  r = rz_buf_read_at(obj->b, entry->location.rva, (ut8 *)&token_info_list, sizeof(token_info_list));
1107  if (r != sizeof(token_info_list)) {
1108  break;
1109  }
1110 
1111  sdb_set(obj->kv, "mdmp_token_info.format", "ddq "
1112  "TokenSize TokenId TokenHandle",
1113  0);
1114 
1115  sdb_num_set(obj->kv, "mdmp_token_info_list.offset",
1116  entry->location.rva, 0);
1117  sdb_set(obj->kv, "mdmp_token_info_list.format", "dddd "
1118  "TokenListSize TokenListEntries ListHeaderSize ElementHeaderSize",
1119  0);
1120 
1121  offset = entry->location.rva + sizeof(token_info_list);
1122  for (i = 0; i < token_info_list.number_of_entries; i++) {
1123  struct minidump_token_info *info = RZ_NEW(struct minidump_token_info);
1124  if (!info) {
1125  break;
1126  }
1127  r = rz_buf_read_at(obj->b, offset, (ut8 *)info, sizeof(*info));
1128  if (r != sizeof(*info)) {
1129  break;
1130  }
1132  offset += sizeof(*info);
1133  }
1134  break;
1135 
1136  case LAST_RESERVED_STREAM:
1137  /* TODO: Not yet fully parsed or utilised */
1138  break;
1139  case UNUSED_STREAM:
1140  case RESERVED_STREAM_0:
1141  case RESERVED_STREAM_1:
1142  /* Silently ignore reserved streams */
1143  break;
1144  default:
1145  RZ_LOG_WARN("Invalid or unsupported enumeration encountered %d\n", entry->stream_type);
1146  break;
1147  }
1148  return true;
1149 }
1150 
1151 static bool read_entry(RzBuffer *b, ut64 addr, struct minidump_directory *entry) {
1152  st64 tmp = rz_buf_seek(b, 0, RZ_BUF_CUR);
1153  if (tmp < 0) {
1154  return false;
1155  }
1156 
1157  if (rz_buf_seek(b, addr, RZ_BUF_SET) < 0) {
1158  return false;
1159  }
1160 
1161  ut32 stream_type;
1162  if (!rz_buf_read_le32(b, &stream_type)) {
1163  return false;
1164  }
1165  entry->stream_type = stream_type;
1166 
1167  ut32 data_size;
1168  if (!rz_buf_read_le32(b, &data_size)) {
1169  return false;
1170  }
1171  entry->location.data_size = data_size;
1172 
1173  ut32 rva;
1174  if (!rz_buf_read_le32(b, &rva)) {
1175  return false;
1176  }
1177  entry->location.rva = rva;
1178 
1179  if (rz_buf_seek(b, tmp, RZ_BUF_SET) < 0) {
1180  return false;
1181  }
1182 
1183  return true;
1184 }
1185 
1187  ut32 i;
1188  struct minidump_directory entry;
1189 
1190  sdb_num_set(obj->kv, "mdmp_directory.offset",
1191  obj->hdr->stream_directory_rva, 0);
1192  sdb_set(obj->kv, "mdmp_directory.format", "[4]E? "
1193  "(mdmp_stream_type)StreamType "
1194  "(mdmp_location_descriptor)Location",
1195  0);
1196 
1197  ut64 rvadir = obj->hdr->stream_directory_rva;
1198  ut64 bytes_left = rvadir < obj->size ? obj->size - rvadir : 0;
1199  size_t max_entries = RZ_MIN(obj->hdr->number_of_streams, bytes_left / sizeof(struct minidump_directory));
1200  if (max_entries < obj->hdr->number_of_streams) {
1201  RZ_LOG_ERROR("Number of streams = %u is greater than is supportable by bin size\n",
1202  obj->hdr->number_of_streams);
1203  }
1204  /* Parse each entry in the directory */
1205  for (i = 0; i < max_entries; i++) {
1206  ut32 delta = i * sizeof(struct minidump_directory);
1207  if (read_entry(obj->b, rvadir + delta, &entry)) {
1209  return false;
1210  }
1211  }
1212  }
1213 
1214  return true;
1215 }
1216 
1218  int i;
1219  Pe64_image_dos_header dos_hdr;
1220  Pe64_image_nt_headers nt_hdr;
1221 
1222  if (!Pe64_read_dos_header(pe_buf, &dos_hdr)) {
1223  return false;
1224  }
1225  if (!Pe64_read_nt_headers(pe_buf, dos_hdr.e_lfanew, &nt_hdr)) {
1226  return false;
1227  }
1228 
1229  /* Patch RawData in headers */
1230  ut64 sect_hdrs_off = dos_hdr.e_lfanew + 4 + sizeof(Pe64_image_file_header) + nt_hdr.file_header.SizeOfOptionalHeader;
1231  Pe64_image_section_header section_hdr;
1232  for (i = 0; i < nt_hdr.file_header.NumberOfSections; i++) {
1233  Pe64_read_image_section_header(pe_buf, sect_hdrs_off + i * sizeof(section_hdr), &section_hdr);
1234  section_hdr.PointerToRawData = section_hdr.VirtualAddress;
1235  Pe64_write_image_section_header(pe_buf, sect_hdrs_off + i * sizeof(section_hdr), &section_hdr);
1236  }
1237 
1238  return true;
1239 }
1240 
1242  unsigned int idx;
1243  if (!buf || length <= 0x3d) {
1244  return false;
1245  }
1246 
1247  ut8 tmp1;
1248  if (!rz_buf_read8_at(buf, 0x3c, &tmp1)) {
1249  return false;
1250  }
1251 
1252  ut8 tmp2;
1253  if (!rz_buf_read8_at(buf, 0x3d, &tmp2)) {
1254  return false;
1255  }
1256 
1257  idx = tmp1 | (tmp2 << 8);
1258 
1259  if (length > idx + 0x18 + 2) {
1260  ut8 tmp1[2], tmp2[2], tmp3[2];
1261  rz_buf_read_at(buf, 0, tmp1, 2);
1262  rz_buf_read_at(buf, idx, tmp2, 2);
1263  rz_buf_read_at(buf, idx + 0x18, tmp3, 2);
1264  if (!memcmp(tmp1, "MZ", 2) && !memcmp(tmp2, "PE", 2) && !memcmp(tmp3, "\x0b\x01", 2)) {
1265  return true;
1266  }
1267  }
1268 
1269  return false;
1270 }
1271 
1273  int idx, ret = false;
1274  if (!buf || length <= 0x3d) {
1275  return false;
1276  }
1277 
1278  ut8 tmp1;
1279  if (!rz_buf_read8_at(buf, 0x3c, &tmp1)) {
1280  return false;
1281  }
1282 
1283  ut8 tmp2;
1284  if (!rz_buf_read8_at(buf, 0x3d, &tmp2)) {
1285  return false;
1286  }
1287 
1288  idx = tmp1 | (tmp2 << 8);
1289 
1290  if (length >= idx + 0x20) {
1291  ut8 tmp1[2], tmp2[2], tmp3[2];
1292  rz_buf_read_at(buf, 0, tmp1, 2);
1293  rz_buf_read_at(buf, idx, tmp2, 2);
1294  rz_buf_read_at(buf, idx + 0x18, tmp3, 2);
1295  if (!memcmp(tmp1, "MZ", 2) && !memcmp(tmp2, "PE", 2) && !memcmp(tmp3, "\x0b\x02", 2)) {
1296  ret = true;
1297  }
1298  }
1299  return ret;
1300 }
1301 
1302 static bool rz_bin_mdmp_init_pe_bins(struct rz_bin_mdmp_obj *obj) {
1303  bool dup;
1304  ut64 paddr;
1305  struct minidump_module *module;
1306  struct Pe32_rz_bin_mdmp_pe_bin *pe32_bin, *pe32_dup;
1307  struct Pe64_rz_bin_mdmp_pe_bin *pe64_bin, *pe64_dup;
1308  RzBuffer *buf;
1309  RzListIter *it, *it_dup;
1310 
1311  rz_list_foreach (obj->streams.modules, it, module) {
1312  /* Duplicate modules can appear in the MDMP module list,
1313  ** filtering them out seems to be the correct behaviour */
1314  if (!(paddr = rz_bin_mdmp_get_paddr(obj, module->base_of_image))) {
1315  continue;
1316  }
1317  ut8 *b = RZ_NEWS(ut8, module->size_of_image);
1318  if (!b) {
1319  continue;
1320  }
1321  int r = rz_buf_read_at(obj->b, paddr, b, module->size_of_image);
1323  dup = false;
1324  if (check_pe32_buf(buf, module->size_of_image)) {
1325  rz_list_foreach (obj->pe32_bins, it_dup, pe32_dup) {
1326  if (pe32_dup->vaddr == module->base_of_image) {
1327  dup = true;
1328  continue;
1329  }
1330  }
1331  if (dup) {
1332  continue;
1333  }
1334  if (!(pe32_bin = RZ_NEW0(struct Pe32_rz_bin_mdmp_pe_bin))) {
1335  continue;
1336  }
1338  pe32_bin->vaddr = module->base_of_image;
1339  pe32_bin->paddr = paddr;
1340  pe32_bin->bin = Pe32_rz_bin_pe_new_buf(buf, 0);
1341 
1342  rz_list_append(obj->pe32_bins, pe32_bin);
1343  } else if (check_pe64_buf(buf, module->size_of_image)) {
1344  rz_list_foreach (obj->pe64_bins, it_dup, pe64_dup) {
1345  if (pe64_dup->vaddr == module->base_of_image) {
1346  dup = true;
1347  continue;
1348  }
1349  }
1350  if (dup) {
1351  continue;
1352  }
1353  if (!(pe64_bin = RZ_NEW0(struct Pe64_rz_bin_mdmp_pe_bin))) {
1354  continue;
1355  }
1357  pe64_bin->vaddr = module->base_of_image;
1358  pe64_bin->paddr = paddr;
1359  pe64_bin->bin = Pe64_rz_bin_pe_new_buf(buf, 0);
1360 
1361  rz_list_append(obj->pe64_bins, pe64_bin);
1362  }
1363  rz_buf_free(buf);
1364  }
1365  return true;
1366 }
1367 
1368 static int rz_bin_mdmp_init(struct rz_bin_mdmp_obj *obj) {
1370 
1371  if (!rz_bin_mdmp_init_hdr(obj)) {
1372  RZ_LOG_ERROR("Failed to initialise header\n");
1373  return false;
1374  }
1375 
1376  if (!rz_bin_mdmp_init_directory(obj)) {
1377  RZ_LOG_ERROR("Failed to initialise directory structures!\n");
1378  return false;
1379  }
1380 
1381  if (!rz_bin_mdmp_init_pe_bins(obj)) {
1382  RZ_LOG_ERROR("Failed to initialise pe binaries!\n");
1383  return false;
1384  }
1385 
1386  return true;
1387 }
1388 
1390  bool fail = false;
1391  struct rz_bin_mdmp_obj *obj = RZ_NEW0(struct rz_bin_mdmp_obj);
1392  if (!obj) {
1393  return NULL;
1394  }
1395  obj->kv = sdb_new0();
1396  obj->size = (ut32)rz_buf_size(buf);
1397 
1398  fail |= (!(obj->streams.ex_threads = rz_list_new()));
1399  fail |= (!(obj->streams.memories = rz_list_newf((RzListFree)free)));
1400  fail |= (!(obj->streams.memories64.memories = rz_list_new()));
1402  fail |= (!(obj->streams.modules = rz_list_newf((RzListFree)free)));
1406  fail |= (!(obj->streams.threads = rz_list_new()));
1408 
1411 
1412  if (fail) {
1413  rz_bin_mdmp_free(obj);
1414  return NULL;
1415  }
1416 
1417  obj->b = rz_buf_ref(buf);
1418  if (!rz_bin_mdmp_init(obj)) {
1419  rz_bin_mdmp_free(obj);
1420  return NULL;
1421  }
1422 
1423  return obj;
1424 }
static char * version
Definition: acr.h:4
lzma_index ** i
Definition: index.h:629
RzBinInfo * info(RzBinFile *bf)
Definition: bin_ne.c:86
static char * signature(RzBinFile *bf, bool json)
Definition: bin_pe.c:117
const char * desc
Definition: bin_vsf.c:19
static ut64 rva(RzBinObject *o, ut64 paddr, ut64 vaddr, int va)
Definition: cbin.c:77
#define NULL
Definition: cris-opc.c:27
#define r
Definition: crypto_rc6.c:12
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void static offset struct stat static buf void long static basep static whence static length const void static len static semflg const void static shmflg const struct timespec struct timespec static rem const char static group const void length
Definition: sflib.h:133
uint32_t ut32
RZ_API char * sdb_fmt(const char *fmt,...)
Definition: fmt.c:26
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
voidpf uLong offset
Definition: ioapi.h:144
voidpf void * buf
Definition: ioapi.h:138
uint8_t ut8
Definition: lh5801.h:11
RZ_API RZ_OWN RzList * rz_list_newf(RzListFree f)
Returns a new initialized RzList pointer and sets the free method.
Definition: list.c:248
RZ_API RZ_OWN RzList * rz_list_new(void)
Returns a new initialized RzList pointer (free method is not initialized)
Definition: list.c:235
RZ_API RZ_BORROW RzListIter * rz_list_append(RZ_NONNULL RzList *list, void *data)
Appends at the end of the list a new element.
Definition: list.c:288
RZ_API void rz_list_free(RZ_NONNULL RzList *list)
Empties the list and frees the list pointer.
Definition: list.c:137
static static fork const void static count static fd const char const char static newpath char char char static envp time_t static t const char static mode static whence const char static dir time_t static t unsigned static seconds const char struct utimbuf static buf static inc static sig const char static mode dup
Definition: sflib.h:68
@ reserved
Definition: lm32_isa.h:94
static int rz_bin_mdmp_init(struct rz_bin_mdmp_obj *obj)
Definition: mdmp.c:1368
static bool read_memory64_list(RzBuffer *b, ut64 addr, struct minidump_memory64_list *memory64_list)
Definition: mdmp.c:609
static bool rz_bin_mdmp_init_hdr(struct rz_bin_mdmp_obj *obj)
Definition: mdmp.c:409
static int check_pe64_buf(RzBuffer *buf, ut64 length)
Definition: mdmp.c:1272
static void rz_bin_mdmp_free_pe64_bin(void *pe_bin_)
Definition: mdmp.c:88
#define COMMENTS_SIZE
Definition: mdmp.c:9
static bool rz_bin_mdmp_patch_pe_headers(RzBuffer *pe_buf)
Definition: mdmp.c:1217
void rz_bin_mdmp_free(struct rz_bin_mdmp_obj *obj)
Definition: mdmp.c:97
static void rz_bin_mdmp_free_pe32_bin(void *pe_bin_)
Definition: mdmp.c:79
static bool read_entry(RzBuffer *b, ut64 addr, struct minidump_directory *entry)
Definition: mdmp.c:1151
static void rz_bin_mdmp_init_parsing(struct rz_bin_mdmp_obj *obj)
Definition: mdmp.c:131
static int check_pe32_buf(RzBuffer *buf, ut64 length)
Definition: mdmp.c:1241
ut64 rz_bin_mdmp_get_paddr(struct rz_bin_mdmp_obj *obj, ut64 vaddr)
Definition: mdmp.c:11
static bool rz_bin_mdmp_init_directory(struct rz_bin_mdmp_obj *obj)
Definition: mdmp.c:1186
static bool rz_bin_mdmp_init_directory_entry(struct rz_bin_mdmp_obj *obj, struct minidump_directory *entry)
Definition: mdmp.c:667
static bool read_hdr(RzBuffer *b, struct minidump_header *hdr)
Definition: mdmp.c:348
struct rz_bin_mdmp_obj * rz_bin_mdmp_new_buf(RzBuffer *buf)
Definition: mdmp.c:1389
static bool read_desc(RzBuffer *b, ut64 addr, struct minidump_memory_descriptor64 *desc)
Definition: mdmp.c:638
static bool read_module_aux(RzBuffer *b, ut64 addr, struct minidump_module *module)
Definition: mdmp.c:442
ut32 rz_bin_mdmp_get_perm(struct rz_bin_mdmp_obj *obj, ut64 vaddr)
Definition: mdmp.c:47
struct minidump_memory_info * rz_bin_mdmp_get_mem_info(struct rz_bin_mdmp_obj *obj, ut64 vaddr)
Definition: mdmp.c:30
static bool rz_bin_mdmp_init_pe_bins(struct rz_bin_mdmp_obj *obj)
Definition: mdmp.c:1302
static bool read_module(RzBuffer *b, ut64 addr, struct minidump_module *module)
Definition: mdmp.c:590
#define MINIDUMP_PAGE_EXECUTE_WRITECOPY
Definition: mdmp_specs.h:58
#define MINIDUMP_PAGE_NOACCESS
Definition: mdmp_specs.h:51
#define MINIDUMP_PAGE_WRITECOMBINE
Definition: mdmp_specs.h:61
@ UNLOADED_MODULE_LIST_STREAM
Definition: mdmp_specs.h:130
@ COMMENT_STREAM_A
Definition: mdmp_specs.h:126
@ UNUSED_STREAM
Definition: mdmp_specs.h:116
@ FUNCTION_TABLE_STREAM
Definition: mdmp_specs.h:129
@ LAST_RESERVED_STREAM
Definition: mdmp_specs.h:141
@ EXCEPTION_STREAM
Definition: mdmp_specs.h:122
@ TOKEN_STREAM
Definition: mdmp_specs.h:135
@ THREAD_INFO_LIST_STREAM
Definition: mdmp_specs.h:133
@ MISC_INFO_STREAM
Definition: mdmp_specs.h:131
@ HANDLE_OPERATION_LIST_STREAM
Definition: mdmp_specs.h:134
@ RESERVED_STREAM_0
Definition: mdmp_specs.h:117
@ HANDLE_DATA_STREAM
Definition: mdmp_specs.h:128
@ MODULE_LIST_STREAM
Definition: mdmp_specs.h:120
@ COMMENT_STREAM_W
Definition: mdmp_specs.h:127
@ MEMORY_64_LIST_STREAM
Definition: mdmp_specs.h:125
@ THREAD_EX_LIST_STREAM
Definition: mdmp_specs.h:124
@ RESERVED_STREAM_1
Definition: mdmp_specs.h:118
@ MEMORY_LIST_STREAM
Definition: mdmp_specs.h:121
@ THREAD_LIST_STREAM
Definition: mdmp_specs.h:119
@ MEMORY_INFO_LIST_STREAM
Definition: mdmp_specs.h:132
@ SYSTEM_INFO_STREAM
Definition: mdmp_specs.h:123
#define MINIDUMP_PAGE_GUARD
Definition: mdmp_specs.h:59
#define MINIDUMP_PAGE_EXECUTE_READ
Definition: mdmp_specs.h:56
#define MINIDUMP_PAGE_READONLY
Definition: mdmp_specs.h:52
#define MINIDUMP_PAGE_EXECUTE_READWRITE
Definition: mdmp_specs.h:57
#define MINIDUMP_PAGE_READWRITE
Definition: mdmp_specs.h:53
#define MINIDUMP_PAGE_NOCACHE
Definition: mdmp_specs.h:60
#define MINIDUMP_PAGE_WRITECOPY
Definition: mdmp_specs.h:54
#define MINIDUMP_PAGE_EXECUTE
Definition: mdmp_specs.h:55
int idx
Definition: setup.py:197
RZ_API int sdb_num_set(Sdb *s, const char *key, ut64 v, ut32 cas)
Definition: num.c:25
void Pe64_write_image_section_header(RzBuffer *b, ut64 addr, Pe64_image_section_header *section_header)
struct Pe32_image_file_header Pe64_image_file_header
bool Pe64_read_image_section_header(RzBuffer *b, ut64 addr, Pe64_image_section_header *section_header)
bool Pe64_read_dos_header(RzBuffer *buf, Pe64_image_dos_header *header)
bool Pe64_read_nt_headers(RzBuffer *buf, ut64 addr, Pe64_image_nt_headers *headers)
RZ_API st64 rz_buf_seek(RZ_NONNULL RzBuffer *b, st64 addr, int whence)
Modify the current cursor position in the buffer.
Definition: buf.c:1166
#define RZ_BUF_CUR
Definition: rz_buf.h:15
RZ_API RzBuffer * rz_buf_ref(RzBuffer *b)
Increment the reference count of the buffer.
Definition: buf.c:668
RZ_API bool rz_buf_read8_at(RzBuffer *b, ut64 addr, RZ_NONNULL RZ_OUT ut8 *result)
Read a byte at the specified address in the buffer.
Definition: buf.c:876
RZ_API st64 rz_buf_read_at(RZ_NONNULL RzBuffer *b, ut64 addr, RZ_NONNULL RZ_OUT ut8 *buf, ut64 len)
Read len bytes of the buffer at the specified address.
Definition: buf.c:1136
#define rz_buf_read_le32_at(b, addr, result)
Definition: rz_buf.h:271
#define RZ_BUF_SET
Definition: rz_buf.h:14
#define rz_buf_read_le32(b, result)
Definition: rz_buf.h:267
#define rz_buf_read_le64(b, result)
Definition: rz_buf.h:268
RZ_API void rz_buf_free(RzBuffer *b)
Free all internal data hold by the buffer and the buffer.
Definition: buf.c:1253
RZ_API RZ_OWN RzBuffer * rz_buf_new_with_bytes(RZ_NULLABLE RZ_BORROW const ut8 *bytes, ut64 len)
Creates a new buffer with a bytes array.
Definition: buf.c:465
RZ_API ut64 rz_buf_size(RZ_NONNULL RzBuffer *b)
Return the size of the buffer.
Definition: buf.c:1225
void(* RzListFree)(void *ptr)
Definition: rz_list.h:11
#define RZ_LOG_INFO(fmtstr,...)
Definition: rz_log.h:54
#define RZ_LOG_WARN(fmtstr,...)
Definition: rz_log.h:56
#define RZ_LOG_ERROR(fmtstr,...)
Definition: rz_log.h:58
#define RZ_NEWS(x, y)
Definition: rz_types.h:283
#define PFMT64d
Definition: rz_types.h:394
#define RZ_PERM_R
Definition: rz_types.h:93
#define RZ_NEW0(x)
Definition: rz_types.h:284
#define RZ_PERM_RW
Definition: rz_types.h:96
#define RZ_NEW(x)
Definition: rz_types.h:285
#define RZ_PERM_X
Definition: rz_types.h:95
#define RZ_PERM_RX
Definition: rz_types.h:97
#define RZ_PERM_RWX
Definition: rz_types.h:98
#define RZ_FREE(x)
Definition: rz_types.h:369
#define RZ_MIN(x, y)
#define st64
Definition: rz_types_base.h:10
RZ_API int sdb_set(Sdb *s, const char *key, const char *val, ut32 cas)
Definition: sdb.c:611
RZ_API Sdb * sdb_new0(void)
Definition: sdb.c:43
RZ_API bool sdb_free(Sdb *s)
Definition: sdb.c:206
static struct sockaddr static addrlen static backlog const void static flags void flags
Definition: sfsocketcall.h:123
#define b(i)
Definition: sha256.c:42
Pe64_image_file_header file_header
Definition: pe_specs.h:445
Definition: zipcmp.c:77
Definition: sftypes.h:77
struct minidump_handle_data_stream * handle_data
Definition: mdmp.h:27
struct minidump_exception_stream * exception
Definition: mdmp.h:25
struct minidump_misc_info * misc_info_1
Definition: mdmp.h:31
struct minidump_function_table_stream * function_table
Definition: mdmp.h:26
struct minidump_system_info * system_info
Definition: mdmp.h:28
union rz_bin_mdmp_obj::minidump_streams::@162 misc_info
struct rz_bin_mdmp_obj::minidump_streams::@163 memories64
RzList * pe32_bins
Definition: mdmp.h:52
Sdb * kv
Definition: mdmp.h:58
size_t size
Definition: mdmp.h:56
RzBuffer * b
Definition: mdmp.h:55
struct rz_bin_mdmp_obj::minidump_streams streams
RzList * pe64_bins
Definition: mdmp.h:53
struct minidump_header * hdr
Definition: mdmp.h:18
#define fail(test)
Definition: tests.h:29
Definition: dis.c:32
static st64 delta
Definition: vmenus.c:2425
ut64(WINAPI *w32_GetEnabledXStateFeatures)()
static int addr
Definition: z80asm.c:58