@@ -404,7 +404,8 @@ def __setitem__(self, index, value):
404404
405405
406406class Dumpulator (Architecture ):
407- def __init__ (self , minidump_file , trace = False ):
407+ def __init__ (self , minidump_file , * , trace = False , quiet = False ):
408+ self ._quiet = quiet
408409 self ._minidump = MinidumpFile .parse (minidump_file )
409410 super ().__init__ (type (self ._minidump .threads .threads [0 ].ContextObject ) is not WOW64_CONTEXT )
410411 self .addr_mask = 0xFFFFFFFFFFFFFFFF if self ._x64 else 0xFFFFFFFF
@@ -434,6 +435,13 @@ def __init__(self, minidump_file, trace=False):
434435 self ._setup_syscalls ()
435436 self .exports = self ._setup_exports ()
436437
438+ def info (self , message : str ):
439+ if not self ._quiet :
440+ print (message )
441+
442+ def error (self , message : str ):
443+ print (message )
444+
437445 # Source: https://github.com/mandiant/speakeasy/blob/767edd2272510a5badbab89c5f35d43a94041378/speakeasy/windows/winemu.py#L533
438446 def _setup_gdt (self , teb_addr ):
439447 """
@@ -538,7 +546,7 @@ def _setup_emulator(self):
538546 for info in self ._minidump .memory_info .infos :
539547 emu_addr = info .BaseAddress & self .addr_mask
540548 if info .State == MemoryState .MEM_COMMIT :
541- print (f"mapped base: 0x{ emu_addr :x} , size: 0x{ info .RegionSize :x} , protect: { info .Protect } " )
549+ self . info (f"mapped base: 0x{ emu_addr :x} , size: 0x{ info .RegionSize :x} , protect: { info .Protect } " )
542550 self ._uc .mem_map (emu_addr , info .RegionSize , map_unicorn_perms (info .Protect ))
543551 elif info .State == MemoryState .MEM_FREE and emu_addr > 0x10000 and info .RegionSize >= self ._allocate_size :
544552 self ._allocate_base = emu_addr
@@ -547,7 +555,7 @@ def _setup_emulator(self):
547555 seg : MinidumpMemorySegment
548556 for seg in self ._minidump .memory_segments_64 .memory_segments :
549557 emu_addr = seg .start_virtual_address & self .addr_mask
550- print (f"initialize base: 0x{ emu_addr :x} , size: 0x{ seg .size :x} " )
558+ self . info (f"initialize base: 0x{ emu_addr :x} , size: 0x{ seg .size :x} " )
551559 memory .move (seg .start_virtual_address )
552560 assert memory .current_position == seg .start_virtual_address
553561 data = memory .read (seg .size )
@@ -631,17 +639,17 @@ def _setup_emulator(self):
631639 self .stdin_handle = self .read_ptr (process_parameters + 0x18 )
632640 self .stdout_handle = self .read_ptr (process_parameters + 0x1c )
633641 self .stderr_handle = self .read_ptr (process_parameters + 0x20 )
634- print (f"TEB: 0x{ self .teb :x} , PEB: 0x{ self .peb :x} " )
635- print (f" ConsoleHandle: 0x{ self .console_handle :x} " )
636- print (f" StandardInput: 0x{ self .stdin_handle :x} " )
637- print (f" StandardOutput: 0x{ self .stdout_handle :x} " )
638- print (f" StandardError: 0x{ self .stderr_handle :x} " )
642+ self . info (f"TEB: 0x{ self .teb :x} , PEB: 0x{ self .peb :x} " )
643+ self . info (f" ConsoleHandle: 0x{ self .console_handle :x} " )
644+ self . info (f" StandardInput: 0x{ self .stdin_handle :x} " )
645+ self . info (f" StandardOutput: 0x{ self .stdout_handle :x} " )
646+ self . info (f" StandardError: 0x{ self .stderr_handle :x} " )
639647
640648 def _setup_exports (self ):
641649 exports = {}
642650 for module in self ._minidump .modules .modules :
643651 module_name = module .name .split ('\\ ' )[- 1 ].lower ()
644- print (f"{ module_name } 0x{ module .baseaddress :x} [0x{ module .size :x} ]" )
652+ self . info (f"{ module_name } 0x{ module .baseaddress :x} [0x{ module .size :x} ]" )
645653 for export in self ._parse_module_exports (module ):
646654 if export .name :
647655 name = export .name .decode ("utf-8" )
@@ -669,7 +677,7 @@ def _parse_module_exports(self, module):
669677 try :
670678 module_data = self .read (module .baseaddress , module .size )
671679 except UcError :
672- print (f"Failed to read module data" )
680+ self . error (f"Failed to read module data" )
673681 return []
674682 pe = PE (data = module_data , fast_load = True )
675683 # Hack to adjust pefile to accept in-memory modules
@@ -691,7 +699,7 @@ def _setup_syscalls(self):
691699 elif export .name == b"Wow64Transition" :
692700 addr = ntdll .baseaddress + export .address
693701 patch_addr = self .read_ptr (addr )
694- print (f"Patching Wow64Transition: { addr :0x} -> { patch_addr :0x} " )
702+ self . info (f"Patching Wow64Transition: { addr :0x} -> { patch_addr :0x} " )
695703 # See: https://opcode0x90.wordpress.com/2007/05/18/kifastsystemcall-hook/
696704 # mov edx, esp; sysenter; ret
697705 KiFastSystemCall = b"\x8B \xD4 \x0F \x34 \xC3 "
@@ -753,11 +761,11 @@ def allocate(self, size):
753761 def start (self , begin , end = 0xffffffffffffffff , count = 0 ):
754762 try :
755763 self ._uc .emu_start (begin , until = end , count = count )
756- print (f'emulation finished, cip = { self .regs .cip :0x} ' )
764+ self . info (f'emulation finished, cip = { self .regs .cip :0x} ' )
757765 if self .exit_code is not None :
758- print (f"exit code: { self .exit_code } " )
766+ self . info (f"exit code: { self .exit_code } " )
759767 except UcError as err :
760- print (f'error: { err } , cip = { self .regs .cip :0x} ' )
768+ self . error (f'error: { err } , cip = { self .regs .cip :0x} ' )
761769
762770 def stop (self , exit_code = None ):
763771 self .exit_code = int (exit_code )
@@ -772,12 +780,12 @@ def NtCurrentThread(self):
772780
773781def _hook_mem (uc : Uc , access , address , size , value , dp : Dumpulator ):
774782 if access == UC_MEM_READ_UNMAPPED :
775- print (f"unmapped read from { address :0x} [{ size :0x} ], cip = { dp .regs .cip :0x} " )
783+ dp . error (f"unmapped read from { address :0x} [{ size :0x} ], cip = { dp .regs .cip :0x} " )
776784 elif access == UC_MEM_WRITE_UNMAPPED :
777- print (f"unmapped write to { address :0x} [{ size :0x} ] = { value :0x} , cip = { dp .regs .cip :0x} " )
785+ dp . error (f"unmapped write to { address :0x} [{ size :0x} ] = { value :0x} , cip = { dp .regs .cip :0x} " )
778786
779787 elif access == UC_MEM_FETCH_UNMAPPED :
780- print (f"unmapped fetch of { address :0x} [{ size :0x} ] = { value :0x} , cip = { dp .regs .cip :0x} " )
788+ dp . error (f"unmapped fetch of { address :0x} [{ size :0x} ] = { value :0x} , cip = { dp .regs .cip :0x} " )
781789 return False
782790
783791def _get_regs (instr ):
@@ -844,7 +852,7 @@ def _arg_type_string(arg):
844852
845853
846854def _hook_interrupt (uc : Uc , number , dp : Dumpulator ):
847- print (f"interrupt { number } , cip = { dp .regs .cip :0x} " )
855+ dp . error (f"interrupt { number } , cip = { dp .regs .cip :0x} " )
848856 uc .emu_stop ()
849857
850858
@@ -861,7 +869,7 @@ def syscall_arg(index):
861869 return dp .regs .r10
862870 return dp .args [index ]
863871
864- print (f"syscall: { name } (" )
872+ dp . info (f"syscall: { name } (" )
865873 for i in range (0 , argcount ):
866874 argname = argspec .args [1 + i ]
867875 argtype = argspec .annotations [argname ]
@@ -881,25 +889,25 @@ def syscall_arg(index):
881889 if i + 1 == argcount :
882890 comma = ""
883891
884- print (f" { _arg_type_string (argvalue )} { argname } = { _arg_to_string (argvalue )} { comma } " )
885- print (")" )
892+ dp . info (f" { _arg_type_string (argvalue )} { argname } = { _arg_to_string (argvalue )} { comma } " )
893+ dp . info (")" )
886894 try :
887895 status = cb (dp , * args )
888- print (f"status = { status :x} " )
896+ dp . info (f"status = { status :x} " )
889897 dp .regs .cax = status
890898 dp .regs .ccx = dp .regs .cip + 2
891899 except Exception as exc :
892900 sys .stderr = sys .stdout
893901 traceback .print_exception (type (exc ), exc , exc .__traceback__ )
894- print (f"Exception thrown during syscall implementation, stopping emulation!" )
902+ dp . error (f"Exception thrown during syscall implementation, stopping emulation!" )
895903 uc .emu_stop ()
896904 else :
897- print (f"syscall index: { index :0x} -> { name } not implemented!" )
905+ dp . error (f"syscall index: { index :0x} -> { name } not implemented!" )
898906 uc .emu_stop ()
899907 else :
900- print (f"syscall index { index :0x} out of range" )
908+ dp . error (f"syscall index { index :0x} out of range" )
901909 uc .emu_stop ()
902910
903911def _hook_invalid (uc : Uc , address , dp : Dumpulator ):
904- print (f"invalid instruction at { address :0x} " )
912+ dp . error (f"invalid instruction at { address :0x} " )
905913 return False
0 commit comments