From 54f958154640264de2e5da2b3698ebd6c2cbf867 Mon Sep 17 00:00:00 2001 From: Fabrice Desclaux Date: Tue, 15 Sep 2020 08:08:08 +0200 Subject: [PATCH 01/12] Refactor Sandbox --- example/jitter/arm_sc.py | 13 +- example/jitter/sandbox_call.py | 3 +- example/jitter/sandbox_elf_aarch64l.py | 3 +- .../jitter/{arm.py => sandbox_elf_arml.py} | 3 +- example/jitter/sandbox_elf_ppc32.py | 3 +- example/jitter/sandbox_pe_x86_32.py | 7 +- example/jitter/sandbox_pe_x86_64.py | 7 +- example/jitter/test_x86_32_seh.py | 7 +- example/jitter/trace.py | 3 +- example/jitter/unpack_upx.py | 19 +- example/symbol_exec/dse_crackme.py | 3 +- miasm/analysis/sandbox.py | 1056 ++++++++--------- test/arch/x86/qemu/testqemu.py | 3 +- test/arch/x86/qemu/testqemu64.py | 3 +- test/os_dep/linux/test_env.py | 3 +- test/test_all.py | 6 +- 16 files changed, 516 insertions(+), 626 deletions(-) rename example/jitter/{arm.py => sandbox_elf_arml.py} (85%) diff --git a/example/jitter/arm_sc.py b/example/jitter/arm_sc.py index 201184296..3727eccf0 100755 --- a/example/jitter/arm_sc.py +++ b/example/jitter/arm_sc.py @@ -1,16 +1,15 @@ #! /usr/bin/env python2 #-*- coding:utf-8 -*- from miasm.core.utils import int_to_byte -from miasm.analysis.sandbox import Sandbox_Linux_armb_str -from miasm.analysis.sandbox import Sandbox_Linux_arml_str +from miasm.analysis.sandbox import Sandbox_Linux_armb_shellcode +from miasm.analysis.sandbox import Sandbox_Linux_arml_shellcode from miasm.loader.strpatchwork import StrPatchwork from miasm.core.locationdb import LocationDB from pdb import pm -parser = Sandbox_Linux_arml_str.parser(description="""Sandbox an elf binary with arm engine +parser = Sandbox_Linux_arml_shellcode.parser(description="""Sandbox an elf binary with arm engine (ex: jit_arm_sc.py example/demo_arm_l.bin)""") -parser.add_argument("filename", help="string Filename") parser.add_argument("endianness", help="endianness [b/l]") parser.add_argument('-v', "--verbose", help="verbose mode", action="store_true") @@ -18,14 +17,14 @@ options = parser.parse_args() if options.endianness == 'b': - sandbox = Sandbox_Linux_armb_str + sandbox = Sandbox_Linux_armb_shellcode elif options.endianness == 'l': - sandbox = Sandbox_Linux_arml_str + sandbox = Sandbox_Linux_arml_shellcode else: raise ValueError("Bad endianness!") loc_db = LocationDB() -sb = sandbox(loc_db, options.filename, options, globals()) +sb = sandbox(loc_db, options, globals()) if options.address is None: raise ValueError('invalid address') diff --git a/example/jitter/sandbox_call.py b/example/jitter/sandbox_call.py index 6d24777a5..82bbff4f1 100644 --- a/example/jitter/sandbox_call.py +++ b/example/jitter/sandbox_call.py @@ -9,11 +9,10 @@ # Parse arguments parser = Sandbox_Linux_arml.parser(description="ELF sandboxer") -parser.add_argument("filename", help="ELF Filename") options = parser.parse_args() loc_db = LocationDB() -sb = Sandbox_Linux_arml(loc_db, options.filename, options, globals()) +sb = Sandbox_Linux_arml(loc_db, options, globals()) with open(options.filename, "rb") as fdesc: cont = Container.from_stream(fdesc, loc_db) diff --git a/example/jitter/sandbox_elf_aarch64l.py b/example/jitter/sandbox_elf_aarch64l.py index 7ad911187..1d443e31e 100644 --- a/example/jitter/sandbox_elf_aarch64l.py +++ b/example/jitter/sandbox_elf_aarch64l.py @@ -8,12 +8,11 @@ # Parse arguments parser = Sandbox_Linux_aarch64l.parser(description="ELF sandboxer") -parser.add_argument("filename", help="ELF Filename") options = parser.parse_args() # Create sandbox loc_db = LocationDB() -sb = Sandbox_Linux_aarch64l(loc_db, options.filename, options, globals()) +sb = Sandbox_Linux_aarch64l(loc_db, options, globals()) log_func.setLevel(logging.ERROR) diff --git a/example/jitter/arm.py b/example/jitter/sandbox_elf_arml.py similarity index 85% rename from example/jitter/arm.py rename to example/jitter/sandbox_elf_arml.py index 72fcbc494..8d700f3ca 100755 --- a/example/jitter/arm.py +++ b/example/jitter/sandbox_elf_arml.py @@ -10,13 +10,12 @@ # Get arguments parser = Sandbox_Linux_arml.parser(description="""Sandbox an elf binary with arm engine (ex: jit_arm.py samples/md5_arm -a A684)""") -parser.add_argument("filename", help="ELF Filename") parser.add_argument('-v', "--verbose", help="verbose mode", action="store_true") options = parser.parse_args() # Prepare the sandbox loc_db = LocationDB() -sb = Sandbox_Linux_arml(loc_db, options.filename, options, globals()) +sb = Sandbox_Linux_arml(loc_db, options, globals()) # Handle 'verbose' option if options.verbose is True: diff --git a/example/jitter/sandbox_elf_ppc32.py b/example/jitter/sandbox_elf_ppc32.py index d59181de1..94769e947 100644 --- a/example/jitter/sandbox_elf_ppc32.py +++ b/example/jitter/sandbox_elf_ppc32.py @@ -10,12 +10,11 @@ # Parse arguments parser = Sandbox_Linux_ppc32b.parser(description="ELF sandboxer") -parser.add_argument("filename", help="ELF Filename") options = parser.parse_args() # Create sandbox loc_db = LocationDB() -sb = Sandbox_Linux_ppc32b(loc_db, options.filename, options, globals()) +sb = Sandbox_Linux_ppc32b(loc_db, options, globals()) log_func.setLevel(logging.ERROR) sb.run() diff --git a/example/jitter/sandbox_pe_x86_32.py b/example/jitter/sandbox_pe_x86_32.py index de7af95d2..97f397686 100644 --- a/example/jitter/sandbox_pe_x86_32.py +++ b/example/jitter/sandbox_pe_x86_32.py @@ -1,16 +1,15 @@ from pdb import pm -from miasm.analysis.sandbox import Sandbox_Win_x86_32 +from miasm.analysis.sandbox import Sandbox_WinXP_x86_32 from miasm.core.locationdb import LocationDB # Insert here user defined methods # Parse arguments -parser = Sandbox_Win_x86_32.parser(description="PE sandboxer") -parser.add_argument("filename", help="PE Filename") +parser = Sandbox_WinXP_x86_32.parser(description="PE sandboxer") options = parser.parse_args() # Create sandbox loc_db = LocationDB() -sb = Sandbox_Win_x86_32(loc_db, options.filename, options, globals()) +sb = Sandbox_WinXP_x86_32(loc_db, options, globals()) # Run sb.run() diff --git a/example/jitter/sandbox_pe_x86_64.py b/example/jitter/sandbox_pe_x86_64.py index a168c3250..401a92fb9 100644 --- a/example/jitter/sandbox_pe_x86_64.py +++ b/example/jitter/sandbox_pe_x86_64.py @@ -1,17 +1,16 @@ from pdb import pm -from miasm.analysis.sandbox import Sandbox_Win_x86_64 +from miasm.analysis.sandbox import Sandbox_WinXP_x86_64 from miasm.core.locationdb import LocationDB # Insert here user defined methods # Parse arguments -parser = Sandbox_Win_x86_64.parser(description="PE sandboxer") -parser.add_argument("filename", help="PE Filename") +parser = Sandbox_WinXP_x86_64.parser(description="PE sandboxer") options = parser.parse_args() # Create sandbox loc_db = LocationDB() -sb = Sandbox_Win_x86_64(loc_db, options.filename, options, globals()) +sb = Sandbox_WinXP_x86_64(loc_db, options, globals()) # Run sb.run() diff --git a/example/jitter/test_x86_32_seh.py b/example/jitter/test_x86_32_seh.py index e2c354a0c..66dd5c32b 100644 --- a/example/jitter/test_x86_32_seh.py +++ b/example/jitter/test_x86_32_seh.py @@ -1,6 +1,6 @@ import os from pdb import pm -from miasm.analysis.sandbox import Sandbox_Win_x86_32 +from miasm.analysis.sandbox import Sandbox_WinXP_x86_32 from miasm.core.locationdb import LocationDB from miasm.os_dep import win_api_x86_32_seh from miasm.jitter.csts import * @@ -36,15 +36,14 @@ def return_from_seh(jitter): # Insert here user defined methods # Parse arguments -parser = Sandbox_Win_x86_32.parser(description="PE sandboxer") -parser.add_argument("filename", help="PE Filename") +parser = Sandbox_WinXP_x86_32.parser(description="PE sandboxer") options = parser.parse_args() options.usesegm = True options.use_windows_structs = True # Create sandbox loc_db = LocationDB() -sb = Sandbox_Win_x86_32(loc_db, options.filename, options, globals()) +sb = Sandbox_WinXP_x86_32(loc_db, options, globals()) # Install Windows SEH callbacks sb.jitter.add_exception_handler(EXCEPT_ACCESS_VIOL, deal_exception_access_violation) diff --git a/example/jitter/trace.py b/example/jitter/trace.py index 968626f42..af80b9159 100644 --- a/example/jitter/trace.py +++ b/example/jitter/trace.py @@ -38,7 +38,6 @@ def mem_write(self, dest, data): # Parse arguments parser = Sandbox_Linux_arml.parser(description="Tracer") -parser.add_argument("filename", help="ELF Filename") options = parser.parse_args() # Use our memory tracker @@ -47,7 +46,7 @@ def mem_write(self, dest, data): # Create sandbox, forcing Python jitter options.jitter = "python" loc_db = LocationDB() -sb = Sandbox_Linux_arml(loc_db, options.filename, options, globals()) +sb = Sandbox_Linux_arml(loc_db, options, globals()) # Force jit one instr per call, and register our callback sb.jitter.jit.set_options(jit_maxline=1, max_exec_per_call=1) diff --git a/example/jitter/unpack_upx.py b/example/jitter/unpack_upx.py index 59f7389a1..dbcbe0799 100644 --- a/example/jitter/unpack_upx.py +++ b/example/jitter/unpack_upx.py @@ -1,7 +1,8 @@ from __future__ import print_function +from pdb import pm import os import logging -from miasm.analysis.sandbox import Sandbox_Win_x86_32 +from miasm.analysis.sandbox import Sandbox_WinXP_x86_32 from miasm.jitter.loader.pe import vm2pe from miasm.core.locationdb import LocationDB @@ -32,20 +33,24 @@ def kernel32_GetProcAddress(jitter): jitter.func_ret_stdcall(ret_ad, ad) -parser = Sandbox_Win_x86_32.parser(description="Generic UPX unpacker") -parser.add_argument("filename", help="PE Filename") +parser = Sandbox_WinXP_x86_32.parser(description="Generic UPX unpacker") parser.add_argument('-v', "--verbose", help="verbose mode", action="store_true") + +""" +parser.add_argument("filename", help="PE Filename") +""" + parser.add_argument("--graph", help="Export the CFG graph in graph.dot", action="store_true") + options = parser.parse_args() options.load_hdr = True loc_db = LocationDB() -sb = Sandbox_Win_x86_32( - loc_db, options.filename, options, globals(), - parse_reloc=False +sb = Sandbox_WinXP_x86_32( + loc_db, options, globals() ) @@ -58,7 +63,7 @@ def kernel32_GetProcAddress(jitter): print(sb.jitter.vm) # Ensure there is one and only one leave (for OEP discovering) -mdis = sb.machine.dis_engine(sb.jitter.bs, loc_db=loc_db) +mdis = sb.arch.machine.dis_engine(sb.jitter.bs, loc_db=loc_db) mdis.dont_dis_nulstart_bloc = True asmcfg = mdis.dis_multiblock(sb.entry_point) diff --git a/example/symbol_exec/dse_crackme.py b/example/symbol_exec/dse_crackme.py index fc2e14148..14d1d94dc 100644 --- a/example/symbol_exec/dse_crackme.py +++ b/example/symbol_exec/dse_crackme.py @@ -68,7 +68,6 @@ def xxx_fclose(jitter): # Create sandbox parser = Sandbox_Linux_x86_64.parser(description="ELF sandboxer") -parser.add_argument("filename", help="ELF Filename") parser.add_argument("--strategy", choices=["code-cov", "branch-cov", "path-cov"], help="Strategy to use for solution creation", @@ -77,7 +76,7 @@ def xxx_fclose(jitter): options.mimic_env = True options.command_line = ["%s" % TEMP_FILE.name] loc_db = LocationDB() -sb = Sandbox_Linux_x86_64(loc_db, options.filename, options, globals()) +sb = Sandbox_Linux_x86_64(loc_db, options, globals()) # Init segment sb.jitter.lifter.do_stk_segm = True diff --git a/miasm/analysis/sandbox.py b/miasm/analysis/sandbox.py index 542e31f93..0b5ef201c 100644 --- a/miasm/analysis/sandbox.py +++ b/miasm/analysis/sandbox.py @@ -15,13 +15,50 @@ from miasm.core.utils import force_bytes -class Sandbox(object): +class Arch(object): + """ + Parent class for Arch abstraction + """ + + @classmethod + def update_parser(cls, parser): + parser.add_argument( + "-j", + "--jitter", + help="Jitter engine. Possible values are: gcc (default), llvm, python", + default="gcc", + ) + parser.add_argument( + "-b", "--dumpblocs", action="store_true", help="Log disasm blocks" + ) + parser.add_argument( + "-z", "--singlestep", action="store_true", help="Log single step" + ) + + def __init__(self, loc_db, options): + self.machine = Machine(self._ARCH_) + self.jitter = self.machine.jitter(loc_db, options.jitter) + + # Logging options + self.jitter.set_trace_log( + trace_instr=options.singlestep, + trace_regs=options.singlestep, + trace_new_blocks=options.dumpblocs, + ) + + +class Sandbox(object): """ Parent class for Sandbox abstraction """ - CALL_FINISH_ADDR = 0x13371acc + CALL_FINISH_ADDR = 0x13371ACC + + def __init__(self, loc_db, options, custom_methods=None): + self.arch = self.CLS_ARCH(loc_db, options) + self.os = self.CLS_OS(self.arch.jitter, options, custom_methods) + self.jitter = self.arch.jitter @staticmethod def code_sentinelle(jitter): @@ -29,52 +66,19 @@ def code_sentinelle(jitter): return False @classmethod - def _classes_(cls): - """ - Iterator on parent classes except Sanbox - """ - for base_cls in cls.__bases__: - # Avoid infinite loop - if base_cls == Sandbox: - continue - - yield base_cls - - classes = property(lambda x: x.__class__._classes_()) - - def __init__(self, loc_db, fname, options, custom_methods=None, **kwargs): - """ - Initialize a sandbox - @fname: str file name - @options: namespace instance of specific options - @custom_methods: { str => func } for custom API implementations - """ - - # Initialize - assert isinstance(fname, basestring) - self.fname = fname - self.options = options - self.loc_db = loc_db - if custom_methods is None: - custom_methods = {} - kwargs["loc_db"] = loc_db - for cls in self.classes: - if cls == Sandbox: - continue - if issubclass(cls, OS): - cls.__init__(self, custom_methods, **kwargs) - else: - cls.__init__(self, **kwargs) - - # Logging options - self.jitter.set_trace_log( - trace_instr=self.options.singlestep, - trace_regs=self.options.singlestep, - trace_new_blocks=self.options.dumpblocs + def update_parser(cls, parser): + parser.add_argument( + "-a", "--address", help="Force entry point address", default=None, + ) + parser.add_argument( + "-d", "--debugging", action="store_true", help="Debug shell", + ) + parser.add_argument( + "-g", "--gdbserver", type=int, help="Listen on port @port", ) - if not self.options.quiet_function_calls: - log_func.setLevel(logging.INFO) + cls.CLS_ARCH.update_parser(parser) + cls.CLS_OS.update_parser(parser) @classmethod def parser(cls, *args, **kwargs): @@ -84,27 +88,7 @@ def parser(cls, *args, **kwargs): """ parser = ArgumentParser(*args, **kwargs) - parser.add_argument('-a', "--address", - help="Force entry point address", default=None) - parser.add_argument('-b', "--dumpblocs", action="store_true", - help="Log disasm blocks") - parser.add_argument('-z', "--singlestep", action="store_true", - help="Log single step") - parser.add_argument('-d', "--debugging", action="store_true", - help="Debug shell") - parser.add_argument('-g', "--gdbserver", type=int, - help="Listen on port @port") - parser.add_argument("-j", "--jitter", - help="Jitter engine. Possible values are: gcc (default), llvm, python", - default="gcc") - parser.add_argument( - '-q', "--quiet-function-calls", action="store_true", - help="Don't log function calls") - parser.add_argument('-i', "--dependencies", action="store_true", - help="Load PE and its dependencies") - - for base_cls in cls._classes_(): - base_cls.update_parser(parser) + cls.update_parser(parser) return parser def run(self, addr=None): @@ -112,11 +96,15 @@ def run(self, addr=None): Launch emulation (gdbserver, debugging, basic JIT). @addr: (int) start address """ - if addr is None and self.options.address is not None: + if addr is not None: + addr = addr + elif self.options.address is not None: addr = int(self.options.address, 0) + else: + addr = self.entry_point if any([self.options.debugging, self.options.gdbserver]): - dbg = debugging.Debugguer(self.jitter) + dbg = debugging.Debugguer(self.arch.jitter) self.dbg = dbg dbg.init_run(addr) @@ -132,8 +120,8 @@ def run(self, addr=None): cmd.cmdloop() else: - self.jitter.init_run(addr) - self.jitter.continue_run() + self.arch.jitter.init_run(addr) + self.arch.jitter.continue_run() def call(self, prepare_cb, addr, *args): """ @@ -149,56 +137,99 @@ def call(self, prepare_cb, addr, *args): self.jitter.continue_run() - class OS(object): - """ Parent class for OS abstraction """ - def __init__(self, custom_methods, **kwargs): - pass + +class Arch_x86_32(Arch): + _ARCH_ = "x86_32" # Arch name + + def __init__(self, loc_db, options): + super(Arch_x86_32, self).__init__(loc_db, options) + + if options.usesegm: + self.jitter.lifter.do_stk_segm = True + self.jitter.lifter.do_ds_segm = True + self.jitter.lifter.do_str_segm = True + self.jitter.lifter.do_all_segm = True @classmethod def update_parser(cls, parser): - pass + Arch.update_parser(parser) + parser.add_argument("-s", "--usesegm", action="store_true", help="Use segments") -class Arch(object): +class Arch_arml(Arch): + _ARCH_ = "arml" - """ - Parent class for Arch abstraction - """ - # Architecture name - _ARCH_ = None +class Arch_armb(Arch): + _ARCH_ = "armb" - def __init__(self, loc_db, **kwargs): - self.machine = Machine(self._ARCH_) - self.jitter = self.machine.jitter(loc_db, self.options.jitter) - @classmethod - def update_parser(cls, parser): - pass +class Arch_aarch64l(Arch): + _ARCH_ = "aarch64l" -class OS_Win(OS): - # DLL to import - ALL_IMP_DLL = [ - "ntdll.dll", "kernel32.dll", "user32.dll", - "ole32.dll", "urlmon.dll", - "ws2_32.dll", 'advapi32.dll', "psapi.dll", +class Arch_aarch64b(Arch): + _ARCH_ = "aarch64b" + + +class Arch_ppc32b(Arch): + _ARCH_ = "ppc32b" + + +class Arch_x86_64(Arch): + _ARCH_ = "x86_64" + + +class Arch_mips32b(Arch): + _ARCH_ = "mips32b" + + +class Arch_mips32l(Arch): + _ARCH_ = "mips32l" + + +class OS_WinXP32(OS): + LOADED_DLLS = [ + "ntdll.dll", + "kernel32.dll", + "user32.dll", + "ole32.dll", + "urlmon.dll", + "ws2_32.dll", + "advapi32.dll", + "psapi.dll", ] - modules_path = "win_dll" - def __init__(self, custom_methods, *args, **kwargs): - from miasm.jitter.loader.pe import vm_load_pe, vm_load_pe_libs,\ - preload_pe, libimp_pe, vm_load_pe_and_dependencies + PATH_DLLS = "win_dll" + + STACK_SIZE = 0x10000 + STACK_BASE = 0x130000 + + def __init__(self, jitter, options, custom_methods=None): + from miasm.jitter.loader.pe import ( + vm_load_pe, + vm_load_pe_libs, + preload_pe, + libimp_pe, + vm_load_pe_and_dependencies, + ) from miasm.os_dep import win_api_x86_32, win_api_x86_32_seh - methods = dict((name, func) for name, func in viewitems(win_api_x86_32.__dict__)) + + self.jitter = jitter + methods = dict( + (name, func) for name, func in viewitems(win_api_x86_32.__dict__) + ) methods.update(custom_methods) - super(OS_Win, self).__init__(methods, *args, **kwargs) + # Init stack + self.jitter.stack_size = self.STACK_SIZE + self.jitter.stack_base = self.STACK_BASE + self.jitter.init_stack() # Import manager libs = libimp_pe() @@ -206,32 +237,31 @@ def __init__(self, custom_methods, *args, **kwargs): win_api_x86_32.winobjs.runtime_dll = libs self.name2module = {} - fname_basename = os.path.basename(self.fname).lower() + fname_basename = os.path.basename(options.filename).lower() # Load main pe - with open(self.fname, "rb") as fstream: + with open(options.filename, "rb") as fstream: self.pe = vm_load_pe( self.jitter.vm, fstream.read(), - load_hdr=self.options.load_hdr, - name=self.fname, + load_hdr=options.load_hdr, + name=options.filename, winobjs=win_api_x86_32.winobjs, - **kwargs ) self.name2module[fname_basename] = self.pe - # Load library - if self.options.loadbasedll: + win_api_x86_32.winobjs.current_pe = self.pe + # Load library + if options.loadbasedll: # Load libs in memory self.name2module.update( vm_load_pe_libs( self.jitter.vm, - self.ALL_IMP_DLL, + self.LOADED_DLLS, libs, - self.modules_path, + self.PATH_DLLS, winobjs=win_api_x86_32.winobjs, - **kwargs ) ) @@ -239,19 +269,16 @@ def __init__(self, custom_methods, *args, **kwargs): for pe in viewvalues(self.name2module): preload_pe(self.jitter.vm, pe, libs) - if self.options.dependencies: + if options.dependencies: vm_load_pe_and_dependencies( self.jitter.vm, fname_basename, self.name2module, libs, - self.modules_path, + self.PATH_DLLS, winobjs=win_api_x86_32.winobjs, - **kwargs ) - win_api_x86_32.winobjs.current_pe = self.pe - # Fix pe imports preload_pe(self.jitter.vm, self.pe, libs) @@ -259,7 +286,7 @@ def __init__(self, custom_methods, *args, **kwargs): self.jitter.add_lib_handler(libs, methods) # Manage SEH - if self.options.use_windows_structs: + if options.use_windows_structs: win_api_x86_32_seh.main_pe_name = fname_basename win_api_x86_32_seh.main_pe = self.pe win_api_x86_32.winobjs.hcurmodule = self.pe.NThdr.ImageBase @@ -267,317 +294,232 @@ def __init__(self, custom_methods, *args, **kwargs): win_api_x86_32_seh.set_win_fs_0(self.jitter) win_api_x86_32_seh.init_seh(self.jitter) - self.entry_point = self.pe.rva2virt( - self.pe.Opthdr.AddressOfEntryPoint) - @classmethod def update_parser(cls, parser): - parser.add_argument('-o', "--load-hdr", action="store_true", - help="Load pe hdr") - parser.add_argument('-y', "--use-windows-structs", action="store_true", - help="Create and use windows structures (peb, ldr, seh, ...)") - parser.add_argument('-l', "--loadbasedll", action="store_true", - help="Load base dll (path './win_dll')") - parser.add_argument('-r', "--parse-resources", - action="store_true", help="Load resources") - - -class OS_Linux(OS): - - PROGRAM_PATH = "./program" - - def __init__(self, custom_methods, *args, **kwargs): - from miasm.jitter.loader.elf import vm_load_elf, preload_elf, libimp_elf - from miasm.os_dep import linux_stdlib - methods = linux_stdlib.__dict__ - methods.update(custom_methods) - - super(OS_Linux, self).__init__(methods, *args, **kwargs) - - # Import manager - self.libs = libimp_elf() - - with open(self.fname, "rb") as fstream: - self.elf = vm_load_elf( - self.jitter.vm, - fstream.read(), - name=self.fname, - **kwargs - ) - preload_elf(self.jitter.vm, self.elf, self.libs) - - self.entry_point = self.elf.Ehdr.entry - - # Library calls handler - self.jitter.add_lib_handler(self.libs, methods) - linux_stdlib.ABORT_ADDR = self.CALL_FINISH_ADDR - - # Arguments - self.argv = [self.PROGRAM_PATH] - if self.options.command_line: - self.argv += self.options.command_line - self.envp = self.options.environment_vars - - @classmethod - def update_parser(cls, parser): - parser.add_argument('-c', '--command-line', - action="append", - default=[], - help="Command line arguments") - parser.add_argument('--environment-vars', - action="append", - default=[], - help="Environment variables arguments") - parser.add_argument('--mimic-env', - action="store_true", - help="Mimic the environment of a starting executable") - -class OS_Linux_str(OS): - - PROGRAM_PATH = "./program" - - def __init__(self, custom_methods, *args, **kwargs): - from miasm.jitter.loader.elf import libimp_elf - from miasm.os_dep import linux_stdlib - methods = linux_stdlib.__dict__ - methods.update(custom_methods) - - super(OS_Linux_str, self).__init__(methods, *args, **kwargs) - - # Import manager - libs = libimp_elf() - self.libs = libs - - data = open(self.fname, "rb").read() - self.options.load_base_addr = int(self.options.load_base_addr, 0) - self.jitter.vm.add_memory_page( - self.options.load_base_addr, PAGE_READ | PAGE_WRITE, data, - "Initial Str" + parser.add_argument("filename", help="PE Filename") + parser.add_argument("-o", "--load-hdr", action="store_true", help="Load pe hdr") + parser.add_argument( + "-y", + "--use-windows-structs", + action="store_true", + help="Create and use windows structures (peb, ldr, seh, ...)", + ) + parser.add_argument( + "-l", + "--loadbasedll", + action="store_true", + help="Load base dll (path './win_dll')", + ) + parser.add_argument( + "-r", "--parse-resources", action="store_true", help="Load resources" + ) + parser.add_argument( + "-i", + "--dependencies", + action="store_true", + help="Load PE and its dependencies", + ) + parser.add_argument( + "-q", + "--quiet-function-calls", + action="store_true", + help="Don't log function calls", ) - # Library calls handler - self.jitter.add_lib_handler(libs, methods) - linux_stdlib.ABORT_ADDR = self.CALL_FINISH_ADDR - - # Arguments - self.argv = [self.PROGRAM_PATH] - if self.options.command_line: - self.argv += self.options.command_line - self.envp = self.options.environment_vars - - @classmethod - def update_parser(cls, parser): - parser.add_argument('-c', '--command-line', - action="append", - default=[], - help="Command line arguments") - parser.add_argument('--environment-vars', - action="append", - default=[], - help="Environment variables arguments") - parser.add_argument('--mimic-env', - action="store_true", - help="Mimic the environment of a starting executable") - parser.add_argument("load_base_addr", help="load base address") - - -class Arch_x86(Arch): - _ARCH_ = None # Arch name - STACK_SIZE = 0x10000 - STACK_BASE = 0x130000 - - def __init__(self, loc_db, **kwargs): - super(Arch_x86, self).__init__(loc_db, **kwargs) - - if self.options.usesegm: - self.jitter.lifter.do_stk_segm = True - self.jitter.lifter.do_ds_segm = True - self.jitter.lifter.do_str_segm = True - self.jitter.lifter.do_all_segm = True - - # Init stack - self.jitter.stack_size = self.STACK_SIZE - self.jitter.stack_base = self.STACK_BASE - self.jitter.init_stack() - @classmethod - def update_parser(cls, parser): - parser.add_argument('-s', "--usesegm", action="store_true", - help="Use segments") +class Sandbox_WinXP_x86_32(Sandbox): + CLS_ARCH = Arch_x86_32 + CLS_OS = OS_WinXP32 + def __init__(self, loc_db, options, custom_methods=None): + super(Sandbox_WinXP_x86_32, self).__init__(loc_db, options, custom_methods) + self.pe = self.os.pe + self.libs = self.os.libs -class Arch_x86_32(Arch_x86): - _ARCH_ = "x86_32" + self.entry_point = self.pe.rva2virt(self.pe.Opthdr.AddressOfEntryPoint) + self.options = options + self.loc_db = loc_db -class Arch_x86_64(Arch_x86): - _ARCH_ = "x86_64" + # Pre-stack return address + self.jitter.push_uint32_t(self.CALL_FINISH_ADDR) + self.jitter.add_breakpoint(self.CALL_FINISH_ADDR, self.code_sentinelle) + def call(self, addr, *args, **kwargs): + """ + Direct call of the function at @addr, with arguments @args + @addr: address of the target function + @args: arguments + """ + prepare_cb = kwargs.pop("prepare_cb", self.jitter.func_prepare_stdcall) + super(Sandbox_WinXP_x86_32, self).call(prepare_cb, addr, *args) -class Arch_arml(Arch): - _ARCH_ = "arml" - STACK_SIZE = 0x100000 - STACK_BASE = 0x100000 - def __init__(self, loc_db, **kwargs): - super(Arch_arml, self).__init__(loc_db, **kwargs) +class Sandbox_WinXP_x86_64(Sandbox): + CLS_ARCH = Arch_x86_64 + CLS_OS = OS_WinXP32 - # Init stack - self.jitter.stack_size = self.STACK_SIZE - self.jitter.stack_base = self.STACK_BASE - self.jitter.init_stack() + def __init__(self, loc_db, options, custom_methods=None): + super(Sandbox_WinXP_x86_64, self).__init__(loc_db, options, custom_methods) + self.pe = self.os.pe + self.libs = self.os.libs + self.entry_point = self.pe.rva2virt(self.pe.Opthdr.AddressOfEntryPoint) -class Arch_armb(Arch): - _ARCH_ = "armb" - STACK_SIZE = 0x100000 - STACK_BASE = 0x100000 - - def __init__(self, loc_db, **kwargs): - super(Arch_armb, self).__init__(loc_db, **kwargs) - - # Init stack - self.jitter.stack_size = self.STACK_SIZE - self.jitter.stack_base = self.STACK_BASE - self.jitter.init_stack() + self.options = options + self.loc_db = loc_db + # Pre-stack return address + self.jitter.push_uint64_t(self.CALL_FINISH_ADDR) + self.jitter.add_breakpoint(self.CALL_FINISH_ADDR, self.code_sentinelle) -class Arch_armtl(Arch): - _ARCH_ = "armtl" - STACK_SIZE = 0x100000 - STACK_BASE = 0x100000 + def call(self, addr, *args, **kwargs): + """ + Direct call of the function at @addr, with arguments @args + @addr: address of the target function + @args: arguments + """ + prepare_cb = kwargs.pop("prepare_cb", self.jitter.func_prepare_stdcall) + super(Sandbox_WinXP_x86_64, self).call(prepare_cb, addr, *args) - def __init__(self, loc_db, **kwargs): - super(Arch_armtl, self).__init__(loc_db, **kwargs) - # Init stack - self.jitter.stack_size = self.STACK_SIZE - self.jitter.stack_base = self.STACK_BASE - self.jitter.init_stack() +class OS_Linux(OS): + CALL_FINISH_ADDR = 0x13371ACC -class Arch_mips32b(Arch): - _ARCH_ = "mips32b" STACK_SIZE = 0x100000 STACK_BASE = 0x100000 - def __init__(self, loc_db, **kwargs): - super(Arch_mips32b, self).__init__(loc_db, **kwargs) - - # Init stack - self.jitter.stack_size = self.STACK_SIZE - self.jitter.stack_base = self.STACK_BASE - self.jitter.init_stack() - + def __init__(self, jitter, options, custom_methods=None): + from miasm.jitter.loader.elf import vm_load_elf, preload_elf, libimp_elf + from miasm.os_dep import linux_stdlib -class Arch_aarch64l(Arch): - _ARCH_ = "aarch64l" - STACK_SIZE = 0x100000 - STACK_BASE = 0x100000 + methods = linux_stdlib.__dict__ + methods.update(custom_methods) - def __init__(self, loc_db, **kwargs): - super(Arch_aarch64l, self).__init__(loc_db, **kwargs) + self.jitter = jitter # Init stack self.jitter.stack_size = self.STACK_SIZE self.jitter.stack_base = self.STACK_BASE self.jitter.init_stack() + # Import manager + self.libs = libimp_elf() -class Arch_aarch64b(Arch): - _ARCH_ = "aarch64b" - STACK_SIZE = 0x100000 - STACK_BASE = 0x100000 - - def __init__(self, loc_db, **kwargs): - super(Arch_aarch64b, self).__init__(loc_db, **kwargs) - - # Init stack - self.jitter.stack_size = self.STACK_SIZE - self.jitter.stack_base = self.STACK_BASE - self.jitter.init_stack() + with open(options.filename, "rb") as fstream: + self.elf = vm_load_elf( + self.jitter.vm, fstream.read(), name=options.filename, + ) + preload_elf(self.jitter.vm, self.elf, self.libs) -class Arch_ppc(Arch): - _ARCH_ = None + self.entry_point = self.elf.Ehdr.entry -class Arch_ppc32(Arch): - _ARCH_ = None + # Library calls handler + self.jitter.add_lib_handler(self.libs, methods) + linux_stdlib.ABORT_ADDR = self.CALL_FINISH_ADDR -class Arch_ppc32b(Arch_ppc32): - _ARCH_ = "ppc32b" + @classmethod + def update_parser(cls, parser): + parser.add_argument("filename", help="ELF Filename") + parser.add_argument( + "-c", + "--command-line", + action="append", + default=[], + help="Command line arguments", + ) + parser.add_argument( + "--environment-vars", + action="append", + default=[], + help="Environment variables arguments", + ) + parser.add_argument( + "--mimic-env", + action="store_true", + help="Mimic the environment of a starting executable", + ) -class Sandbox_Win_x86_32(Sandbox, Arch_x86_32, OS_Win): - def __init__(self, loc_db, *args, **kwargs): - Sandbox.__init__(self, loc_db, *args, **kwargs) +class OS_Linux_shellcode(OS): - # Pre-stack some arguments - self.jitter.push_uint32_t(2) - self.jitter.push_uint32_t(1) - self.jitter.push_uint32_t(0) - self.jitter.push_uint32_t(self.CALL_FINISH_ADDR) + CALL_FINISH_ADDR = 0x13371ACC - # Set the runtime guard - self.jitter.add_breakpoint(self.CALL_FINISH_ADDR, self.__class__.code_sentinelle) + STACK_SIZE = 0x100000 + STACK_BASE = 0x100000 - def run(self, addr=None): - """ - If addr is not set, use entrypoint - """ - if addr is None and self.options.address is None: - addr = self.entry_point - super(Sandbox_Win_x86_32, self).run(addr) + def __init__(self, jitter, options, custom_methods=None): + from miasm.jitter.loader.elf import vm_load_elf, preload_elf, libimp_elf + from miasm.os_dep import linux_stdlib - def call(self, addr, *args, **kwargs): - """ - Direct call of the function at @addr, with arguments @args - @addr: address of the target function - @args: arguments - """ - prepare_cb = kwargs.pop('prepare_cb', self.jitter.func_prepare_stdcall) - super(self.__class__, self).call(prepare_cb, addr, *args) + methods = linux_stdlib.__dict__ + methods.update(custom_methods) + self.jitter = jitter -class Sandbox_Win_x86_64(Sandbox, Arch_x86_64, OS_Win): + # Init stack + self.jitter.stack_size = self.STACK_SIZE + self.jitter.stack_base = self.STACK_BASE + self.jitter.init_stack() - def __init__(self, loc_db, *args, **kwargs): - Sandbox.__init__(self, loc_db, *args, **kwargs) + # Import manager + self.libs = libimp_elf() - # reserve stack for local reg - for _ in range(0x4): - self.jitter.push_uint64_t(0) + data = open(options.filename, "rb").read() + options.load_base_addr = int(options.load_base_addr, 0) + self.jitter.vm.add_memory_page( + options.load_base_addr, PAGE_READ | PAGE_WRITE, data, "Initial shellcode" + ) - # Pre-stack return address - self.jitter.push_uint64_t(self.CALL_FINISH_ADDR) + # Library calls handler + self.jitter.add_lib_handler(self.libs, methods) + linux_stdlib.ABORT_ADDR = self.CALL_FINISH_ADDR - # Set the runtime guard - self.jitter.add_breakpoint( - self.CALL_FINISH_ADDR, - self.__class__.code_sentinelle + @classmethod + def update_parser(cls, parser): + parser.add_argument("filename", help="shellcode") + parser.add_argument("load_base_addr", help="load base address") + parser.add_argument( + "-c", + "--command-line", + action="append", + default=[], + help="Command line arguments", + ) + parser.add_argument( + "--environment-vars", + action="append", + default=[], + help="Environment variables arguments", + ) + parser.add_argument( + "--mimic-env", + action="store_true", + help="Mimic the environment of a starting executable", ) - def run(self, addr=None): - """ - If addr is not set, use entrypoint - """ - if addr is None and self.options.address is None: - addr = self.entry_point - super(Sandbox_Win_x86_64, self).run(addr) - def call(self, addr, *args, **kwargs): - """ - Direct call of the function at @addr, with arguments @args - @addr: address of the target function - @args: arguments - """ - prepare_cb = kwargs.pop('prepare_cb', self.jitter.func_prepare_stdcall) - super(self.__class__, self).call(prepare_cb, addr, *args) +class Sandbox_Linux_x86_32(Sandbox): + CLS_ARCH = Arch_x86_32 + CLS_OS = OS_Linux + PROGRAM_PATH = "./program" + + def __init__(self, loc_db, options, custom_methods=None): + super(Sandbox_Linux_x86_32, self).__init__(loc_db, options, custom_methods) + self.elf = self.os.elf + self.libs = self.os.libs + self.entry_point = self.elf.Ehdr.entry -class Sandbox_Linux_x86_32(Sandbox, Arch_x86_32, OS_Linux): + self.options = options + self.loc_db = loc_db - def __init__(self, loc_db, *args, **kwargs): - Sandbox.__init__(self, loc_db, *args, **kwargs) + # Arguments + self.argv = [self.PROGRAM_PATH] + if self.options.command_line: + self.argv += self.options.command_line + self.envp = self.options.environment_vars # Pre-stack some arguments if self.options.mimic_env: @@ -611,92 +553,39 @@ def __init__(self, loc_db, *args, **kwargs): # Set the runtime guard self.jitter.add_breakpoint( - self.CALL_FINISH_ADDR, - self.__class__.code_sentinelle + self.CALL_FINISH_ADDR, self.__class__.code_sentinelle ) - def run(self, addr=None): - """ - If addr is not set, use entrypoint - """ - if addr is None and self.options.address is None: - addr = self.entry_point - super(Sandbox_Linux_x86_32, self).run(addr) - def call(self, addr, *args, **kwargs): """ Direct call of the function at @addr, with arguments @args @addr: address of the target function @args: arguments """ - prepare_cb = kwargs.pop('prepare_cb', self.jitter.func_prepare_systemv) - super(self.__class__, self).call(prepare_cb, addr, *args) - - - -class Sandbox_Linux_x86_64(Sandbox, Arch_x86_64, OS_Linux): - - def __init__(self, loc_db, *args, **kwargs): - Sandbox.__init__(self, loc_db, *args, **kwargs) - - # Pre-stack some arguments - if self.options.mimic_env: - env_ptrs = [] - for env in self.envp: - env = force_bytes(env) - env += b"\x00" - self.jitter.cpu.RSP -= len(env) - ptr = self.jitter.cpu.RSP - self.jitter.vm.set_mem(ptr, env) - env_ptrs.append(ptr) - argv_ptrs = [] - for arg in self.argv: - arg = force_bytes(arg) - arg += b"\x00" - self.jitter.cpu.RSP -= len(arg) - ptr = self.jitter.cpu.RSP - self.jitter.vm.set_mem(ptr, arg) - argv_ptrs.append(ptr) - - self.jitter.push_uint64_t(self.CALL_FINISH_ADDR) - self.jitter.push_uint64_t(0) - for ptr in reversed(env_ptrs): - self.jitter.push_uint64_t(ptr) - self.jitter.push_uint64_t(0) - for ptr in reversed(argv_ptrs): - self.jitter.push_uint64_t(ptr) - self.jitter.push_uint64_t(len(self.argv)) - else: - self.jitter.push_uint64_t(self.CALL_FINISH_ADDR) + prepare_cb = kwargs.pop("prepare_cb", self.jitter.func_prepare_systemv) + super(Sandbox_Linux_x86_32, self).call(prepare_cb, addr, *args) - # Set the runtime guard - self.jitter.add_breakpoint( - self.CALL_FINISH_ADDR, - self.__class__.code_sentinelle - ) - def run(self, addr=None): - """ - If addr is not set, use entrypoint - """ - if addr is None and self.options.address is None: - addr = self.entry_point - super(Sandbox_Linux_x86_64, self).run(addr) +class Sandbox_Linux_arml(Sandbox): + CLS_ARCH = Arch_arml + CLS_OS = OS_Linux + PROGRAM_PATH = "./program" - def call(self, addr, *args, **kwargs): - """ - Direct call of the function at @addr, with arguments @args - @addr: address of the target function - @args: arguments - """ - prepare_cb = kwargs.pop('prepare_cb', self.jitter.func_prepare_systemv) - super(self.__class__, self).call(prepare_cb, addr, *args) + def __init__(self, loc_db, options, custom_methods=None): + super(Sandbox_Linux_arml, self).__init__(loc_db, options, custom_methods) + self.elf = self.os.elf + self.libs = self.os.libs + self.entry_point = self.elf.Ehdr.entry -class Sandbox_Linux_arml(Sandbox, Arch_arml, OS_Linux): + self.options = options + self.loc_db = loc_db - def __init__(self, loc_db, *args, **kwargs): - Sandbox.__init__(self, loc_db, *args, **kwargs) + # Arguments + self.argv = [self.PROGRAM_PATH] + if self.options.command_line: + self.argv += self.options.command_line + self.envp = self.options.environment_vars # Pre-stack some arguments if self.options.mimic_env: @@ -718,7 +607,7 @@ def __init__(self, loc_db, *args, **kwargs): argv_ptrs.append(ptr) # Round SP to 4 - self.jitter.cpu.SP = self.jitter.cpu.SP & ~ 3 + self.jitter.cpu.SP = self.jitter.cpu.SP & ~3 self.jitter.push_uint32_t(0) for ptr in reversed(env_ptrs): @@ -732,29 +621,40 @@ def __init__(self, loc_db, *args, **kwargs): # Set the runtime guard self.jitter.add_breakpoint( - self.CALL_FINISH_ADDR, - self.__class__.code_sentinelle + self.CALL_FINISH_ADDR, self.__class__.code_sentinelle ) - def run(self, addr=None): - if addr is None and self.options.address is None: - addr = self.entry_point - super(Sandbox_Linux_arml, self).run(addr) - def call(self, addr, *args, **kwargs): """ Direct call of the function at @addr, with arguments @args @addr: address of the target function @args: arguments """ - prepare_cb = kwargs.pop('prepare_cb', self.jitter.func_prepare_systemv) - super(self.__class__, self).call(prepare_cb, addr, *args) + prepare_cb = kwargs.pop("prepare_cb", self.jitter.func_prepare_systemv) + super(Sandbox_Linux_arml, self).call(prepare_cb, addr, *args) + + +class Sandbox_Linux_arml_shellcode(Sandbox): + CLS_ARCH = Arch_arml + CLS_OS = OS_Linux_shellcode + PROGRAM_PATH = "./program" + + def __init__(self, loc_db, options, custom_methods=None): + super(Sandbox_Linux_arml_shellcode, self).__init__( + loc_db, options, custom_methods + ) + self.libs = self.os.libs + self.entry_point = options.load_base_addr -class Sandbox_Linux_armtl(Sandbox, Arch_armtl, OS_Linux): + self.options = options + self.loc_db = loc_db - def __init__(self, loc_db, *args, **kwargs): - Sandbox.__init__(self, loc_db, *args, **kwargs) + # Arguments + self.argv = [self.PROGRAM_PATH] + if self.options.command_line: + self.argv += self.options.command_line + self.envp = self.options.environment_vars # Pre-stack some arguments if self.options.mimic_env: @@ -776,7 +676,7 @@ def __init__(self, loc_db, *args, **kwargs): argv_ptrs.append(ptr) # Round SP to 4 - self.jitter.cpu.SP = self.jitter.cpu.SP & ~ 3 + self.jitter.cpu.SP = self.jitter.cpu.SP & ~3 self.jitter.push_uint32_t(0) for ptr in reversed(env_ptrs): @@ -790,30 +690,51 @@ def __init__(self, loc_db, *args, **kwargs): # Set the runtime guard self.jitter.add_breakpoint( - self.CALL_FINISH_ADDR, - self.__class__.code_sentinelle + self.CALL_FINISH_ADDR, self.__class__.code_sentinelle ) - def run(self, addr=None): - if addr is None and self.options.address is None: - addr = self.entry_point - super(Sandbox_Linux_armtl, self).run(addr) - def call(self, addr, *args, **kwargs): """ Direct call of the function at @addr, with arguments @args @addr: address of the target function @args: arguments """ - prepare_cb = kwargs.pop('prepare_cb', self.jitter.func_prepare_systemv) - super(self.__class__, self).call(prepare_cb, addr, *args) + prepare_cb = kwargs.pop("prepare_cb", self.jitter.func_prepare_systemv) + super(Sandbox_Linux_arml_shellcode, self).call(prepare_cb, addr, *args) + + +class Sandbox_Linux_armb_shellcode(Sandbox_Linux_arml_shellcode): + CLS_ARCH = Arch_armb + CLS_OS = OS_Linux_shellcode + PROGRAM_PATH = "./program" + +class Sandbox_Linux_armb(Sandbox): + CLS_ARCH = Arch_armb + CLS_OS = OS_Linux + PROGRAM_PATH = "./program" + + +class Sandbox_Linux_aarch64l(Sandbox): + CLS_ARCH = Arch_aarch64l + CLS_OS = OS_Linux + PROGRAM_PATH = "./program" + def __init__(self, loc_db, options, custom_methods=None): + super(Sandbox_Linux_aarch64l, self).__init__(loc_db, options, custom_methods) + self.elf = self.os.elf + self.libs = self.os.libs -class Sandbox_Linux_mips32b(Sandbox, Arch_mips32b, OS_Linux): + self.entry_point = self.elf.Ehdr.entry + + self.options = options + self.loc_db = loc_db - def __init__(self, loc_db, *args, **kwargs): - Sandbox.__init__(self, loc_db, *args, **kwargs) + # Arguments + self.argv = [self.PROGRAM_PATH] + if self.options.command_line: + self.argv += self.options.command_line + self.envp = self.options.environment_vars # Pre-stack some arguments if self.options.mimic_env: @@ -834,73 +755,74 @@ def __init__(self, loc_db, *args, **kwargs): self.jitter.vm.set_mem(ptr, arg) argv_ptrs.append(ptr) - self.jitter.push_uint32_t(0) + self.jitter.push_uint64_t(0) for ptr in reversed(env_ptrs): - self.jitter.push_uint32_t(ptr) - self.jitter.push_uint32_t(0) + self.jitter.push_uint64_t(ptr) + self.jitter.push_uint64_t(0) for ptr in reversed(argv_ptrs): - self.jitter.push_uint32_t(ptr) - self.jitter.push_uint32_t(len(self.argv)) + self.jitter.push_uint64_t(ptr) + self.jitter.push_uint64_t(len(self.argv)) - self.jitter.cpu.RA = 0x1337beef + self.jitter.cpu.LR = self.CALL_FINISH_ADDR # Set the runtime guard self.jitter.add_breakpoint( - 0x1337beef, - self.__class__.code_sentinelle + self.CALL_FINISH_ADDR, self.__class__.code_sentinelle ) - def run(self, addr=None): - if addr is None and self.options.address is None: - addr = self.entry_point - super(Sandbox_Linux_mips32b, self).run(addr) - def call(self, addr, *args, **kwargs): - """ - Direct call of the function at @addr, with arguments @args - @addr: address of the target function - @args: arguments - """ - prepare_cb = kwargs.pop('prepare_cb', self.jitter.func_prepare_systemv) - super(self.__class__, self).call(prepare_cb, addr, *args) +class Sandbox_Linux_ppc32b(Sandbox): + CLS_ARCH = Arch_ppc32b + CLS_OS = OS_Linux + PROGRAM_PATH = "./program" + def __init__(self, loc_db, options, custom_methods=None): + super(Sandbox_Linux_ppc32b, self).__init__(loc_db, options, custom_methods) + self.elf = self.os.elf + self.libs = self.os.libs -class Sandbox_Linux_armb_str(Sandbox, Arch_armb, OS_Linux_str): + self.entry_point = self.elf.Ehdr.entry - def __init__(self, loc_db, *args, **kwargs): - Sandbox.__init__(self, loc_db, *args, **kwargs) + self.options = options + self.loc_db = loc_db - self.jitter.cpu.LR = self.CALL_FINISH_ADDR + self.jitter.push_uint32_t(self.CALL_FINISH_ADDR) # Set the runtime guard - self.jitter.add_breakpoint(self.CALL_FINISH_ADDR, self.__class__.code_sentinelle) - - def run(self, addr=None): - if addr is None and self.options.address is not None: - addr = int(self.options.address, 0) - super(Sandbox_Linux_armb_str, self).run(addr) - - -class Sandbox_Linux_arml_str(Sandbox, Arch_arml, OS_Linux_str): + self.jitter.add_breakpoint( + self.CALL_FINISH_ADDR, self.__class__.code_sentinelle + ) - def __init__(self, loc_db, *args, **kwargs): - Sandbox.__init__(self, loc_db, *args, **kwargs) + def call(self, addr, *args, **kwargs): + """ + Direct call of the function at @addr, with arguments @args + @addr: address of the target function + @args: arguments + """ + prepare_cb = kwargs.pop("prepare_cb", self.jitter.func_prepare_stdcall) + super(Sandbox_Linux_ppc32b, self).call(prepare_cb, addr, *args) - self.jitter.cpu.LR = self.CALL_FINISH_ADDR - # Set the runtime guard - self.jitter.add_breakpoint(self.CALL_FINISH_ADDR, self.__class__.code_sentinelle) +class Sandbox_Linux_x86_64(Sandbox): + CLS_ARCH = Arch_x86_64 + CLS_OS = OS_Linux + PROGRAM_PATH = "./program" - def run(self, addr=None): - if addr is None and self.options.address is not None: - addr = int(self.options.address, 0) - super(Sandbox_Linux_arml_str, self).run(addr) + def __init__(self, loc_db, options, custom_methods=None): + super(Sandbox_Linux_x86_64, self).__init__(loc_db, options, custom_methods) + self.elf = self.os.elf + self.libs = self.os.libs + self.entry_point = self.elf.Ehdr.entry -class Sandbox_Linux_aarch64l(Sandbox, Arch_aarch64l, OS_Linux): + self.options = options + self.loc_db = loc_db - def __init__(self, loc_db, *args, **kwargs): - Sandbox.__init__(self, loc_db, *args, **kwargs) + # Arguments + self.argv = [self.PROGRAM_PATH] + if self.options.command_line: + self.argv += self.options.command_line + self.envp = self.options.environment_vars # Pre-stack some arguments if self.options.mimic_env: @@ -908,19 +830,20 @@ def __init__(self, loc_db, *args, **kwargs): for env in self.envp: env = force_bytes(env) env += b"\x00" - self.jitter.cpu.SP -= len(env) - ptr = self.jitter.cpu.SP + self.jitter.cpu.RSP -= len(env) + ptr = self.jitter.cpu.RSP self.jitter.vm.set_mem(ptr, env) env_ptrs.append(ptr) argv_ptrs = [] for arg in self.argv: arg = force_bytes(arg) arg += b"\x00" - self.jitter.cpu.SP -= len(arg) - ptr = self.jitter.cpu.SP + self.jitter.cpu.RSP -= len(arg) + ptr = self.jitter.cpu.RSP self.jitter.vm.set_mem(ptr, arg) argv_ptrs.append(ptr) + self.jitter.push_uint64_t(self.CALL_FINISH_ADDR) self.jitter.push_uint64_t(0) for ptr in reversed(env_ptrs): self.jitter.push_uint64_t(ptr) @@ -928,45 +851,35 @@ def __init__(self, loc_db, *args, **kwargs): for ptr in reversed(argv_ptrs): self.jitter.push_uint64_t(ptr) self.jitter.push_uint64_t(len(self.argv)) - - self.jitter.cpu.LR = self.CALL_FINISH_ADDR + else: + self.jitter.push_uint64_t(self.CALL_FINISH_ADDR) # Set the runtime guard self.jitter.add_breakpoint( - self.CALL_FINISH_ADDR, - self.__class__.code_sentinelle + self.CALL_FINISH_ADDR, self.__class__.code_sentinelle ) - def run(self, addr=None): - if addr is None and self.options.address is None: - addr = self.entry_point - super(Sandbox_Linux_aarch64l, self).run(addr) - def call(self, addr, *args, **kwargs): - """ - Direct call of the function at @addr, with arguments @args - @addr: address of the target function - @args: arguments - """ - prepare_cb = kwargs.pop('prepare_cb', self.jitter.func_prepare_systemv) - super(self.__class__, self).call(prepare_cb, addr, *args) +class Sandbox_Linux_mips32b(Sandbox): + CLS_ARCH = Arch_mips32b + CLS_OS = OS_Linux + PROGRAM_PATH = "./program" -class Sandbox_Linux_ppc32b(Sandbox, Arch_ppc32b, OS_Linux): + def __init__(self, loc_db, options, custom_methods=None): + super(Sandbox_Linux_mips32b, self).__init__(loc_db, options, custom_methods) + self.elf = self.os.elf + self.libs = self.os.libs - STACK_SIZE = 0x10000 - STACK_BASE = 0xbfce0000 + self.entry_point = self.elf.Ehdr.entry - # The glue between the kernel and the ELF ABI on Linux/PowerPC is - # implemented in glibc/sysdeps/powerpc/powerpc32/dl-start.S, so we - # have to play the role of ld.so here. - def __init__(self, loc_db, *args, **kwargs): - super(Sandbox_Linux_ppc32b, self).__init__(loc_db, *args, **kwargs) + self.options = options + self.loc_db = loc_db - # Init stack - self.jitter.stack_size = self.STACK_SIZE - self.jitter.stack_base = self.STACK_BASE - self.jitter.init_stack() - self.jitter.cpu.R1 -= 8 + # Arguments + self.argv = [self.PROGRAM_PATH] + if self.options.command_line: + self.argv += self.options.command_line + self.envp = self.options.environment_vars # Pre-stack some arguments if self.options.mimic_env: @@ -974,60 +887,45 @@ def __init__(self, loc_db, *args, **kwargs): for env in self.envp: env = force_bytes(env) env += b"\x00" - self.jitter.cpu.R1 -= len(env) - ptr = self.jitter.cpu.R1 + self.jitter.cpu.SP -= len(env) + ptr = self.jitter.cpu.SP self.jitter.vm.set_mem(ptr, env) env_ptrs.append(ptr) argv_ptrs = [] for arg in self.argv: arg = force_bytes(arg) arg += b"\x00" - self.jitter.cpu.R1 -= len(arg) - ptr = self.jitter.cpu.R1 + self.jitter.cpu.SP -= len(arg) + ptr = self.jitter.cpu.SP self.jitter.vm.set_mem(ptr, arg) argv_ptrs.append(ptr) self.jitter.push_uint32_t(0) for ptr in reversed(env_ptrs): self.jitter.push_uint32_t(ptr) - self.jitter.cpu.R5 = self.jitter.cpu.R1 # envp self.jitter.push_uint32_t(0) for ptr in reversed(argv_ptrs): self.jitter.push_uint32_t(ptr) - self.jitter.cpu.R4 = self.jitter.cpu.R1 # argv - self.jitter.cpu.R3 = len(self.argv) # argc - self.jitter.push_uint32_t(self.jitter.cpu.R3) - - self.jitter.cpu.R6 = 0 # auxp - self.jitter.cpu.R7 = 0 # termination function - - # From the glibc, we should push a 0 here to distinguish a - # dynamically linked executable from a statically linked one. - # We actually do not do it and attempt to be somehow compatible - # with both types of executables. - #self.jitter.push_uint32_t(0) + self.jitter.push_uint32_t(len(self.argv)) - self.jitter.cpu.LR = self.CALL_FINISH_ADDR + self.jitter.cpu.RA = 0x1337BEEF # Set the runtime guard self.jitter.add_breakpoint( - self.CALL_FINISH_ADDR, - self.__class__.code_sentinelle + self.CALL_FINISH_ADDR, self.__class__.code_sentinelle ) - def run(self, addr=None): - """ - If addr is not set, use entrypoint - """ - if addr is None and self.options.address is None: - addr = self.entry_point - super(Sandbox_Linux_ppc32b, self).run(addr) - def call(self, addr, *args, **kwargs): """ Direct call of the function at @addr, with arguments @args @addr: address of the target function @args: arguments """ - prepare_cb = kwargs.pop('prepare_cb', self.jitter.func_prepare_systemv) - super(self.__class__, self).call(prepare_cb, addr, *args) + prepare_cb = kwargs.pop("prepare_cb", self.jitter.func_prepare_systemv) + super(Sandbox_Linux_mips32b, self).call(prepare_cb, addr, *args) + + +class Sandbox_Linux_mips32l(Sandbox_Linux_mips32b): + CLS_ARCH = Arch_mips32l + CLS_OS = OS_Linux + PROGRAM_PATH = "./program" diff --git a/test/arch/x86/qemu/testqemu.py b/test/arch/x86/qemu/testqemu.py index 6a516ac3b..a07d4b452 100644 --- a/test/arch/x86/qemu/testqemu.py +++ b/test/arch/x86/qemu/testqemu.py @@ -114,7 +114,6 @@ def xxx_puts(jitter): # Parse arguments parser = Sandbox_Linux_x86_32.parser(description="ELF sandboxer") -parser.add_argument("filename", help="ELF Filename") parser.add_argument("funcname", help="Targeted function's name") parser.add_argument("expected", help="Expected output") options = parser.parse_args() @@ -124,7 +123,7 @@ def xxx_puts(jitter): # Create sandbox loc_db = LocationDB() -sb = Sandbox_Linux_x86_32(loc_db, options.filename, options, globals()) +sb = Sandbox_Linux_x86_32(loc_db, options, globals()) try: addr = sb.elf.getsectionbyname(".symtab")[options.funcname].value except AttributeError: diff --git a/test/arch/x86/qemu/testqemu64.py b/test/arch/x86/qemu/testqemu64.py index b17abe669..186e4d1de 100644 --- a/test/arch/x86/qemu/testqemu64.py +++ b/test/arch/x86/qemu/testqemu64.py @@ -110,7 +110,6 @@ def xxx_puts(jitter): # Parse arguments parser = Sandbox_Linux_x86_64.parser(description="ELF sandboxer") -parser.add_argument("filename", help="ELF Filename") parser.add_argument("funcname", help="Targeted function's name") parser.add_argument("expected", help="Expected output") options = parser.parse_args() @@ -120,7 +119,7 @@ def xxx_puts(jitter): # Create sandbox loc_db = LocationDB() -sb = Sandbox_Linux_x86_64(loc_db, options.filename, options, globals()) +sb = Sandbox_Linux_x86_64(loc_db, options, globals()) try: addr = sb.elf.getsectionbyname(".symtab")[options.funcname].value except AttributeError: diff --git a/test/os_dep/linux/test_env.py b/test/os_dep/linux/test_env.py index 5bf3d2a06..a07b014c2 100644 --- a/test/os_dep/linux/test_env.py +++ b/test/os_dep/linux/test_env.py @@ -26,12 +26,11 @@ # Parse arguments parser = sandbox.parser(description="ELF sandboxer") -parser.add_argument("filename", help="ELF Filename") options = parser.parse_args(sys.argv[2:]) # Create sandbox loc_db = LocationDB() -sb = sandbox(loc_db, options.filename, options, globals()) +sb = sandbox(loc_db, options, globals()) # Run sb.run() diff --git a/test/test_all.py b/test/test_all.py index f0ac755e4..183072fed 100755 --- a/test/test_all.py +++ b/test/test_all.py @@ -797,7 +797,7 @@ class ExampleJitterNoPython(ExampleJitter): for script, dep in [(["x86_32.py", Example.get_sample("x86_32_sc.bin")], []), - (["arm.py", Example.get_sample("md5_arm"), "--mimic-env"], + (["sandbox_elf_arml.py", Example.get_sample("md5_arm"), "--mimic-env"], []), (["sandbox_elf_aarch64l.py", Example.get_sample("md5_aarch64l"), "--mimic-env"], @@ -809,9 +809,9 @@ class ExampleJitterNoPython(ExampleJitter): [test_msp430]), (["mips32.py", Example.get_sample("mips32_sc_l.bin"), "0"], [test_mips32l]), - (["arm_sc.py", "0", Example.get_sample("demo_arm_b.bin"), + (["arm_sc.py", Example.get_sample("demo_arm_b.bin"), "0", "b", "-a", "0"], [test_armb]), - (["arm_sc.py", "0", Example.get_sample("demo_arm_l.bin"), + (["arm_sc.py", Example.get_sample("demo_arm_l.bin"), "0", "l", "-a", "0"], [test_arml]), (["sandbox_call.py", Example.get_sample("md5_arm")], []), (["sandbox_pe_x86_32.py", Example.get_sample("x86_32_automod_2.bin")], From b4f63ce09a924bf7d01274a7e3c9b88186bfd2b3 Mon Sep 17 00:00:00 2001 From: Fabrice Desclaux Date: Tue, 13 Oct 2020 08:04:58 +0200 Subject: [PATCH 02/12] Space cleanup --- miasm/jitter/loader/pe.py | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/miasm/jitter/loader/pe.py b/miasm/jitter/loader/pe.py index 28010b748..837e1bc3b 100644 --- a/miasm/jitter/loader/pe.py +++ b/miasm/jitter/loader/pe.py @@ -23,14 +23,11 @@ def get_pe_dependencies(pe_obj): """Collect the shared libraries upon which this PE depends. - @pe_obj: pe object Returns a set of strings of DLL names. - Example: - - pe = miasm.analysis.binary.Container.from_string(buf) - deps = miasm.jitter.loader.pe.get_pe_dependencies(pe.executable) + container = miasm.analysis.binary.Container.from_string(buf) + deps = miasm.jitter.loader.pe.get_pe_dependencies(container.executable) assert sorted(deps)[0] == 'api-ms-win-core-appcompat-l1-1-0.dll' """ @@ -63,12 +60,12 @@ def get_import_address_pe(e): """Compute the addresses of imported symbols. @e: pe object Returns a dict mapping from tuple (dll name string, symbol name string) to set of virtual addresses. - + Example: - + pe = miasm.analysis.binary.Container.from_string(buf) imports = miasm.jitter.loader.pe.get_import_address_pe(pe.executable) - assert imports[('api-ms-win-core-rtlsupport-l1-1-0.dll', 'RtlCaptureStackBackTrace')] == {0x6b88a6d0} + assert imports[('api-ms-win-core-rtlsupport-l1-1-0.dll', 'RtlCaptureStackBackTrace')] == {0x6b88a6d0} """ import2addr = defaultdict(set) if e.DirImport.impdesc is None: From ee917c98da3d6655f02f8aefc575b7908dbbfb1b Mon Sep 17 00:00:00 2001 From: Fabrice Desclaux Date: Wed, 14 Oct 2020 13:51:48 +0200 Subject: [PATCH 03/12] Rename libimp -> Loader --- miasm/analysis/dse.py | 8 ++++---- miasm/analysis/sandbox.py | 12 ++++++------ miasm/jitter/loader/elf.py | 11 +++++++++-- miasm/jitter/loader/pe.py | 23 +++++++++++++++-------- miasm/jitter/loader/utils.py | 2 +- 5 files changed, 35 insertions(+), 21 deletions(-) diff --git a/miasm/analysis/dse.py b/miasm/analysis/dse.py index 5e6c4e8d9..6fee0a5f0 100644 --- a/miasm/analysis/dse.py +++ b/miasm/analysis/dse.py @@ -247,8 +247,8 @@ def add_handler(self, addr, callback): @callback: func(dse instance)""" self.handler[addr] = callback - def add_lib_handler(self, libimp, namespace): - """Add search for handler based on a @libimp libimp instance + def add_lib_handler(self, loader, namespace): + """Add search for handler based on a @loader Loader instance Known functions will be looked by {name}_symb or {name}_{ord}_symb in the @namespace """ @@ -258,14 +258,14 @@ def add_lib_handler(self, libimp, namespace): # lambda cannot contain statement def default_func(dse): - fname = libimp.fad2cname[dse.jitter.pc] + fname = loader.fad2cname[dse.jitter.pc] if isinstance(fname, tuple): fname = b"%s_%d_symb" % (force_bytes(fname[0]), fname[1]) else: fname = b"%s_symb" % force_bytes(fname) raise RuntimeError("Symbolic stub '%s' not found" % fname) - for addr, fname in viewitems(libimp.fad2cname): + for addr, fname in viewitems(loader.fad2cname): if isinstance(fname, tuple): fname = b"%s_%d_symb" % (force_bytes(fname[0]), fname[1]) else: diff --git a/miasm/analysis/sandbox.py b/miasm/analysis/sandbox.py index 0b5ef201c..47561d4e1 100644 --- a/miasm/analysis/sandbox.py +++ b/miasm/analysis/sandbox.py @@ -215,7 +215,7 @@ def __init__(self, jitter, options, custom_methods=None): vm_load_pe, vm_load_pe_libs, preload_pe, - libimp_pe, + LoaderWindows, vm_load_pe_and_dependencies, ) from miasm.os_dep import win_api_x86_32, win_api_x86_32_seh @@ -232,7 +232,7 @@ def __init__(self, jitter, options, custom_methods=None): self.jitter.init_stack() # Import manager - libs = libimp_pe() + libs = LoaderWindows() self.libs = libs win_api_x86_32.winobjs.runtime_dll = libs @@ -391,7 +391,7 @@ class OS_Linux(OS): STACK_BASE = 0x100000 def __init__(self, jitter, options, custom_methods=None): - from miasm.jitter.loader.elf import vm_load_elf, preload_elf, libimp_elf + from miasm.jitter.loader.elf import vm_load_elf, preload_elf, LoaderUnix from miasm.os_dep import linux_stdlib methods = linux_stdlib.__dict__ @@ -405,7 +405,7 @@ def __init__(self, jitter, options, custom_methods=None): self.jitter.init_stack() # Import manager - self.libs = libimp_elf() + self.libs = LoaderUnix() with open(options.filename, "rb") as fstream: self.elf = vm_load_elf( @@ -450,7 +450,7 @@ class OS_Linux_shellcode(OS): STACK_BASE = 0x100000 def __init__(self, jitter, options, custom_methods=None): - from miasm.jitter.loader.elf import vm_load_elf, preload_elf, libimp_elf + from miasm.jitter.loader.elf import vm_load_elf, preload_elf, LoaderUnix from miasm.os_dep import linux_stdlib methods = linux_stdlib.__dict__ @@ -464,7 +464,7 @@ def __init__(self, jitter, options, custom_methods=None): self.jitter.init_stack() # Import manager - self.libs = libimp_elf() + self.libs = LoaderUnix() data = open(options.filename, "rb").read() options.load_base_addr = int(options.load_base_addr, 0) diff --git a/miasm/jitter/loader/elf.py b/miasm/jitter/loader/elf.py index cb102c476..d8cd95b8c 100644 --- a/miasm/jitter/loader/elf.py +++ b/miasm/jitter/loader/elf.py @@ -1,4 +1,5 @@ import struct +import warnings from collections import defaultdict from future.utils import viewitems @@ -8,7 +9,7 @@ import miasm.loader.elf as elf_csts from miasm.jitter.csts import * -from miasm.jitter.loader.utils import canon_libname_libfunc, libimp +from miasm.jitter.loader.utils import canon_libname_libfunc, Loader from miasm.core.utils import force_str from miasm.core.interval import interval @@ -315,10 +316,16 @@ def vm_load_elf(vm, fdata, name="", base_addr=0, loc_db=None, apply_reloc=False, return elf -class libimp_elf(libimp): +class LoaderUnix(Loader): pass +class libimp_elf(LoaderUnix): + def __init__(self, *args, **kwargs): + warnings.warn("DEPRECATION WARNING: Use LoaderUnix instead of limimb_elf") + super(limbimp_elf, self).__init__(*args, **kwargs) + + # machine, size, sex -> arch_name ELF_machine = {(elf_csts.EM_ARM, 32, elf_csts.ELFDATA2LSB): "arml", (elf_csts.EM_ARM, 32, elf_csts.ELFDATA2MSB): "armb", diff --git a/miasm/jitter/loader/pe.py b/miasm/jitter/loader/pe.py index 837e1bc3b..524301265 100644 --- a/miasm/jitter/loader/pe.py +++ b/miasm/jitter/loader/pe.py @@ -2,6 +2,7 @@ import os import struct import logging +import warnings from collections import defaultdict from future.utils import viewitems, viewvalues @@ -11,7 +12,7 @@ from miasm.loader import * from miasm.jitter.csts import * -from miasm.jitter.loader.utils import canon_libname_libfunc, libimp +from miasm.jitter.loader.utils import canon_libname_libfunc, Loader from miasm.core.utils import force_str log = logging.getLogger('loader_pe') @@ -88,10 +89,10 @@ def get_import_address_pe(e): def preload_pe(vm, e, runtime_lib, patch_vm_imp=True): - fa = get_import_address_pe(e) + import_information = get_import_address_pe(e) dyn_funcs = {} - # log.debug('imported funcs: %s' % fa) - for (libname, libfunc), ads in viewitems(fa): + # log.debug('imported funcs: %s' % import_information) + for (libname, libfunc), ads in viewitems(import_information): for ad in ads: libname = force_str(libname) ad_base_lib = runtime_lib.lib_get_add_base(libname) @@ -293,7 +294,7 @@ def vm_load_pe_lib(vm, fname_in, libs, lib_path_base, **kargs): """Call vm_load_pe on @fname_in and update @libs accordingly @vm: VmMngr instance @fname_in: library name - @libs: libimp_pe instance + @libs: LoaderWindows instance @lib_path_base: DLLs relative path Return the corresponding PE instance Extra arguments are passed to vm_load_pe @@ -312,7 +313,7 @@ def vm_load_pe_libs(vm, libs_name, libs, lib_path_base, **kargs): """Call vm_load_pe_lib on each @libs_name filename @vm: VmMngr instance @libs_name: list of str - @libs: libimp_pe instance + @libs: LoaderWindows instance @lib_path_base: (optional) DLLs relative path Return a dictionary Filename -> PE instances Extra arguments are passed to vm_load_pe_lib @@ -418,10 +419,10 @@ def vm2pe(myjit, fname, libs=None, e_orig=None, return mye -class libimp_pe(libimp): +class LoaderWindows(Loader): def __init__(self, *args, **kwargs): - super(libimp_pe, self).__init__(*args, **kwargs) + super(LoaderWindows, self).__init__(*args, **kwargs) # dependency -> redirector self.created_redirected_imports = {} @@ -579,6 +580,12 @@ def gen_new_lib(self, target_pe, filter_import=lambda peobj, ad: True, **kwargs) return new_lib +class limbimp_pe(LoaderWindows): + def __init__(self, *args, **kwargs): + warnings.warn("DEPRECATION WARNING: Use LoaderWindows instead of limimb_pe") + super(limbimp_pe, self).__init__(*args, **kwargs) + + def vm_load_pe_and_dependencies(vm, fname, name2module, runtime_lib, lib_path_base, **kwargs): """Load a binary and all its dependencies. Returns a dictionary containing diff --git a/miasm/jitter/loader/utils.py b/miasm/jitter/loader/utils.py index 73809141f..4cd08b13f 100644 --- a/miasm/jitter/loader/utils.py +++ b/miasm/jitter/loader/utils.py @@ -21,7 +21,7 @@ def canon_libname_libfunc(libname, libfunc): return "%s_%s" % (dn, libfunc) -class libimp(object): +class Loader(object): def __init__(self, lib_base_ad=0x71111000, **kargs): self.name2off = {} From ad9a600ca02a02a00b65b1829b84cfe1a1f8d657 Mon Sep 17 00:00:00 2001 From: Fabrice Desclaux Date: Wed, 14 Oct 2020 14:33:21 +0200 Subject: [PATCH 04/12] Rename libs -> loader --- example/jitter/unpack_upx.py | 6 ++-- example/symbol_exec/dse_crackme.py | 2 +- miasm/analysis/sandbox.py | 51 +++++++++++++++++------------- miasm/jitter/loader/pe.py | 28 ++++++++-------- 4 files changed, 47 insertions(+), 40 deletions(-) diff --git a/example/jitter/unpack_upx.py b/example/jitter/unpack_upx.py index dbcbe0799..a75e9a797 100644 --- a/example/jitter/unpack_upx.py +++ b/example/jitter/unpack_upx.py @@ -25,7 +25,7 @@ def kernel32_GetProcAddress(jitter): # Get the generated address of the library, and store it in memory to # dst_ad - ad = sb.libs.lib_get_add_func(args.libbase, fname, dst_ad) + ad = sb.loader.lib_get_add_func(args.libbase, fname, dst_ad) # Add a breakpoint in case of a call on the resolved function # NOTE: never happens in UPX, just for skeleton jitter.handle_function(ad) @@ -108,7 +108,7 @@ def stop(jitter): # vm2pe will: # - set the new entry point to the current address (ie, the OEP) # - dump each section from the virtual memory into the new PE -# - use `sb.libs` to generate a new import directory, and use it in the new PE +# - use `sb.loader` to generate a new import directory, and use it in the new PE # - save the resulting PE in `out_fname` -vm2pe(sb.jitter, out_fname, libs=sb.libs, e_orig=sb.pe) +vm2pe(sb.jitter, out_fname, loader=sb.loader, e_orig=sb.pe) diff --git a/example/symbol_exec/dse_crackme.py b/example/symbol_exec/dse_crackme.py index 14d1d94dc..7aa7c2eec 100644 --- a/example/symbol_exec/dse_crackme.py +++ b/example/symbol_exec/dse_crackme.py @@ -260,7 +260,7 @@ def xxx_puts_symb(dse): dse.cur_solver.add(z3_file_size < 0x10) # Register symbolic stubs for extern functions (xxx_puts_symb, ...) -dse.add_lib_handler(sb.libs, globals()) +dse.add_lib_handler(sb.loader, globals()) # Automatic exploration of solution diff --git a/miasm/analysis/sandbox.py b/miasm/analysis/sandbox.py index 47561d4e1..8a27c2d86 100644 --- a/miasm/analysis/sandbox.py +++ b/miasm/analysis/sandbox.py @@ -3,6 +3,7 @@ import os import logging +import warnings from argparse import ArgumentParser from future.utils import viewitems, viewvalues @@ -80,6 +81,12 @@ def update_parser(cls, parser): cls.CLS_ARCH.update_parser(parser) cls.CLS_OS.update_parser(parser) + def get_libs(self): + warnings.warn("Use loader instead of libs") + return self.loader + + libs = property(get_libs) + @classmethod def parser(cls, *args, **kwargs): """ @@ -232,9 +239,9 @@ def __init__(self, jitter, options, custom_methods=None): self.jitter.init_stack() # Import manager - libs = LoaderWindows() - self.libs = libs - win_api_x86_32.winobjs.runtime_dll = libs + loader = LoaderWindows() + self.loader = loader + win_api_x86_32.winobjs.runtime_dll = loader self.name2module = {} fname_basename = os.path.basename(options.filename).lower() @@ -259,7 +266,7 @@ def __init__(self, jitter, options, custom_methods=None): vm_load_pe_libs( self.jitter.vm, self.LOADED_DLLS, - libs, + loader, self.PATH_DLLS, winobjs=win_api_x86_32.winobjs, ) @@ -267,23 +274,23 @@ def __init__(self, jitter, options, custom_methods=None): # Patch libs imports for pe in viewvalues(self.name2module): - preload_pe(self.jitter.vm, pe, libs) + preload_pe(self.jitter.vm, pe, loader) if options.dependencies: vm_load_pe_and_dependencies( self.jitter.vm, fname_basename, self.name2module, - libs, + loader, self.PATH_DLLS, winobjs=win_api_x86_32.winobjs, ) # Fix pe imports - preload_pe(self.jitter.vm, self.pe, libs) + preload_pe(self.jitter.vm, self.pe, loader) # Library calls handler - self.jitter.add_lib_handler(libs, methods) + self.jitter.add_lib_handler(loader, methods) # Manage SEH if options.use_windows_structs: @@ -334,7 +341,7 @@ class Sandbox_WinXP_x86_32(Sandbox): def __init__(self, loc_db, options, custom_methods=None): super(Sandbox_WinXP_x86_32, self).__init__(loc_db, options, custom_methods) self.pe = self.os.pe - self.libs = self.os.libs + self.loader = self.os.loader self.entry_point = self.pe.rva2virt(self.pe.Opthdr.AddressOfEntryPoint) @@ -362,7 +369,7 @@ class Sandbox_WinXP_x86_64(Sandbox): def __init__(self, loc_db, options, custom_methods=None): super(Sandbox_WinXP_x86_64, self).__init__(loc_db, options, custom_methods) self.pe = self.os.pe - self.libs = self.os.libs + self.loader = self.os.loader self.entry_point = self.pe.rva2virt(self.pe.Opthdr.AddressOfEntryPoint) @@ -405,18 +412,18 @@ def __init__(self, jitter, options, custom_methods=None): self.jitter.init_stack() # Import manager - self.libs = LoaderUnix() + self.loader = LoaderUnix() with open(options.filename, "rb") as fstream: self.elf = vm_load_elf( self.jitter.vm, fstream.read(), name=options.filename, ) - preload_elf(self.jitter.vm, self.elf, self.libs) + preload_elf(self.jitter.vm, self.elf, self.loader) self.entry_point = self.elf.Ehdr.entry # Library calls handler - self.jitter.add_lib_handler(self.libs, methods) + self.jitter.add_lib_handler(self.loader, methods) linux_stdlib.ABORT_ADDR = self.CALL_FINISH_ADDR @classmethod @@ -464,7 +471,7 @@ def __init__(self, jitter, options, custom_methods=None): self.jitter.init_stack() # Import manager - self.libs = LoaderUnix() + self.loader = LoaderUnix() data = open(options.filename, "rb").read() options.load_base_addr = int(options.load_base_addr, 0) @@ -473,7 +480,7 @@ def __init__(self, jitter, options, custom_methods=None): ) # Library calls handler - self.jitter.add_lib_handler(self.libs, methods) + self.jitter.add_lib_handler(self.loader, methods) linux_stdlib.ABORT_ADDR = self.CALL_FINISH_ADDR @classmethod @@ -508,7 +515,7 @@ class Sandbox_Linux_x86_32(Sandbox): def __init__(self, loc_db, options, custom_methods=None): super(Sandbox_Linux_x86_32, self).__init__(loc_db, options, custom_methods) self.elf = self.os.elf - self.libs = self.os.libs + self.loader = self.os.loader self.entry_point = self.elf.Ehdr.entry @@ -574,7 +581,7 @@ class Sandbox_Linux_arml(Sandbox): def __init__(self, loc_db, options, custom_methods=None): super(Sandbox_Linux_arml, self).__init__(loc_db, options, custom_methods) self.elf = self.os.elf - self.libs = self.os.libs + self.loader = self.os.loader self.entry_point = self.elf.Ehdr.entry @@ -643,7 +650,7 @@ def __init__(self, loc_db, options, custom_methods=None): super(Sandbox_Linux_arml_shellcode, self).__init__( loc_db, options, custom_methods ) - self.libs = self.os.libs + self.loader = self.os.loader self.entry_point = options.load_base_addr @@ -723,7 +730,7 @@ class Sandbox_Linux_aarch64l(Sandbox): def __init__(self, loc_db, options, custom_methods=None): super(Sandbox_Linux_aarch64l, self).__init__(loc_db, options, custom_methods) self.elf = self.os.elf - self.libs = self.os.libs + self.loader = self.os.loader self.entry_point = self.elf.Ehdr.entry @@ -779,7 +786,7 @@ class Sandbox_Linux_ppc32b(Sandbox): def __init__(self, loc_db, options, custom_methods=None): super(Sandbox_Linux_ppc32b, self).__init__(loc_db, options, custom_methods) self.elf = self.os.elf - self.libs = self.os.libs + self.loader = self.os.loader self.entry_point = self.elf.Ehdr.entry @@ -811,7 +818,7 @@ class Sandbox_Linux_x86_64(Sandbox): def __init__(self, loc_db, options, custom_methods=None): super(Sandbox_Linux_x86_64, self).__init__(loc_db, options, custom_methods) self.elf = self.os.elf - self.libs = self.os.libs + self.loader = self.os.loader self.entry_point = self.elf.Ehdr.entry @@ -868,7 +875,7 @@ class Sandbox_Linux_mips32b(Sandbox): def __init__(self, loc_db, options, custom_methods=None): super(Sandbox_Linux_mips32b, self).__init__(loc_db, options, custom_methods) self.elf = self.os.elf - self.libs = self.os.libs + self.loader = self.os.loader self.entry_point = self.elf.Ehdr.entry diff --git a/miasm/jitter/loader/pe.py b/miasm/jitter/loader/pe.py index 524301265..6a7124c30 100644 --- a/miasm/jitter/loader/pe.py +++ b/miasm/jitter/loader/pe.py @@ -290,11 +290,11 @@ def vm_load_pe(vm, fdata, align_s=True, load_hdr=True, name="", winobjs=None, ** return pe -def vm_load_pe_lib(vm, fname_in, libs, lib_path_base, **kargs): - """Call vm_load_pe on @fname_in and update @libs accordingly +def vm_load_pe_lib(vm, fname_in, loader, lib_path_base, **kargs): + """Call vm_load_pe on @fname_in and update @loader accordingly @vm: VmMngr instance @fname_in: library name - @libs: LoaderWindows instance + @loader: LoaderWindows instance @lib_path_base: DLLs relative path Return the corresponding PE instance Extra arguments are passed to vm_load_pe @@ -305,15 +305,15 @@ def vm_load_pe_lib(vm, fname_in, libs, lib_path_base, **kargs): fname = os.path.join(lib_path_base, fname_in) with open(fname, "rb") as fstream: pe = vm_load_pe(vm, fstream.read(), name=fname_in, **kargs) - libs.add_export_lib(pe, fname_in) + loader.add_export_lib(pe, fname_in) return pe -def vm_load_pe_libs(vm, libs_name, libs, lib_path_base, **kargs): +def vm_load_pe_libs(vm, libs_name, loader, lib_path_base, **kargs): """Call vm_load_pe_lib on each @libs_name filename @vm: VmMngr instance @libs_name: list of str - @libs: LoaderWindows instance + @loader: LoaderWindows instance @lib_path_base: (optional) DLLs relative path Return a dictionary Filename -> PE instances Extra arguments are passed to vm_load_pe_lib @@ -321,17 +321,17 @@ def vm_load_pe_libs(vm, libs_name, libs, lib_path_base, **kargs): out = {} for fname in libs_name: assert isinstance(fname, str) - out[fname] = vm_load_pe_lib(vm, fname, libs, lib_path_base, **kargs) + out[fname] = vm_load_pe_lib(vm, fname, loader, lib_path_base, **kargs) return out -def vm_fix_imports_pe_libs(lib_imgs, libs, lib_path_base, +def vm_fix_imports_pe_libs(lib_imgs, loader, lib_path_base, patch_vm_imp=True, **kargs): for e in viewvalues(lib_imgs): - preload_pe(e, libs, patch_vm_imp) + preload_pe(e, loader, patch_vm_imp) -def vm2pe(myjit, fname, libs=None, e_orig=None, +def vm2pe(myjit, fname, loader=None, e_orig=None, min_addr=None, max_addr=None, min_section_offset=0x1000, img_base=None, added_funcs=None, **kwargs): @@ -379,15 +379,15 @@ def vm2pe(myjit, fname, libs=None, e_orig=None, addr=ad - mye.NThdr.ImageBase, data=all_mem[ad]['data']) first = False - if libs: + if loader: if added_funcs is not None: for addr, funcaddr in added_funcs: - libbase, dllname = libs.fad2info[funcaddr] - libs.lib_get_add_func(libbase, dllname, addr) + libbase, dllname = loader.fad2info[funcaddr] + loader.lib_get_add_func(libbase, dllname, addr) filter_import = kwargs.get( 'filter_import', lambda _, ad: mye.virt.is_addr_in(ad)) - new_dll = libs.gen_new_lib(mye, filter_import) + new_dll = loader.gen_new_lib(mye, filter_import) else: new_dll = {} From ab9350432b3bc33273d0f7b3c212e12137a558ab Mon Sep 17 00:00:00 2001 From: Fabrice Desclaux Date: Wed, 14 Oct 2020 14:39:50 +0200 Subject: [PATCH 05/12] Rename runtime_libs -> Loader --- miasm/analysis/sandbox.py | 2 +- miasm/jitter/loader/elf.py | 12 ++++++------ miasm/jitter/loader/pe.py | 30 +++++++++++++++--------------- miasm/os_dep/win_api_x86_32.py | 31 +++++++++++++++++++++---------- 4 files changed, 43 insertions(+), 32 deletions(-) diff --git a/miasm/analysis/sandbox.py b/miasm/analysis/sandbox.py index 8a27c2d86..4f7573607 100644 --- a/miasm/analysis/sandbox.py +++ b/miasm/analysis/sandbox.py @@ -241,7 +241,7 @@ def __init__(self, jitter, options, custom_methods=None): # Import manager loader = LoaderWindows() self.loader = loader - win_api_x86_32.winobjs.runtime_dll = loader + win_api_x86_32.winobjs.loader = loader self.name2module = {} fname_basename = os.path.basename(options.filename).lower() diff --git a/miasm/jitter/loader/elf.py b/miasm/jitter/loader/elf.py index d8cd95b8c..9aa11143a 100644 --- a/miasm/jitter/loader/elf.py +++ b/miasm/jitter/loader/elf.py @@ -33,17 +33,17 @@ def get_import_address_elf(e): return import2addr -def preload_elf(vm, e, runtime_lib, patch_vm_imp=True, loc_db=None): +def preload_elf(vm, e, loader, patch_vm_imp=True, loc_db=None): # XXX quick hack - fa = get_import_address_elf(e) + import_information = get_import_address_elf(e) dyn_funcs = {} - for (libname, libfunc), ads in viewitems(fa): + for (libname, libfunc), ads in viewitems(import_information): # Quick hack - if a symbol is already known, do not stub it if loc_db and loc_db.get_name_location(libfunc) is not None: continue for ad in ads: - ad_base_lib = runtime_lib.lib_get_add_base(libname) - ad_libfunc = runtime_lib.lib_get_add_func(ad_base_lib, libfunc, ad) + ad_base_lib = loader.lib_get_add_base(libname) + ad_libfunc = loader.lib_get_add_func(ad_base_lib, libfunc, ad) libname_s = canon_libname_libfunc(libname, libfunc) dyn_funcs[libname_s] = ad_libfunc @@ -56,7 +56,7 @@ def preload_elf(vm, e, runtime_lib, patch_vm_imp=True, loc_db=None): struct.pack(set_endianness + cstruct.size2type[e.size], ad_libfunc)) - return runtime_lib, dyn_funcs + return loader, dyn_funcs def fill_loc_db_with_symbols(elf, loc_db, base_addr=0): """Parse the miasm.loader's ELF @elf to extract symbols, and fill the LocationDB diff --git a/miasm/jitter/loader/pe.py b/miasm/jitter/loader/pe.py index 6a7124c30..b260e5315 100644 --- a/miasm/jitter/loader/pe.py +++ b/miasm/jitter/loader/pe.py @@ -88,15 +88,15 @@ def get_import_address_pe(e): return import2addr -def preload_pe(vm, e, runtime_lib, patch_vm_imp=True): +def preload_pe(vm, e, loader, patch_vm_imp=True): import_information = get_import_address_pe(e) dyn_funcs = {} # log.debug('imported funcs: %s' % import_information) for (libname, libfunc), ads in viewitems(import_information): for ad in ads: libname = force_str(libname) - ad_base_lib = runtime_lib.lib_get_add_base(libname) - ad_libfunc = runtime_lib.lib_get_add_func(ad_base_lib, libfunc, ad) + ad_base_lib = loader.lib_get_add_base(libname) + ad_libfunc = loader.lib_get_add_func(ad_base_lib, libfunc, ad) libname_s = canon_libname_libfunc(libname, libfunc) dyn_funcs[libname_s] = ad_libfunc @@ -328,7 +328,7 @@ def vm_load_pe_libs(vm, libs_name, loader, lib_path_base, **kargs): def vm_fix_imports_pe_libs(lib_imgs, loader, lib_path_base, patch_vm_imp=True, **kargs): for e in viewvalues(lib_imgs): - preload_pe(e, loader, patch_vm_imp) + preload_pe(e, loader, patch_vm_imp=patch_vm_imp) def vm2pe(myjit, fname, loader=None, e_orig=None, @@ -586,7 +586,7 @@ def __init__(self, *args, **kwargs): super(limbimp_pe, self).__init__(*args, **kwargs) -def vm_load_pe_and_dependencies(vm, fname, name2module, runtime_lib, +def vm_load_pe_and_dependencies(vm, fname, name2module, loader, lib_path_base, **kwargs): """Load a binary and all its dependencies. Returns a dictionary containing the association between binaries names and it's pe object @@ -595,7 +595,7 @@ def vm_load_pe_and_dependencies(vm, fname, name2module, runtime_lib, @fname: full path of the binary @name2module: dict containing association between name and pe object. Updated. - @runtime_lib: libimp instance + @loader: Loader instance @lib_path_base: directory of the libraries containing dependencies """ @@ -668,23 +668,23 @@ def vm_load_pe_and_dependencies(vm, fname, name2module, runtime_lib, continue ad = pe_obj.NThdr.ImageBase libad = ad - runtime_lib.name2off[dllname] = ad - runtime_lib.libbase2lastad[ad] = ad + 0x1 - runtime_lib.lib_imp2ad[ad] = {} - runtime_lib.lib_imp2dstad[ad] = {} - runtime_lib.libbase_ad += 0x1000 + loader.name2off[dllname] = ad + loader.libbase2lastad[ad] = ad + 0x1 + loader.lib_imp2ad[ad] = {} + loader.lib_imp2dstad[ad] = {} + loader.libbase_ad += 0x1000 for (dllname, imp_ord_or_name), addr in known_export_addresses.items(): - runtime_lib.add_function(dllname, imp_ord_or_name, addr) - libad = runtime_lib.name2off[dllname] - runtime_lib.lib_imp2ad[libad][imp_ord_or_name] = addr + loader.add_function(dllname, imp_ord_or_name, addr) + libad = loader.name2off[dllname] + loader.lib_imp2ad[libad][imp_ord_or_name] = addr assert not to_resolve for dllname, pe_obj in name2module.items(): if pe_obj is None: continue - preload_pe(vm, pe_obj, runtime_lib, patch_vm_imp=True) + preload_pe(vm, pe_obj, loader, patch_vm_imp=True) return name2module diff --git a/miasm/os_dep/win_api_x86_32.py b/miasm/os_dep/win_api_x86_32.py index 568a646d2..734666fb6 100644 --- a/miasm/os_dep/win_api_x86_32.py +++ b/miasm/os_dep/win_api_x86_32.py @@ -164,7 +164,7 @@ def __init__(self): self.windowlong_dw = 0x77700 self.module_cur_hwnd = 0x88800 self.module_file_nul = 0x999000 - self.runtime_dll = None + self.loader = None self.current_pe = None self.tls_index = 0xf self.tls_values = {} @@ -195,6 +195,17 @@ def __init__(self): second=11, microsecond=123456 ) + + def get_loader(self): + warnings.warn("Use loader instead of runtime_dll") + return self.loader + + def set_loader(self, loader): + warnings.warn("Use loader instead of runtime_dll") + self.loader = loader + + runtime_dll = property(get_loader, set_loader) + winobjs = c_winobjs() @@ -901,12 +912,12 @@ def kernel32_GetModuleFileName(jitter, funcname, set_str): if args.hmodule in [0, winobjs.hcurmodule]: p = winobjs.module_path[:] - elif (winobjs.runtime_dll and - args.hmodule in viewvalues(winobjs.runtime_dll.name2off)): + elif (winobjs.loader and + args.hmodule in viewvalues(winobjs.loader.name2off)): name_inv = dict( [ (x[1], x[0]) - for x in viewitems(winobjs.runtime_dll.name2off) + for x in viewitems(winobjs.loader.name2off) ] ) p = name_inv[args.hmodule] @@ -1018,7 +1029,7 @@ def kernel32_LoadLibrary(jitter, get_str): ret_ad, args = jitter.func_args_stdcall(["dllname"]) libname = get_str(args.dllname, 0x100) - ret = winobjs.runtime_dll.lib_get_add_base(libname) + ret = winobjs.loader.lib_get_add_base(libname) log.info("Loading %r ret 0x%x", libname, ret) jitter.func_ret_stdcall(ret_ad, ret) @@ -1037,7 +1048,7 @@ def kernel32_LoadLibraryEx(jitter, get_str): if args.hfile != 0: raise NotImplementedError("Untested case") libname = get_str(args.dllname, 0x100) - ret = winobjs.runtime_dll.lib_get_add_base(libname) + ret = winobjs.loader.lib_get_add_base(libname) log.info("Loading %r ret 0x%x", libname, ret) jitter.func_ret_stdcall(ret_ad, ret) @@ -1058,7 +1069,7 @@ def kernel32_GetProcAddress(jitter): if not fname: fname = None if fname is not None: - ad = winobjs.runtime_dll.lib_get_add_func(args.libbase, fname) + ad = winobjs.loader.lib_get_add_func(args.libbase, fname) else: ad = 0 log.info("GetProcAddress %r %r ret 0x%x", args.libbase, fname, ad) @@ -1072,7 +1083,7 @@ def kernel32_GetModuleHandle(jitter, funcname, get_str): if args.dllname: libname = get_str(args.dllname) if libname: - ret = winobjs.runtime_dll.lib_get_add_base(libname) + ret = winobjs.loader.lib_get_add_base(libname) else: log.warning('unknown module!') ret = 0 @@ -1978,7 +1989,7 @@ def ntdll_LdrLoadDll(jitter): s = get_win_str_w(jitter, p_src) libname = s.lower() - ad = winobjs.runtime_dll.lib_get_add_base(libname) + ad = winobjs.loader.lib_get_add_base(libname) log.info("Loading %r ret 0x%x", s, ad) jitter.vm.set_u32(args.modhandle, ad) @@ -1999,7 +2010,7 @@ def ntdll_LdrGetProcedureAddress(jitter): l1, l2, p_src = struct.unpack('HHI', jitter.vm.get_mem(args.pfname, 0x8)) fname = get_win_str_a(jitter, p_src) - ad = winobjs.runtime_dll.lib_get_add_func(args.libbase, fname) + ad = winobjs.loader.lib_get_add_func(args.libbase, fname) jitter.add_breakpoint(ad, jitter.handle_lib) jitter.vm.set_u32(args.p_ad, ad) From 28a50bf52344fe23a6f2f63b7a964dc77380bae1 Mon Sep 17 00:00:00 2001 From: Fabrice Desclaux Date: Wed, 14 Oct 2020 16:59:06 +0200 Subject: [PATCH 06/12] Add sandbox win10 with ApiSet Thanks to @w4kfu for the help on apiset ApiSet explained here: https://lucasg.github.io/2017/10/15/Api-set-resolution/ --- miasm/analysis/sandbox.py | 181 ++++++++++----- miasm/jitter/loader/pe.py | 60 ++++- miasm/os_dep/windows/__init__.py | 0 miasm/os_dep/windows/apiset/10.0.15063.0.json | 1 + miasm/os_dep/windows/apiset/__init__.py | 0 setup.py | 5 +- utils/apiset_to_json.py | 209 ++++++++++++++++++ 7 files changed, 396 insertions(+), 60 deletions(-) create mode 100644 miasm/os_dep/windows/__init__.py create mode 100644 miasm/os_dep/windows/apiset/10.0.15063.0.json create mode 100644 miasm/os_dep/windows/apiset/__init__.py create mode 100644 utils/apiset_to_json.py diff --git a/miasm/analysis/sandbox.py b/miasm/analysis/sandbox.py index 4f7573607..5f9ef81a0 100644 --- a/miasm/analysis/sandbox.py +++ b/miasm/analysis/sandbox.py @@ -217,34 +217,36 @@ class OS_WinXP32(OS): STACK_SIZE = 0x10000 STACK_BASE = 0x130000 - def __init__(self, jitter, options, custom_methods=None): - from miasm.jitter.loader.pe import ( - vm_load_pe, - vm_load_pe_libs, - preload_pe, - LoaderWindows, - vm_load_pe_and_dependencies, - ) - from miasm.os_dep import win_api_x86_32, win_api_x86_32_seh - - self.jitter = jitter - methods = dict( - (name, func) for name, func in viewitems(win_api_x86_32.__dict__) - ) - methods.update(custom_methods) - + def init_stack(self): # Init stack self.jitter.stack_size = self.STACK_SIZE self.jitter.stack_base = self.STACK_BASE self.jitter.init_stack() + def init_loader(self): + from miasm.jitter.loader.pe import LoaderWindows + from miasm.os_dep.win_api_x86_32 import winobjs + # Import manager loader = LoaderWindows() self.loader = loader - win_api_x86_32.winobjs.loader = loader + winobjs.loader = loader + + def use_windows_structs(self): + from miasm.os_dep import win_api_x86_32, win_api_x86_32_seh + + win_api_x86_32_seh.main_pe_name = self.fname_basename + win_api_x86_32_seh.main_pe = self.pe + win_api_x86_32.winobjs.hcurmodule = self.pe.NThdr.ImageBase + win_api_x86_32_seh.name2module = self.name2module + win_api_x86_32_seh.set_win_fs_0(self.jitter) + win_api_x86_32_seh.init_seh(self.jitter) + + def load_main_pe(self, options): + from miasm.jitter.loader.pe import vm_load_pe + from miasm.os_dep.win_api_x86_32 import winobjs self.name2module = {} - fname_basename = os.path.basename(options.filename).lower() # Load main pe with open(options.filename, "rb") as fstream: @@ -253,53 +255,77 @@ def __init__(self, jitter, options, custom_methods=None): fstream.read(), load_hdr=options.load_hdr, name=options.filename, - winobjs=win_api_x86_32.winobjs, - ) - self.name2module[fname_basename] = self.pe - - win_api_x86_32.winobjs.current_pe = self.pe - - # Load library - if options.loadbasedll: - # Load libs in memory - self.name2module.update( - vm_load_pe_libs( - self.jitter.vm, - self.LOADED_DLLS, - loader, - self.PATH_DLLS, - winobjs=win_api_x86_32.winobjs, - ) + winobjs=winobjs, ) + self.name2module[self.fname_basename] = self.pe + winobjs.current_pe = self.pe - # Patch libs imports - for pe in viewvalues(self.name2module): - preload_pe(self.jitter.vm, pe, loader) + def load_base_dll(self): + from miasm.os_dep.win_api_x86_32 import winobjs + from miasm.jitter.loader.pe import vm_load_pe_libs, preload_pe - if options.dependencies: - vm_load_pe_and_dependencies( + # Load libs in memory + self.name2module.update( + vm_load_pe_libs( self.jitter.vm, - fname_basename, - self.name2module, - loader, + self.LOADED_DLLS, + self.loader, self.PATH_DLLS, - winobjs=win_api_x86_32.winobjs, + winobjs=winobjs, ) + ) - # Fix pe imports - preload_pe(self.jitter.vm, self.pe, loader) + # Patch libs imports + for pe in viewvalues(self.name2module): + preload_pe(self.jitter.vm, pe, self.loader) + + def load_dependencies(self): + from miasm.os_dep.win_api_x86_32 import winobjs + from miasm.jitter.loader.pe import vm_load_pe_and_dependencies + + vm_load_pe_and_dependencies( + self.jitter.vm, + self.fname_basename, + self.name2module, + self.loader, + self.PATH_DLLS, + winobjs=winobjs, + ) + def set_call_handler(self, custom_methods): # Library calls handler - self.jitter.add_lib_handler(loader, methods) + from miasm.os_dep import win_api_x86_32 + + methods = dict( + (name, func) for name, func in viewitems(win_api_x86_32.__dict__) + ) + methods.update(custom_methods) + self.jitter.add_lib_handler(self.loader, methods) + + def fix_preload_pe(self): + # Fix pe imports + from miasm.jitter.loader.pe import preload_pe + + preload_pe(self.jitter.vm, self.pe, self.loader) + + def __init__(self, jitter, options, custom_methods=None): + self.fname_basename = os.path.basename(options.filename).lower() + self.jitter = jitter + + self.init_stack() + self.init_loader() + self.load_main_pe(options) + if options.loadbasedll: + self.load_base_dll() + if options.dependencies: + self.load_dependencies() + + self.fix_preload_pe() + self.set_call_handler(custom_methods) # Manage SEH if options.use_windows_structs: - win_api_x86_32_seh.main_pe_name = fname_basename - win_api_x86_32_seh.main_pe = self.pe - win_api_x86_32.winobjs.hcurmodule = self.pe.NThdr.ImageBase - win_api_x86_32_seh.name2module = self.name2module - win_api_x86_32_seh.set_win_fs_0(self.jitter) - win_api_x86_32_seh.init_seh(self.jitter) + self.use_windows_structs() @classmethod def update_parser(cls, parser): @@ -362,6 +388,26 @@ def call(self, addr, *args, **kwargs): super(Sandbox_WinXP_x86_32, self).call(prepare_cb, addr, *args) +class OS_Win10(OS_WinXP32): + VERSION = "10.0.15063.0" + + def init_loader(self): + from miasm.jitter.loader.pe import LoaderWindows + from miasm.os_dep.windows import apiset + from miasm.os_dep.win_api_x86_32 import winobjs + + from miasm.jitter.loader.pe import ApiSet + + basedir, _ = os.path.split(apiset.__file__) + apiset_file = os.path.join(basedir, "%s.json" % self.VERSION) + apiset = ApiSet(apiset_file) + + # Import manager + loader = LoaderWindows(apiset=apiset) + self.loader = loader + winobjs.loader = loader + + class Sandbox_WinXP_x86_64(Sandbox): CLS_ARCH = Arch_x86_64 CLS_OS = OS_WinXP32 @@ -390,6 +436,35 @@ def call(self, addr, *args, **kwargs): super(Sandbox_WinXP_x86_64, self).call(prepare_cb, addr, *args) +class Sandbox_Win10_x86_64(Sandbox): + CLS_ARCH = Arch_x86_64 + CLS_OS = OS_Win10 + + def __init__(self, loc_db, options, custom_methods=None): + super(Sandbox_Win10_x86_64, self).__init__(loc_db, options, custom_methods) + + self.pe = self.os.pe + self.loader = self.os.loader + + self.entry_point = self.pe.rva2virt(self.pe.Opthdr.AddressOfEntryPoint) + + self.options = options + self.loc_db = loc_db + + # Pre-stack return address + self.jitter.push_uint64_t(self.CALL_FINISH_ADDR) + self.jitter.add_breakpoint(self.CALL_FINISH_ADDR, self.code_sentinelle) + + def call(self, addr, *args, **kwargs): + """ + Direct call of the function at @addr, with arguments @args + @addr: address of the target function + @args: arguments + """ + prepare_cb = kwargs.pop("prepare_cb", self.jitter.func_prepare_stdcall) + super(Sandbox_Win10_x86_64, self).call(prepare_cb, addr, *args) + + class OS_Linux(OS): CALL_FINISH_ADDR = 0x13371ACC diff --git a/miasm/jitter/loader/pe.py b/miasm/jitter/loader/pe.py index b260e5315..bd322f137 100644 --- a/miasm/jitter/loader/pe.py +++ b/miasm/jitter/loader/pe.py @@ -1,6 +1,7 @@ from builtins import map import os import struct +import json import logging import warnings from collections import defaultdict @@ -92,17 +93,19 @@ def preload_pe(vm, e, loader, patch_vm_imp=True): import_information = get_import_address_pe(e) dyn_funcs = {} # log.debug('imported funcs: %s' % import_information) - for (libname, libfunc), ads in viewitems(import_information): + for (libname, funcname), ads in viewitems(import_information): for ad in ads: libname = force_str(libname) + if loader.apiset: + libname = loader.apiset.get_redirection(libname) ad_base_lib = loader.lib_get_add_base(libname) - ad_libfunc = loader.lib_get_add_func(ad_base_lib, libfunc, ad) + ad_funcname = loader.lib_get_add_func(ad_base_lib, funcname, ad) - libname_s = canon_libname_libfunc(libname, libfunc) - dyn_funcs[libname_s] = ad_libfunc + libname_s = canon_libname_libfunc(libname, funcname) + dyn_funcs[libname_s] = ad_funcname if patch_vm_imp: vm.set_mem( - ad, struct.pack(cstruct.size2type[e._wsize], ad_libfunc)) + ad, struct.pack(cstruct.size2type[e._wsize], ad_funcname)) return dyn_funcs @@ -421,10 +424,11 @@ def vm2pe(myjit, fname, loader=None, e_orig=None, class LoaderWindows(Loader): - def __init__(self, *args, **kwargs): + def __init__(self, *args, apiset=None, **kwargs): super(LoaderWindows, self).__init__(*args, **kwargs) # dependency -> redirector self.created_redirected_imports = {} + self.apiset = apiset def add_function(self, dllname, imp_ord_or_name, addr): @@ -699,3 +703,47 @@ def guess_arch(pe): """Return the architecture specified by the PE container @pe. If unknown, return None""" return PE_machine.get(pe.Coffhdr.machine, None) + + +class ApiSet(object): + def __init__(self, fname): + data = json.load(open(fname)) + self.version = data['version'] + self.hash_factor = data['hash_factor'] + self.redirections = data['redirections'] + self.hash_entries = data['hashes'] + + def compute_hash(self, apiset_lib_name): + """ + Hash func can be found in ntdll!ApiSetpSearchForApiSet + """ + hashk = 0 + for c in apiset_lib_name: + hashk = (hashk * self.hash_factor + ord(c)) & ((1 << 32) - 1) + return hashk + + def get_redirection(self, libname): + has_dll = libname.endswith(".dll") + if has_dll: + libname = libname[:-4] + if libname in self.redirections: + values = self.redirections[libname] + if len(values) == 1: + assert "" in values + log.warn("ApiSet %s => %s" % (libname, values[""])) + libname = values[""] + else: + libname_dll = "%s.dll" % libname + if libname_dll in values: + fds + else: + libname = values[""] + hash_to_search = self.compute_hash(libname) + if hash_to_search in self.hash_entries: + fds + + if has_dll and not libname.endswith('.dll'): + libname += ".dll" + elif not has_dll and libname.endswith('.dll'): + libname = libname[:-4] + return libname diff --git a/miasm/os_dep/windows/__init__.py b/miasm/os_dep/windows/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/miasm/os_dep/windows/apiset/10.0.15063.0.json b/miasm/os_dep/windows/apiset/10.0.15063.0.json new file mode 100644 index 000000000..a23825400 --- /dev/null +++ b/miasm/os_dep/windows/apiset/10.0.15063.0.json @@ -0,0 +1 @@ +{"version": "10.0.15063.0", "hashes": {"ext-ms-win-mobilecore-ie-textinput-l1-1": {"": ""}, "api-ms-win-security-base-ansi-l1-1": {"": "advapi32.dll"}, "ext-ms-win-kernel32-sidebyside-l1-1": {"": "kernel32.dll"}, "api-ms-win-composition-redirection-l1-1": {"": "dwmredir.dll"}, "api-ms-win-ntuser-sysparams-l1-1": {"": "user32.dll"}, "ext-ms-win-core-resourcepolicyserver-l1-1": {"": "resourcepolicyserver.dll"}, "api-ms-win-net-isolation-l1-1": {"": "firewallapi.dll"}, "api-ms-win-core-psm-app-l1-1": {"": "twinapi.appcore.dll"}, "api-ms-win-dx-d3dkmt-l1-1": {"": "gdi32.dll"}, "ext-ms-win-ntos-werkernel-l1-1": {"": "werkernel.sys"}, "ext-ms-win-mrmcorer-environment-l1-1": {"": ""}, "api-ms-win-security-logon-l1-1": {"": "advapi32.dll"}, "ext-ms-win-networking-xblconnectivity-l1-1": {"": ""}, "ext-ms-win-newdev-config-l1-1": {"": "newdev.dll"}, "ext-ms-win-security-deviceid-l1-1": {"": ""}, "api-ms-win-security-credentials-l1-1": {"": "sechost.dll"}, "api-ms-win-security-credentials-l2-1": {"": "sechost.dll"}, "ext-ms-win-tsf-inputsetting-l1-1": {"": "input.dll"}, "ext-ms-win-core-stateseparationext-l1-1": {"": ""}, "ext-ms-win-nfc-semgr-l1-1": {"": "semgrsvc.dll"}, "ext-ms-win-ntuser-misc-l1-1": {"": "user32.dll"}, "ext-ms-win-ntuser-misc-l1-2": {"": "user32.dll"}, "ext-ms-win-ntuser-misc-l1-3": {"": "user32.dll"}, "ext-ms-win-ntuser-misc-l1-5": {"": "user32.dll"}, "ext-ms-win-firewallapi-webproxy-l1-1": {"": "firewallapi.dll"}, "ext-ms-win-adsi-activeds-l1-1": {"": "activeds.dll"}, "ext-ms-win-smbshare-browser-l1-1": {"": "browser.dll"}, "ext-ms-win-net-netbios-l1-1": {"": "netbios.dll"}, "ext-ms-mf-pal-l2-1": {"": ""}, "ext-ms-win-kernel32-localization-l1-1": {"": "kernel32.dll"}, "ext-ms-win-ole32-oleautomation-l1-1": {"": "ole32.dll"}, "api-ms-win-core-heap-l1-1": {"": "kernelbase.dll"}, "api-ms-win-core-heap-l1-2": {"": "kernelbase.dll"}, "api-ms-win-core-heap-l2-1": {"": "kernelbase.dll"}, "api-ms-win-core-crt-l1-1": {"": "ntdll.dll"}, "api-ms-win-core-crt-l2-1": {"": "kernelbase.dll"}, "api-ms-win-appmodel-identity-l1-2": {"": "kernel.appcore.dll"}, "ext-ms-win-net-vpn-l1-1": {"": ""}, "ext-ms-win-ntuser-windowclass-l1-1": {"": "user32.dll"}, "ext-ms-win-dwmapidxgi-ext-l1-1": {"": "dwmapi.dll"}, "ext-ms-win-ntos-clipsp-l1-1": {"": "clipsp.sys"}, "api-ms-win-core-realtime-l1-1": {"": "kernelbase.dll"}, "ext-ms-win-wwaext-misc-l1-1": {"": "wwaext.dll"}, "ext-ms-win-onecore-shutdown-l1-1": {"": ""}, "ext-ms-win-base-rstrtmgr-l1-1": {"": "rstrtmgr.dll"}, "ext-ms-win-net-netshell-l1-1": {"": "netshell.dll"}, "ext-ms-win-domainjoin-netjoin-l1-1": {"": "netjoin.dll"}, "ext-ms-win-profile-extender-l1-1": {"": "userenv.dll"}, "ext-ms-win-els-elscore-l1-1": {"": "elscore.dll"}, "api-ms-win-core-namedpipe-l1-1": {"": "kernelbase.dll"}, "api-ms-win-core-namedpipe-l1-2": {"": "kernelbase.dll"}, "api-ms-win-core-psm-tc-l1-1": {"": "twinapi.appcore.dll"}, "api-ms-win-core-multipleproviderrouter-l1-1": {"": "mpr.dll"}, "ext-ms-win-gpapi-grouppolicy-l1-1": {"": "gpapi.dll"}, "api-ms-win-security-accesshlpr-l1-1": {"": "sechost.dll"}, "api-ms-win-core-shlwapi-legacy-l1-1": {"": "kernelbase.dll"}, "api-ms-win-crt-environment-l1-1": {"": "ucrtbase.dll"}, "ext-ms-win-ntuser-touch-hittest-l1-1": {"": "user32.dll"}, "api-ms-win-power-base-l1-1": {"": "powrprof.dll"}, "api-ms-win-core-normalization-l1-1": {"": "kernelbase.dll"}, "ext-ms-win-shell-efsadu-l1-1": {"": "efsadu.dll"}, "api-ms-win-core-localization-ansi-l1-1": {"": "kernel32.dll"}, "api-ms-win-rtcore-ntuser-synch-l1-1": {"": "user32.dll"}, "ext-ms-win-rtcore-ntuser-iam-l1-1": {"": "user32.dll"}, "ext-ms-win-printer-winspool-l1-1": {"": "winspool.drv"}, "ext-ms-win-gdi-gdiplus-l1-1": {"": "gdiplus.dll"}, "api-ms-win-eventing-controller-l1-1": {"": "sechost.dll"}, "ext-ms-win-gaming-xblgamesave-l1-1": {"": "xblgamesaveext.dll"}, "api-ms-win-shell-dataobject-l1-1": {"": "windows.storage.dll"}, "api-ms-win-security-grouppolicy-l1-1": {"": "kernelbase.dll"}, "api-ms-win-core-io-l1-1": {"": "kernel32.dll", "kernel32.dll": "kernelbase.dll"}, "ext-ms-win-advapi32-eventlog-ansi-l1-1": {"": "advapi32.dll"}, "api-ms-win-core-apiquery-l1-1": {"": "ntdll.dll"}, "api-ms-win-shcore-obsolete-l1-1": {"": "shcore.dll"}, "api-ms-win-core-appcompat-l1-1": {"": "kernelbase.dll"}, "api-ms-win-core-heap-obsolete-l1-1": {"": "kernel32.dll"}, "ext-ms-win-shell-directory-l1-1": {"": "windows.storage.dll"}, "ext-ms-win-ntos-ium-l1-1": {"": ""}, "ext-ms-win-xblauth-console-l1-1": {"": ""}, "ext-ms-win-kernel32-process-l1-1": {"": "kernel32.dll"}, "ext-ms-win-mpr-multipleproviderrouter-l1-1": {"": "mprext.dll"}, "api-ms-win-core-namespace-ansi-l1-1": {"": "kernel32.dll"}, "ext-ms-win-core-storelicensing-l1-1": {"": "licensemanagerapi.dll"}, "ext-ms-win-core-storelicensing-l1-2": {"": "licensemanagerapi.dll"}, "api-ms-win-core-psapi-ansi-l1-1": {"": "kernelbase.dll"}, "api-ms-win-mm-joystick-l1-1": {"": "winmmbase.dll"}, "ext-ms-win-appmodel-daxcore-l1-1": {"": "daxexec.dll"}, "ext-ms-win-security-tokenbrokerui-l1-1": {"": "tokenbrokerui.dll"}, "ext-ms-win-ntuser-rotationmanager-l1-1": {"": "user32.dll"}, "ext-ms-win-storage-sense-l1-1": {"": "storageusage.dll"}, "ext-ms-win-storage-sense-l1-2": {"": "storageusage.dll"}, "ext-ms-win-rtcore-ntuser-synch-ext-l1-1": {"": "user32.dll"}, "api-ms-win-eventing-obsolete-l1-1": {"": "sechost.dll"}, "api-ms-win-core-registryuserspecific-l1-1": {"": "kernelbase.dll"}, "api-ms-win-shell-shdirectory-l1-1": {"": "shcore.dll"}, "ext-ms-win-base-psapi-l1-1": {"": "psapi.dll"}, "ext-ms-win-cmd-util-l1-1": {"": "cmdext.dll"}, "ext-ms-win-rtcore-ntuser-dpi-l1-1": {"": "user32.dll"}, "ext-ms-win-rtcore-ntuser-dpi-l1-2": {"": "user32.dll"}, "ext-ms-win-session-wtsapi32-l1-1": {"": "wtsapi32.dll"}, "ext-ms-win-security-authbrokerui-l1-1": {"": "authbrokerui.dll"}, "api-ms-win-gaming-tcui-l1-1": {"": "gamingtcui.dll"}, "api-ms-win-core-textinput-client-l1-1": {"": "textinputframework.dll"}, "ext-ms-win-gdi-path-l1-1": {"": "gdi32full.dll"}, "api-ms-win-security-provider-l1-1": {"": "ntmarta.dll"}, "api-ms-win-downlevel-advapi32-l1-1": {"": "kernelbase.dll"}, "api-ms-win-downlevel-advapi32-l2-1": {"": "sechost.dll"}, "api-ms-win-downlevel-advapi32-l3-1": {"": "ntmarta.dll"}, "api-ms-win-downlevel-advapi32-l4-1": {"": "advapi32.dll"}, "ext-ms-win-xaml-controls-l1-1": {"": "windows.ui.xaml.phone.dll"}, "ext-ms-win-com-coml2-l1-1": {"": "coml2.dll"}, "api-ms-win-shcore-registry-l1-1": {"": "shcore.dll"}, "api-ms-win-security-trustee-l1-1": {"": "advapi32.dll"}, "ext-ms-win-kernel32-transacted-l1-1": {"": "kernel32.dll"}, "ext-ms-win-shell-shell32-l1-2": {"": "shell32.dll"}, "ext-ms-win-fsutilext-ifsutil-l1-1": {"": "fsutilext.dll"}, "api-ms-win-ntuser-rectangle-l1-1": {"": "user32.dll"}, "ext-ms-win-ntuser-windowstation-l1-1": {"": "user32.dll"}, "api-ms-win-core-job-l1-1": {"": "kernelbase.dll"}, "api-ms-win-core-job-l2-1": {"": "kernel32.dll"}, "api-ms-win-base-bootconfig-l1-1": {"": "advapi32.dll"}, "ext-ms-win-appmodel-appcontainerpath-l1-1": {"": ""}, "ext-ms-win-gui-uxinit-l1-1": {"": "uxinit.dll"}, "ext-ms-win-umpoext-umpo-l1-1": {"": "umpoext.dll"}, "ext-ms-win-security-chambers-l1-1": {"": ""}, "ext-ms-win-rtcore-ntuser-rawinput-l1-1": {"": "user32.dll"}, "ext-ms-win-ntuser-string-l1-1": {"": "user32.dll"}, "ext-ms-win-rtcore-gdi-devcaps-l1-1": {"": "gdi32.dll"}, "ext-ms-win-ntos-ksigningpolicy-l1-1": {"": ""}, "ext-ms-win-shell-aclui-l1-1": {"": "aclui.dll"}, "ext-ms-win-rtcore-ntuser-integration-l1-1": {"": "user32.dll"}, "ext-ms-win-advapi32-ntmarta-l1-1": {"": "advapi32.dll"}, "ext-ms-win-audiocore-pal-l1-2": {"": ""}, "ext-ms-win-secur32-translatename-l1-1": {"": "secur32.dll"}, "ext-ms-win-xboxlive-xboxnetapisvc-l1-1": {"": ""}, "ext-ms-win-kioskmode-config-l1-1": {"": "lockdownutil.dll"}, "ext-ms-win-wer-wct-l1-1": {"": "wer.dll"}, "ext-ms-win-advapi32-eventlog-l1-1": {"": "advapi32.dll"}, "ext-ms-win-shell-comctl32-window-l1-1": {"": "comctl32.dll"}, "ext-ms-onecore-dcomp-l1-1": {"": "dcomp.dll"}, "ext-ms-win-com-psmregister-l1-1": {"": "kernel.appcore.dll"}, "ext-ms-win-com-psmregister-l1-2": {"": "kernel.appcore.dll"}, "api-ms-win-core-winrt-roparameterizediid-l1-1": {"": "combase.dll"}, "ext-ms-win-msa-device-l1-1": {"": ""}, "ext-ms-win-wwaext-module-l1-1": {"": "wwaext.dll"}, "api-ms-win-shlwapi-ie-l1-1": {"": "shlwapi.dll"}, "ext-ms-win-rtcore-ntuser-inputintercept-l1-1": {"": "user32.dll"}, "api-ms-win-mm-time-l1-1": {"": "kernel32.dll"}, "ext-ms-win-mininput-cursorhost-l1-1": {"": "inputhost.dll"}, "api-ms-win-mm-playsound-l1-1": {"": "winmm.dll"}, "api-ms-win-input-ie-interactioncontext-l1-1": {"": ""}, "ext-ms-win-ntuser-rectangle-ext-l1-1": {"": "user32.dll"}, "api-ms-win-service-management-l1-1": {"": "sechost.dll"}, "api-ms-win-service-management-l2-1": {"": "sechost.dll"}, "api-ms-win-core-misc-l1-1": {"": "kernelbase.dll"}, "api-ms-win-appmodel-runtime-l1-1": {"": "kernel.appcore.dll"}, "ext-ms-win-clouddomainjoin-usermanagement-l1-1": {"": ""}, "ext-ms-win-session-usertoken-l1-1": {"": "wtsapi32.dll"}, "api-ms-win-ro-typeresolution-l1-1": {"": "wintypes.dll"}, "ext-ms-win-usp10-l1-1": {"": "gdi32full.dll"}, "ext-ms-win-kernel32-registry-l1-1": {"": "kernel32.dll"}, "api-ms-win-devices-query-l1-1": {"": "cfgmgr32.dll"}, "ext-ms-win-edputil-policy-l1-1": {"": "edputil.dll"}, "api-ms-win-rtcore-ole32-clipboard-l1-1": {"": "ole32.dll"}, "ext-ms-win-kernel32-package-l1-1": {"": "kernel.appcore.dll"}, "ext-ms-win-shell-exports-internal-l1-1": {"": "shell32.dll"}, "api-ms-win-crt-conio-l1-1": {"": "ucrtbase.dll"}, "ext-ms-win-advapi32-hwprof-l1-1": {"": "advapi32.dll"}, "ext-ms-win-smbshare-browserclient-l1-1": {"": "browcli.dll"}, "ext-ms-win-gdi-private-l1-1": {"": "gdi32full.dll"}, "ext-ms-win-rtcore-ntuser-sysparams-l1-1": {"": "user32.dll"}, "api-ms-win-core-biptcltapi-l1-1": {"": "twinapi.appcore.dll"}, "api-ms-win-core-processenvironment-ansi-l1-1": {"": "kernel32.dll"}, "api-ms-win-downlevel-shell32-l1-1": {"": "shcore.dll"}, "ext-ms-win-audiocore-policymanager-l1-1": {"": ""}, "ext-ms-win-security-slc-l1-1": {"": "slc.dll"}, "ext-ms-win-advapi32-encryptedfile-l1-1": {"": "advapi32.dll"}, "api-ms-win-rtcore-ntuser-private-l1-1": {"": "user32.dll"}, "ext-ms-win-sxs-oleautomation-l1-1": {"": "sxs.dll"}, "ext-ms-win-shell-comctl32-da-l1-1": {"": "comctl32.dll"}, "api-ms-win-core-console-ansi-l2-1": {"": "kernel32.dll"}, "api-ms-win-rtcore-ntuser-wmpointer-l1-1": {"": "user32.dll"}, "ext-ms-win-advapi32-idletask-l1-1": {"": "advapi32.dll"}, "api-ms-win-legacy-shlwapi-l1-1": {"": "kernelbase.dll"}, "api-ms-win-shell-namespace-l1-1": {"": "windows.storage.dll"}, "ext-ms-win-rtcore-minuser-host-l1-1": {"": ""}, "ext-ms-win-winrt-storage-l1-1": {"": "windows.storage.dll"}, "api-ms-win-core-psm-plm-l1-1": {"": "twinapi.appcore.dll"}, "api-ms-win-core-psm-plm-l1-2": {"": "twinapi.appcore.dll"}, "ext-ms-win-shell-comctl32-l1-1": {"": "comctl32.dll"}, "ext-ms-win-uiacore-l1-1": {"": "uiautomationcore.dll"}, "ext-ms-win-msiltcfg-msi-l1-1": {"": "msiltcfg.dll"}, "ext-ms-win-sensors-core-private-l1-1": {"": "sensorsnativeapi.dll"}, "api-ms-win-deprecated-apis-obsolete-l1-1": {"": "kernelbase.dll"}, "ext-ms-win-rtcore-ntuser-syscolors-l1-1": {"": "user32.dll"}, "api-ms-win-core-processthreads-l1-1": {"": "kernel32.dll", "kernel32.dll": "kernelbase.dll"}, "api-ms-win-security-cryptoapi-l1-1": {"": "cryptsp.dll"}, "ext-ms-win-authz-context-l1-1": {"": "authz.dll"}, "api-ms-win-core-libraryloader-private-l1-1": {"": "kernelbase.dll"}, "ext-ms-win-gdi-draw-l1-1": {"": "gdi32full.dll"}, "ext-ms-win-ras-rasdlg-l1-1": {"": "rasdlg.dll"}, "ext-ms-win-rometadata-dispenser-l1-1": {"": "rometadata.dll"}, "ext-ms-win-storage-iscsidsc-l1-1": {"": "iscsidsc.dll"}, "ext-ms-win-rtcore-ntuser-wmpointer-l1-1": {"": "user32.dll"}, "api-ms-win-eventlog-private-l1-1": {"": "advapi32.dll"}, "ext-ms-win-wsclient-devlicense-l1-1": {"": "wsclient.dll"}, "api-ms-win-core-sysinfo-l1-1": {"": "kernelbase.dll"}, "api-ms-win-core-sysinfo-l1-2": {"": "kernelbase.dll"}, "api-ms-win-core-sysinfo-l2-1": {"": "advapi32.dll"}, "ext-ms-win-security-appinfoext-l1-1": {"": "appinfoext.dll"}, "api-ms-win-core-datetime-l1-1": {"": "kernelbase.dll"}, "ext-ms-win-kernel32-windowserrorreporting-l1-1": {"": "kernel32.dll"}, "ext-ms-win-appmodel-datasharingservice-extensions-l1-1": {"": ""}, "ext-ms-win-gdi-render-l1-1": {"": "gdi32.dll"}, "api-ms-win-core-appinit-l1-1": {"": "kernel32.dll", "kernel32.dll": "kernelbase.dll"}, "ext-ms-onecore-phoneinfo-l1-1": {"": ""}, "ext-ms-win-gdi-rgn-l1-1": {"": "gdi32full.dll"}, "ext-ms-win-audiocore-coreaudiopolicymanager-l1-1": {"": "coreaudiopolicymanagerext.dll"}, "api-ms-win-crt-multibyte-l1-1": {"": "ucrtbase.dll"}, "ext-ms-onecore-orientation-l1-1": {"": ""}, "api-ms-win-core-util-l1-1": {"": "kernel32.dll", "kernel32.dll": "kernelbase.dll"}, "api-ms-win-crt-time-l1-1": {"": "ucrtbase.dll"}, "api-ms-onecoreuap-settingsync-status-l1-1": {"": "settingsynccore.dll"}, "ext-ms-win-kernelbase-processthread-l1-1": {"": "kernel32.dll"}, "ext-ms-win-devmgmt-dm-l1-1": {"": "dmapisetextimpldesktop.dll"}, "api-ms-win-core-com-midlproxystub-l1-1": {"": "combase.dll"}, "ext-ms-win-security-capauthz-l1-1": {"": "capauthz.dll"}, "ext-ms-win-ttlsext-eap-l1-1": {"": "ttlsext.dll"}, "ext-ms-win-ntuser-uicontext-ext-l1-1": {"": "user32.dll"}, "ext-ms-win-rtcore-ntuser-winevent-ext-l1-1": {"": "user32.dll"}, "api-ms-win-core-url-l1-1": {"": "kernelbase.dll"}, "ext-ms-win-rtcore-ntuser-cursor-l1-1": {"": "user32.dll"}, "ext-ms-win-mrmcorer-resmanager-l1-1": {"": "mrmcorer.dll"}, "ext-ms-win-coreui-l1-1": {"": ""}, "api-ms-win-core-atoms-l1-1": {"": "kernel32.dll"}, "ext-ms-win-security-kerberos-l1-1": {"": "kerberos.dll"}, "api-ms-win-crt-locale-l1-1": {"": "ucrtbase.dll"}, "api-ms-win-crt-heap-l1-1": {"": "ucrtbase.dll"}, "api-ms-win-shlwapi-winrt-storage-l1-1": {"": "shlwapi.dll"}, "ext-ms-win-reinfo-query-l1-1": {"": "reinfo.dll"}, "api-ms-win-service-core-ansi-l1-1": {"": "advapi32.dll"}, "api-ms-win-core-ums-l1-1": {"": "kernel32.dll"}, "api-ms-win-crt-stdio-l1-1": {"": "ucrtbase.dll"}, "ext-ms-win-security-certpoleng-l1-1": {"": "certpoleng.dll"}, "ext-ms-win-rastlsext-eap-l1-1": {"": "rastlsext.dll"}, "ext-ms-win-advapi32-msi-l1-1": {"": "advapi32.dll"}, "ext-ms-win-ro-typeresolution-l1-1": {"": "wintypes.dll"}, "ext-ms-win-odbc-odbc32-l1-1": {"": "odbc32.dll"}, "ext-ms-win-ntuser-mouse-l1-1": {"": "user32.dll"}, "api-ms-win-mm-mci-l1-1": {"": "winmm.dll"}, "ext-ms-win-advapi32-npusername-l1-1": {"": "advapi32.dll"}, "api-ms-win-appmodel-state-l1-1": {"": "kernel.appcore.dll"}, "api-ms-win-appmodel-state-l1-2": {"": "kernel.appcore.dll"}, "ext-ms-win-networking-wcmapi-l1-1": {"": "wcmapi.dll"}, "api-ms-win-storage-exports-internal-l1-1": {"": "windows.storage.dll"}, "ext-ms-win-core-psm-extendedresourcemode-l1-1": {"": ""}, "ext-ms-win-networking-wlanstorage-l1-1": {"": ""}, "ext-ms-win-ntuser-server-l1-1": {"": "user32.dll"}, "ext-ms-win-mininput-systeminputhost-l1-1": {"": "ism.dll"}, "api-ms-win-appmodel-runtime-internal-l1-1": {"": "kernel.appcore.dll"}, "api-ms-win-core-stringloader-l1-1": {"": "kernelbase.dll"}, "ext-ms-win-winrt-storage-removable-l1-1": {"": ""}, "api-ms-win-core-biplmapi-l1-1": {"": "twinapi.appcore.dll"}, "ext-ms-win-moderncore-win32k-base-ntuser-l1-1": {"": "win32kfull.sys"}, "ext-ms-win-samsrv-accountstore-l1-1": {"": "samsrv.dll"}, "api-ms-win-rtcore-ntuser-draw-l1-1": {"": "user32.dll"}, "api-ms-win-security-isolatedcontainer-l1-1": {"": "shcore.dll"}, "ext-ms-win-coreui-navshutdown-l1-1": {"": "navshutdown.dll"}, "ext-ms-win-wlan-onexui-l1-1": {"": "onexui.dll"}, "api-ms-win-core-com-private-l1-1": {"": "combase.dll"}, "ext-ms-win-kernel32-package-current-l1-1": {"": "kernel.appcore.dll"}, "api-ms-win-security-appcontainer-l1-1": {"": "kernelbase.dll"}, "api-ms-win-mm-misc-l1-1": {"": "winmmbase.dll"}, "api-ms-win-mm-misc-l2-1": {"": "winmm.dll"}, "api-ms-win-core-localization-obsolete-l1-1": {"": "kernelbase.dll"}, "api-ms-win-core-localization-obsolete-l1-2": {"": "kernelbase.dll"}, "api-ms-win-core-localization-obsolete-l1-3": {"": "kernelbase.dll"}, "ext-ms-win-ntuser-message-l1-1": {"": "user32.dll"}, "api-ms-win-core-processsecurity-l1-1": {"": "kernel32.dll", "kernel32.dll": "kernelbase.dll"}, "api-ms-win-devices-config-l1-1": {"": "cfgmgr32.dll"}, "api-ms-win-core-firmware-l1-1": {"": "kernel32.dll"}, "api-ms-win-mm-mme-l1-1": {"": "winmmbase.dll"}, "api-ms-win-core-string-obsolete-l1-1": {"": "kernel32.dll"}, "ext-ms-win-msa-ui-l1-1": {"": "msauserext.dll"}, "ext-ms-win-core-licensemanager-l1-1": {"": ""}, "api-ms-win-core-kernel32-legacy-ansi-l1-1": {"": "kernel32.dll"}, "ext-ms-win-eventing-tdh-ext-l1-1": {"": "tdh.dll"}, "api-ms-win-core-registry-private-l1-1": {"": "advapi32.dll"}, "ext-ms-win-rtcore-ntuser-window-ext-l1-1": {"": "user32.dll"}, "ext-ms-win-shell-embeddedmode-l1-1": {"": "embeddedmodesvcapi.dll"}, "api-ms-win-core-com-l1-1": {"": "combase.dll"}, "api-ms-win-core-com-l2-1": {"": "coml2.dll"}, "api-ms-win-core-version-l1-1": {"": "kernelbase.dll"}, "ext-ms-win-fs-clfs-l1-1": {"": "clfs.sys"}, "ext-ms-win-ras-rasapi32-l1-1": {"": "rasapi32.dll"}, "ext-ms-win-casting-device-l1-1": {"": ""}, "api-ms-win-base-util-l1-1": {"": "advapi32.dll"}, "ext-ms-win-kernel32-file-l1-1": {"": "kernel32.dll"}, "ext-ms-win-appcompat-aepic-l1-1": {"": "aepic.dll"}, "ext-ms-win-appmodel-viewscalefactor-l1-1": {"": ""}, "ext-ms-win-parentalcontrols-setup-l1-1": {"": "wpcapi.dll"}, "ext-ms-win-test-sys1-l1-1": {"": ""}, "ext-ms-win-session-wininit-l1-1": {"": "wininitext.dll"}, "api-ms-win-core-psapiansi-l1-1": {"": "kernelbase.dll"}, "ext-ms-win-casting-shell-l1-1": {"": "castingshellext.dll"}, "ext-ms-win-gaming-xinput-l1-1": {"": "xinputuap.dll"}, "ext-ms-win-test-sys2-l1-1": {"": ""}, "api-ms-win-security-sddl-ansi-l1-1": {"": "advapi32.dll"}, "ext-ms-win-security-efs-l1-1": {"": "efsext.dll"}, "ext-ms-win-wwan-wwapi-l1-1": {"": "wwapi.dll"}, "ext-ms-onecore-appchromeapi-l1-1": {"": ""}, "ext-ms-win-ntuser-windowstation-ansi-l1-1": {"": "user32.dll"}, "api-ms-win-shcore-stream-l1-1": {"": "shcore.dll"}, "ext-ms-win-raschapext-eap-l1-1": {"": "raschapext.dll"}, "api-ms-win-downlevel-kernel32-l1-1": {"": "kernelbase.dll"}, "api-ms-win-downlevel-kernel32-l2-1": {"": "kernel32.dll"}, "api-ms-win-appmodel-unlock-l1-1": {"": "kernel.appcore.dll"}, "ext-ms-win-hyperv-compute-l1-1": {"": "vmcompute.dll"}, "ext-ms-onecore-appmodel-plm-l1-1": {"": "execmodelclient.dll"}, "api-ms-win-deprecated-apis-advapi-l1-1": {"": ""}, "ext-ms-win-core-resourcemanager-l1-1": {"": "rmclient.dll"}, "ext-ms-win-core-resourcemanager-l1-2": {"": "rmclient.dll"}, "ext-ms-win-wer-xbox-l1-1": {"": ""}, "ext-ms-win-shell32-shellfolders-l1-1": {"": "windows.storage.dll"}, "ext-ms-win-shell32-shellfolders-l1-2": {"": "windows.storage.dll"}, "ext-ms-win-composition-init-l1-1": {"": "dwminit.dll"}, "ext-ms-win-ntos-kcminitcfg-l1-1": {"": "cmimcext.sys"}, "ext-ms-win-core-app-package-registration-l1-1": {"": ""}, "ext-ms-win-provisioning-platform-l1-1": {"": "provplatformdesktop.dll"}, "ext-ms-win-ole32-bindctx-l1-1": {"": "ole32.dll"}, "ext-ms-win-gdi-metafile-l1-1": {"": "gdi32full.dll"}, "ext-ms-win-direct2d-desktop-l1-1": {"": "direct2ddesktop.dll"}, "api-ms-win-crt-filesystem-l1-1": {"": "ucrtbase.dll"}, "ext-ms-win-wer-reporting-l1-1": {"": "wer.dll"}, "ext-ms-onecore-appmodel-emclient-l1-1": {"": ""}, "ext-ms-win-gui-ieui-l1-1": {"": "ieui.dll"}, "ext-ms-win-mm-msacm-l1-1": {"": "msacm32.dll"}, "ext-ms-win-devmgmt-policy-l1-1": {"": "policymanager.dll"}, "ext-ms-win-cloudap-tbal-l1-1": {"": ""}, "api-ms-win-core-windowserrorreporting-l1-1": {"": "kernelbase.dll"}, "ext-ms-win-biometrics-winbio-core-l1-1": {"": "winbio.dll"}, "api-ms-win-core-threadpool-l1-1": {"": "kernelbase.dll"}, "api-ms-win-core-threadpool-l1-2": {"": "kernelbase.dll"}, "ext-ms-win-msi-misc-l1-1": {"": "msi.dll"}, "api-ms-win-security-lsalookup-l1-1": {"": "sechost.dll"}, "api-ms-win-security-lsalookup-l2-1": {"": "advapi32.dll"}, "ext-ms-onecore-shlwapi-l1-1": {"": "shlwapi.dll"}, "ext-ms-win-ntuser-sysparams-ext-l1-1": {"": "user32.dll"}, "ext-ms-win-uwf-servicing-apis-l1-1": {"": "uwfservicingapi.dll"}, "api-ms-win-core-localregistry-l1-1": {"": "kernelbase.dll"}, "ext-ms-win-ntuser-dc-access-ext-l1-1": {"": "user32.dll"}, "api-ms-win-core-namespace-l1-1": {"": "kernelbase.dll"}, "api-ms-win-crt-math-l1-1": {"": "ucrtbase.dll"}, "api-ms-win-rtcore-ntuser-window-l1-1": {"": "user32.dll"}, "ext-ms-win-gdi-clipping-l1-1": {"": "gdi32full.dll"}, "ext-ms-win-shell-ntshrui-l1-1": {"": "ntshrui.dll"}, "api-ms-win-core-localization-l1-1": {"": "kernelbase.dll"}, "api-ms-win-core-localization-l1-2": {"": "kernelbase.dll"}, "api-ms-win-core-localization-l2-1": {"": "kernelbase.dll"}, "api-ms-win-shell-associations-l1-1": {"": "windows.storage.dll"}, "ext-ms-win-tsf-msctf-l1-1": {"": "msctf.dll"}, "api-ms-win-core-timezone-l1-1": {"": "kernelbase.dll"}, "ext-ms-win-mf-vfw-l1-1": {"": "mfvfw.dll"}, "ext-ms-net-vpn-soh-l1-1": {"": "vpnsohdesktop.dll"}, "ext-ms-win-net-cmvpn-l1-1": {"": "cmintegrator.dll"}, "ext-ms-win-mm-pehelper-l1-1": {"": "mf.dll"}, "ext-ms-win-cng-rng-l1-1": {"": "bcryptprimitives.dll"}, "ext-ms-win-shell-propsys-l1-1": {"": "propsys.dll"}, "ext-ms-win-appcompat-pcacli-l1-1": {"": "pcacli.dll"}, "api-ms-win-core-sidebyside-ansi-l1-1": {"": "kernel32.dll"}, "api-ms-win-core-winrt-robuffer-l1-1": {"": "wintypes.dll"}, "api-ms-win-core-marshal-l1-1": {"": "combase.dll"}, "api-ms-win-rtcore-ntuser-shell-l1-1": {"": "user32.dll"}, "ext-ms-win-pinenrollment-enrollment-l1-1": {"": "pinenrollmenthelper.dll"}, "ext-ms-win-appcompat-apphelp-l1-1": {"": "apphelp.dll"}, "ext-ms-win-moderncore-win32k-base-sysentry-l1-1": {"": "win32k.sys"}, "ext-ms-win-ntos-ucode-l1-1": {"": "ntosext.sys"}, "ext-ms-win-ci-xbox-l1-1": {"": ""}, "ext-ms-win-advapi32-shutdown-l1-1": {"": "advapi32.dll"}, "api-ms-win-core-memory-l1-1": {"": "kernelbase.dll"}, "api-ms-win-shcore-thread-l1-1": {"": "shcore.dll"}, "ext-ms-win-appmodel-restrictedappcontainer-internal-l1-1": {"": "kernel.appcore.dll"}, "api-ms-win-core-winrt-propertysetprivate-l1-1": {"": "wintypes.dll"}, "api-ms-win-core-processenvironment-l1-1": {"": "kernelbase.dll"}, "api-ms-win-core-processenvironment-l1-2": {"": "kernelbase.dll"}, "api-ms-win-security-cpwl-l1-1": {"": "advapi32.dll"}, "api-ms-win-ntuser-ie-window-l1-1": {"": "user32.dll"}, "api-ms-win-core-kernel32-private-l1-1": {"": "kernel32.dll"}, "api-ms-win-core-threadpool-legacy-l1-1": {"": "kernelbase.dll"}, "api-ms-win-core-quirks-l1-1": {"": "kernelbase.dll"}, "api-ms-win-security-lsalookup-ansi-l2-1": {"": "advapi32.dll"}, "ext-ms-win-ntuser-menu-l1-1": {"": "user32.dll"}, "api-ms-win-core-handle-l1-1": {"": "kernelbase.dll"}, "api-ms-win-deprecated-apis-legacy-l1-1": {"": ""}, "api-ms-win-deprecated-apis-legacy-l1-2": {"": ""}, "ext-ms-win-cluster-clusapi-l1-1": {"": "clusapi.dll"}, "ext-ms-win-rtcore-ntuser-console-l1-1": {"": ""}, "ext-ms-win-oleacc-l1-1": {"": "oleacc.dll"}, "api-ms-win-crt-string-l1-1": {"": "ucrtbase.dll"}, "ext-ms-win-gdi-wcs-l1-1": {"": "gdi32full.dll"}, "api-ms-win-dwmapi-l1-1": {"": "dwmapi.dll"}, "api-ms-win-winrt-search-folder-l1-1": {"": "windows.storage.search.dll"}, "ext-ms-win-moderncore-win32k-base-ntgdi-l1-1": {"": "win32kfull.sys"}, "api-ms-win-perf-legacy-l1-1": {"": "advapi32.dll"}, "api-ms-win-core-libraryloader-l1-1": {"": "kernelbase.dll"}, "api-ms-win-core-libraryloader-l1-2": {"": "kernelbase.dll"}, "api-ms-win-core-libraryloader-l2-1": {"": "kernelbase.dll"}, "ext-ms-win-branding-winbrand-l1-1": {"": "winbrand.dll"}, "ext-ms-win-setupapi-logging-l1-1": {"": "setupapi.dll"}, "ext-ms-win-ntuser-chartranslation-l1-1": {"": "user32.dll"}, "ext-ms-win-advapi32-safer-l1-1": {"": "advapi32.dll"}, "ext-ms-win-casting-receiver-l1-1": {"": ""}, "api-ms-win-core-psm-appnotify-l1-1": {"": "twinapi.appcore.dll"}, "api-ms-win-core-sidebyside-l1-1": {"": "kernelbase.dll"}, "ext-ms-win-shell-comdlg32-l1-1": {"": "comdlg32.dll"}, "ext-ms-win-core-dhcp6client-l1-1": {"": ""}, "ext-ms-win-ntos-ksr-l1-1": {"": ""}, "ext-ms-win-networking-ncsiuserprobe-l1-1": {"": ""}, "ext-ms-win-appmodel-deploymentvolumes-l1-1": {"": ""}, "ext-ms-win-security-credui-internal-l1-1": {"": "wincredui.dll"}, "api-ms-win-security-capability-l1-1": {"": "sechost.dll"}, "api-ms-win-shcore-path-l1-1": {"": "shcore.dll"}, "ext-ms-win-security-srp-l1-1": {"": "srpapi.dll"}, "ext-ms-win-shell32-shellcom-l1-1": {"": "windows.storage.dll"}, "ext-ms-win-security-capauthz-ext-l1-1": {"": ""}, "api-ms-win-http-time-l1-1": {"": "kernelbase.dll"}, "api-ms-win-shell-shellfolders-l1-1": {"": "windows.storage.dll"}, "api-ms-win-obsolete-localization-l1-1": {"": "kernelbase.dll"}, "ext-ms-win-uxtheme-themes-l1-1": {"": "uxtheme.dll"}, "ext-ms-win-wpn-phoneext-l1-1": {"": ""}, "api-ms-win-devices-swdevice-l1-1": {"": "cfgmgr32.dll"}, "api-ms-win-rtcore-ntuser-powermanagement-l1-1": {"": "user32.dll"}, "ext-ms-onecore-comp-dwmmonitor-l1-1": {"": ""}, "ext-ms-win-security-developerunlock-l1-1": {"": ""}, "api-ms-win-core-winrt-l1-1": {"": "combase.dll"}, "ext-ms-win-biometrics-winbio-l1-1": {"": "winbio.dll"}, "ext-ms-win-biometrics-winbio-l1-2": {"": "winbioext.dll"}, "ext-ms-win-biometrics-winbio-l1-3": {"": "winbioext.dll"}, "api-ms-win-security-lsapolicy-l1-1": {"": "sechost.dll"}, "api-ms-win-core-console-l1-1": {"": "kernelbase.dll"}, "api-ms-win-core-console-l2-1": {"": "kernelbase.dll"}, "api-ms-win-core-console-l3-1": {"": "kernelbase.dll"}, "api-ms-win-shcore-sysinfo-l1-1": {"": "shcore.dll"}, "ext-ms-win-ntdsapi-activedirectoryclient-l1-1": {"": "ntdsapi.dll"}, "ext-ms-win-kernel32-appcompat-l1-1": {"": "kernel32.dll"}, "ext-ms-win-gpsvc-grouppolicy-l1-1": {"": "gpsvc.dll"}, "api-ms-win-ngc-serialization-l1-1": {"": "ngckeyenum.dll"}, "ext-ms-win-net-httpproxyext-l1-1": {"": "httpprxc.dll"}, "api-ms-win-security-audit-l1-1": {"": "sechost.dll"}, "api-ms-win-crt-utility-l1-1": {"": "ucrtbase.dll"}, "ext-ms-win-advapi32-registry-l1-1": {"": "advapi32.dll"}, "api-ms-win-security-base-private-l1-1": {"": "kernelbase.dll"}, "ext-ms-onecore-mpc-input-l1-1": {"": "shellcompositor.dll"}, "ext-ms-win-ras-tapi32-l1-1": {"": "tapi32.dll"}, "ext-ms-win-shell-shdocvw-l1-1": {"": "shdocvw.dll"}, "ext-ms-win-rtcore-gdi-rgn-l1-1": {"": "gdi32.dll"}, "ext-ms-win-com-suspendresiliency-l1-1": {"": ""}, "ext-ms-win-winrt-storage-fileexplorer-l1-1": {"": ""}, "api-ms-win-core-timezone-private-l1-1": {"": "kernelbase.dll"}, "ext-ms-win-resources-deployment-l1-1": {"": "mrmdeploy.dll"}, "ext-ms-win-eventing-rundown-l1-1": {"": "etwrundown.dll"}, "ext-ms-win-rtcore-minuser-private-ext-l1-1": {"": ""}, "api-ms-win-downlevel-user32-l1-1": {"": "kernelbase.dll"}, "ext-ms-win-ntdsa-activedirectoryserver-l1-1": {"": "ntdsa.dll"}, "ext-ms-win-com-clbcatq-l1-1": {"": "clbcatq.dll"}, "ext-ms-win-ole32-ie-ext-l1-1": {"": "ole32.dll"}, "ext-ms-win-search-folder-l1-1": {"": "searchfolder.dll"}, "ext-ms-win-core-app-package-volume-l1-1": {"": ""}, "ext-ms-win-rtcore-ntuser-mininit-l1-1": {"": ""}, "api-ms-win-rtcore-ntuser-winevent-l1-1": {"": "user32.dll"}, "ext-ms-win-familysafety-childaccount-l1-1": {"": "familysafetyext.dll"}, "ext-ms-win-globalization-input-l1-1": {"": "globinputhost.dll"}, "ext-ms-win-appmodel-usercontext-l1-1": {"": ""}, "ext-ms-win-fsutilext-ulib-l1-1": {"": "fsutilext.dll"}, "api-ms-win-downlevel-version-l1-1": {"": "kernelbase.dll"}, "api-ms-win-core-synch-ansi-l1-1": {"": "kernel32.dll"}, "ext-ms-win-wnv-l1-1": {"": "wnv.sys"}, "api-ms-win-core-featurestaging-l1-1": {"": "shcore.dll"}, "api-ms-win-shcore-stream-winrt-l1-1": {"": "shcore.dll"}, "ext-ms-win-session-winsta-l1-1": {"": "winsta.dll"}, "ext-ms-win-rdr-davhlpr-l1-1": {"": "davhlpr.dll"}, "api-ms-win-crt-convert-l1-1": {"": "ucrtbase.dll"}, "api-ms-win-security-sddlparsecond-l1-1": {"": "sechost.dll"}, "ext-ms-win-dwmapi-ext-l1-1": {"": "dwmapi.dll"}, "ext-ms-win-globalization-collation-l1-1": {"": "globcollationhost.dll"}, "ext-ms-win-casting-lockscreen-l1-1": {"": "castingshellext.dll"}, "ext-ms-win-winrt-storage-win32broker-l1-1": {"": "windows.storage.winrt.dll"}, "ext-ms-win-mininput-inputhost-l1-1": {"": "inputhost.dll"}, "ext-ms-win-security-vaultcli-l1-1": {"": "vaultcli.dll"}, "api-ms-win-power-setting-l1-1": {"": "powrprof.dll"}, "ext-ms-win-fs-cscapi-l1-1": {"": "cscapi.dll"}, "api-ms-win-core-shutdown-l1-1": {"": "advapi32.dll"}, "ext-ms-win-ntuser-dialogbox-l1-1": {"": "user32.dll"}, "ext-ms-win-gdi-dc-l1-2": {"": "gdi32full.dll"}, "ext-ms-win-gaming-gamechatoverlay-l1-1": {"": "gamechatoverlayext.dll"}, "ext-ms-win-deployment-productenumerator-l1-1": {"": "productenumerator.dll"}, "ext-ms-onecore-shellremindersapi-l1-1": {"": ""}, "api-ms-win-security-provider-ansi-l1-1": {"": "advapi32.dll"}, "ext-ms-win-spinf-inf-l1-1": {"": "spinf.dll"}, "ext-ms-win-dx-ddraw-l1-1": {"": "ddraw.dll"}, "ext-ms-win-mm-wmvcore-l1-1": {"": "wmvcore.dll"}, "ext-ms-onecore-spectrumsyncclient-l1-1": {"": "spectrumsyncclient.dll"}, "ext-ms-win-authz-remote-l1-1": {"": "logoncli.dll"}, "api-ms-win-composition-windowmanager-l1-1": {"": "udwm.dll"}, "ext-ms-onecore-appmodel-tdlmigration-l1-1": {"": "tdlmigration.dll"}, "api-ms-win-core-toolhelp-l1-1": {"": "kernel32.dll"}, "ext-ms-win-ntuser-caret-l1-1": {"": "user32.dll"}, "api-ms-win-ntuser-ie-message-l1-1": {"": "user32.dll"}, "ext-ms-win-imm-l1-1": {"": "imm32.dll"}, "api-ms-win-eventing-tdh-l1-1": {"": "tdh.dll", "tdh.dll": "mintdh.dll"}, "api-ms-win-core-comm-l1-1": {"": "kernelbase.dll"}, "api-ms-win-core-psm-rtimer-l1-1": {"": "twinapi.appcore.dll"}, "api-ms-win-core-delayload-l1-1": {"": "kernelbase.dll"}, "ext-ms-win-wer-ui-l1-1": {"": "werui.dll"}, "ext-ms-win-ntuser-keyboard-l1-1": {"": "user32.dll"}, "ext-ms-win-ntuser-keyboard-l1-2": {"": "user32.dll"}, "ext-ms-win-ntuser-keyboard-l1-3": {"": "user32.dll"}, "ext-ms-win-printer-prntvpt-l1-1": {"": "prntvpt.dll"}, "ext-ms-win-eventing-pdh-l1-1": {"": "pdh.dll"}, "ext-ms-win-bluetooth-apis-private-l1-1": {"": "bluetoothapis.dll"}, "api-ms-win-crt-private-l1-1": {"": "ucrtbase.dll"}, "ext-ms-win-gdi-print-l1-1": {"": "gdi32full.dll"}, "ext-ms-win-bluetooth-apis-l1-1": {"": "bluetoothapis.dll"}, "ext-ms-win-rpc-firewallportuse-l1-1": {"": "rpcrtremote.dll"}, "ext-ms-win-wlan-scard-l1-1": {"": "winscard.dll"}, "ext-ms-win-ras-rasman-l1-1": {"": "rasman.dll"}, "ext-ms-win-winrt-networking-connectivity-l1-1": {"": ""}, "ext-ms-win-msa-user-l1-1": {"": "msauserext.dll"}, "api-ms-win-eventing-consumer-l1-1": {"": "sechost.dll"}, "api-ms-win-rtcore-minuser-private-l1-1": {"": ""}, "api-ms-win-core-profile-l1-1": {"": "kernelbase.dll"}, "ext-ms-onecore-appmodel-emsvcs-l1-1": {"": ""}, "api-ms-win-core-debug-minidump-l1-1": {"": "dbgcore.dll"}, "ext-ms-win-net-nfdapi-l1-1": {"": "ndfapi.dll"}, "api-ms-win-core-namedpipe-ansi-l1-1": {"": "kernel32.dll"}, "api-ms-win-coreui-secruntime-l1-1": {"": ""}, "api-ms-win-core-shlwapi-obsolete-l1-1": {"": "kernelbase.dll"}, "api-ms-win-core-shlwapi-obsolete-l1-2": {"": "kernelbase.dll"}, "api-ms-win-core-processtopology-l1-1": {"": "kernelbase.dll"}, "api-ms-win-core-processtopology-l1-2": {"": "kernelbase.dll"}, "ext-ms-win-shell-shlwapi-l1-1": {"": "shlwapi.dll"}, "ext-ms-win-shell-shlwapi-l1-2": {"": "shlwapi.dll"}, "ext-ms-win-media-avi-l1-1": {"": "avifil32.dll"}, "api-ms-win-core-file-l1-1": {"": "kernelbase.dll"}, "api-ms-win-core-file-l1-2": {"": "kernelbase.dll"}, "api-ms-win-core-file-l2-1": {"": "kernelbase.dll"}, "api-ms-win-networking-interfacecontexts-l1-1": {"": "ondemandconnroutehelper.dll"}, "ext-ms-win-wrp-sfc-l1-1": {"": "sfc.dll"}, "ext-ms-win-security-shutdownext-l1-1": {"": "shutdownext.dll"}, "ext-ms-win-xaml-pal-l1-1": {"": ""}, "ext-ms-win-core-iuri-l1-1": {"": "urlmon.dll"}, "api-ms-win-gaming-gamemonitor-l1-1": {"": "gamemonitor.dll"}, "ext-ms-win-resourcemanager-gamemode-l1-1": {"": "rmclient.dll"}, "ext-ms-win-resourcemanager-gamemode-l1-2": {"": "rmclient.dll"}, "ext-ms-win-ntuser-synch-l1-1": {"": "user32.dll"}, "ext-ms-win-core-xbrm-l1-1": {"": ""}, "ext-ms-win-appxdeploymentclient-appxdeploy-l1-1": {"": "appxdeploymentclient.dll"}, "ext-ms-win-ntuser-powermanagement-l1-1": {"": "user32.dll"}, "ext-ms-win-networking-wlanapi-l1-1": {"": "wlanapi.dll"}, "ext-ms-win-winlogon-mincreds-l1-1": {"": ""}, "api-ms-win-core-slapi-l1-1": {"": "clipc.dll"}, "ext-ms-win-appxdeploymentclient-appxdeployonecore-l1-1": {"": "appxdeploymentclient.dll"}, "api-ms-win-core-version-private-l1-1": {"": "kernelbase.dll"}, "api-ms-win-ntuser-ie-wmpointer-l1-1": {"": "user32.dll"}, "ext-ms-win-storage-hbaapi-l1-1": {"": "hbaapi.dll"}, "ext-ms-win-kernel32-datetime-l1-1": {"": "kernel32.dll"}, "ext-ms-win-networking-nlaapi-l1-1": {"": "nlaapi.dll"}, "api-ms-win-shell-shellcom-l1-1": {"": "kernelbase.dll"}, "api-ms-win-eventing-provider-l1-1": {"": "kernelbase.dll"}, "ext-ms-win-smbshare-sscore-l1-1": {"": "sscoreext.dll"}, "api-ms-onecoreuap-print-render-l1-1": {"": "printrenderapihost.dll"}, "api-ms-win-core-registry-l1-1": {"": "kernelbase.dll"}, "api-ms-win-core-registry-l2-1": {"": "advapi32.dll"}, "api-ms-win-core-registry-l2-2": {"": "advapi32.dll"}, "ext-ms-win-rpc-ssl-l1-1": {"": "rpcrtremote.dll"}, "ext-ms-onecore-defaultdiscovery-l1-1": {"": ""}, "ext-ms-win-rtcore-ntuser-dc-access-l1-1": {"": "user32.dll"}, "api-ms-win-security-systemfunctions-l1-1": {"": "advapi32.dll"}, "ext-ms-win-dx-dinput8-l1-1": {"": "dinput8.dll"}, "ext-ms-win-profile-userenv-l1-1": {"": "profext.dll"}, "ext-ms-win-ntos-tm-l1-1": {"": "tm.sys"}, "ext-ms-win-wlan-grouppolicy-l1-1": {"": "wlgpclnt.dll"}, "api-ms-win-service-winsvc-l1-1": {"": "sechost.dll"}, "api-ms-win-service-winsvc-l1-2": {"": "sechost.dll"}, "api-ms-win-security-activedirectoryclient-l1-1": {"": "kernelbase.dll"}, "ext-ms-win-composition-ghost-l1-1": {"": "dwmghost.dll"}, "api-ms-win-core-threadpool-private-l1-1": {"": "kernelbase.dll"}, "ext-ms-win-appmodel-deployment-l1-1": {"": ""}, "api-ms-win-core-psm-info-l1-1": {"": "appsruprov.dll"}, "api-ms-win-core-privateprofile-l1-1": {"": "kernel32.dll"}, "api-ms-win-core-fibers-l1-1": {"": "kernelbase.dll"}, "api-ms-win-core-fibers-l2-1": {"": "kernelbase.dll"}, "ext-ms-win-compositor-hosting-l1-1": {"": "ism.dll"}, "ext-ms-onecore-shellchromeapi-l1-1": {"": ""}, "api-ms-win-shcore-unicodeansi-l1-1": {"": "shcore.dll"}, "ext-ms-win-profile-load-l1-1": {"": ""}, "api-ms-win-core-processtopology-obsolete-l1-1": {"": "kernel32.dll"}, "ext-ms-win-shell-knownfolderext-l1-1": {"": ""}, "api-ms-win-core-largeinteger-l1-1": {"": "kernelbase.dll"}, "ext-ms-win-fveapi-query-l1-1": {"": "fveapi.dll"}, "ext-ms-win-rtcore-minuser-input-l1-1": {"": ""}, "ext-ms-win-gdi-internal-desktop-l1-1": {"": "gdi32full.dll"}, "api-ms-win-downlevel-shlwapi-l1-1": {"": "kernelbase.dll"}, "api-ms-win-downlevel-shlwapi-l2-1": {"": "shcore.dll"}, "api-ms-win-power-limitsmanagement-l1-1": {"": "powrprof.dll"}, "api-ms-win-core-debug-l1-1": {"": "kernelbase.dll"}, "ext-ms-win-core-winrt-remote-l1-1": {"": ""}, "api-ms-win-core-calendar-l1-1": {"": "kernel32.dll"}, "ext-ms-win-desktopappx-l1-1": {"": "daxexec.dll"}, "ext-ms-win-security-efswrt-l1-1": {"": "efswrt.dll"}, "ext-ms-onecore-appmodel-staterepository-internal-l1-1": {"": "windows.staterepositoryclient.dll"}, "api-ms-win-eventlog-legacy-l1-1": {"": "advapi32.dll"}, "ext-ms-win-ntuser-gui-l1-1": {"": "user32.dll"}, "ext-ms-win-ntuser-gui-l1-2": {"": "user32.dll"}, "ext-ms-win-ntuser-gui-l1-3": {"": "user32.dll"}, "api-ms-win-core-winrt-string-l1-1": {"": "combase.dll"}, "api-ms-win-rtcore-navigation-l1-1": {"": ""}, "ext-ms-win-session-winlogon-l1-1": {"": "winlogonext.dll"}, "ext-ms-win-msimg-draw-l1-1": {"": "msimg32.dll"}, "ext-ms-win-kernel32-elevation-l1-1": {"": "kernel32.dll"}, "api-ms-win-core-string-l1-1": {"": "kernelbase.dll"}, "api-ms-win-core-string-l2-1": {"": "kernelbase.dll"}, "api-ms-win-core-processsnapshot-l1-1": {"": "kernelbase.dll"}, "ext-ms-win-ntuser-rim-l1-1": {"": "user32.dll"}, "ext-ms-win-security-credui-l1-1": {"": "credui.dll"}, "ext-ms-win-mobilecore-boot-l1-1": {"": ""}, "api-ms-win-rtcore-ntuser-clipboard-l1-1": {"": "user32.dll"}, "ext-ms-win-profile-profsvc-l1-1": {"": "profsvcext.dll"}, "ext-ms-win-networking-winipsec-l1-1": {"": "winipsec.dll"}, "ext-ms-win-rtcore-ntuser-controllernavigation-l1-1": {"": ""}, "api-ms-win-downlevel-ole32-l1-1": {"": "combase.dll"}, "ext-ms-win-ntuser-mit-l1-1": {"": "user32.dll"}, "ext-ms-win-ntuser-rawinput-l1-1": {"": "user32.dll"}, "api-ms-win-service-core-l1-1": {"": "sechost.dll"}, "api-ms-win-core-registry-fromapp-l1-1": {"": "reguwpapi.dll"}, "ext-ms-win-com-ole32-l1-1": {"": "ole32.dll"}, "api-ms-win-core-synch-l1-1": {"": "kernelbase.dll"}, "api-ms-win-core-synch-l1-2": {"": "kernelbase.dll"}, "api-ms-win-core-kernel32-legacy-l1-1": {"": "kernel32.dll"}, "api-ms-win-core-windowsceip-l1-1": {"": "kernelbase.dll"}, "api-ms-win-core-bicltapi-l1-1": {"": "bi.dll"}, "ext-ms-win-sensors-utilities-private-l1-1": {"": "sensorsutilsv2.dll"}, "api-ms-win-coremessaging-host-l1-1": {"": ""}, "api-ms-win-core-errorhandling-l1-1": {"": "kernelbase.dll"}, "api-ms-win-core-winrt-error-l1-1": {"": "combase.dll"}, "ext-ms-win-ntos-ksecurity-l1-1": {"": ""}, "ext-ms-win-cluster-resutils-l1-1": {"": "resutils.dll"}, "api-ms-win-gdi-internal-uap-l1-1": {"": "gdi32full.dll"}, "ext-ms-win-shell-settingsync-l1-1": {"": "settingsyncpolicy.dll"}, "api-ms-win-core-psm-key-l1-1": {"": "kernelbase.dll"}, "api-ms-win-shcore-comhelpers-l1-1": {"": "shcore.dll"}, "ext-ms-win-mobilecore-deviceinfo-l1-1": {"": ""}, "ext-ms-win-setupapi-classinstallers-l1-1": {"": "setupapi.dll"}, "ext-ms-win-security-cryptui-l1-1": {"": "cryptui.dll"}, "ext-ms-win-feclient-encryptedfile-l1-1": {"": "feclient.dll"}, "api-ms-win-eventing-legacy-l1-1": {"": "advapi32.dll"}, "api-ms-win-core-guard-l1-1": {"": "kernelbase.dll"}, "ext-ms-win-networking-iphlpsvc-l1-1": {"": ""}, "ext-ms-win-advapi32-lsa-l1-1": {"": "advapi32.dll"}, "api-ms-win-core-wow64-l1-1": {"": "kernelbase.dll"}, "ext-ms-win-setupapi-inf-l1-1": {"": "setupapi.dll"}, "ext-ms-win-gdi-font-l1-1": {"": "gdi32full.dll"}, "api-ms-win-core-psapi-obsolete-l1-1": {"": "kernelbase.dll"}, "ext-ms-win-remotewipe-platform-l1-1": {"": ""}, "ext-ms-win-core-psm-service-l1-1": {"": "psmserviceexthost.dll"}, "ext-ms-win-appmodel-opc-l1-1": {"": "opcservices.dll"}, "api-ms-win-downlevel-normaliz-l1-1": {"": "kernelbase.dll"}, "api-ms-win-core-enclave-l1-1": {"": "kernelbase.dll"}, "ext-ms-win-font-fontgroups-l1-1": {"": "fontgroupsoverride.dll"}, "api-ms-win-core-interlocked-l1-1": {"": "kernelbase.dll"}, "api-ms-win-core-interlocked-l1-2": {"": "kernelbase.dll"}, "ext-ms-win-ntuser-draw-l1-1": {"": "user32.dll"}, "ext-ms-win-dx-d3d9-l1-1": {"": "d3d9.dll"}, "ext-ms-win-audiocore-spatial-l1-1": {"": ""}, "api-ms-win-obsolete-psapi-l1-1": {"": "kernelbase.dll"}, "ext-ms-win-mininput-extensions-l1-1": {"": ""}, "api-ms-win-obsolete-shlwapi-l1-1": {"": "kernelbase.dll"}, "api-ms-win-ole32-ie-l1-1": {"": "ole32.dll"}, "ext-ms-win-session-userinit-l1-1": {"": "userinitext.dll"}, "api-ms-win-core-xstate-l1-1": {"": "ntdll.dll"}, "api-ms-win-core-xstate-l2-1": {"": "kernelbase.dll"}, "ext-ms-win-ntuser-private-l1-1": {"": "user32.dll"}, "ext-ms-win-ntuser-private-l1-2": {"": "user32.dll"}, "ext-ms-win-ntuser-private-l1-3": {"": "user32.dll"}, "api-ms-win-crt-runtime-l1-1": {"": "ucrtbase.dll"}, "api-ms-win-core-shutdown-ansi-l1-1": {"": "advapi32.dll"}, "ext-ms-win-mm-io-l1-1": {"": ""}, "ext-ms-win-networking-mpssvc-l1-1": {"": ""}, "ext-ms-win-networking-radiomonitor-l1-1": {"": "windows.devices.radios.dll"}, "api-ms-win-shcore-scaling-l1-1": {"": "shcore.dll"}, "ext-ms-win-advapi32-psm-app-l1-1": {"": "twinapi.appcore.dll"}, "api-ms-win-core-perfcounters-l1-1": {"": "kernelbase.dll"}, "ext-ms-onecore-hcap-svf-l1-1": {"": "svf.dll"}, "api-ms-win-storage-exports-external-l1-1": {"": "windows.storage.dll"}, "api-ms-win-crt-process-l1-1": {"": "ucrtbase.dll"}, "api-ms-win-core-winrt-errorprivate-l1-1": {"": "combase.dll"}, "ext-ms-win-net-isoext-l1-1": {"": "firewallapi.dll"}, "ext-ms-win-shell-browsersettingsync-l1-1": {"": ""}, "api-ms-win-core-psapi-l1-1": {"": "kernelbase.dll"}, "api-ms-win-shell-changenotify-l1-1": {"": "windows.storage.dll"}, "ext-ms-win-advapi32-auth-l1-1": {"": "advapi32.dll"}, "api-ms-win-core-rtlsupport-l1-1": {"": "ntdll.dll"}, "api-ms-win-core-rtlsupport-l1-2": {"": "ntdll.dll"}, "ext-ms-win-scesrv-server-l1-1": {"": "scesrv.dll"}, "ext-ms-win-mf-pal-l1-1": {"": ""}, "api-ms-win-core-localization-private-l1-1": {"": "kernelbase.dll"}, "ext-ms-onecore-hnetcfg-l1-1": {"": "hnetcfgclient.dll"}, "ext-ms-win-crypto-xbox-l1-1": {"": ""}, "ext-ms-win-appmodel-state-ext-l1-2": {"": "kernel.appcore.dll"}, "api-ms-win-core-winrt-registration-l1-1": {"": "combase.dll"}, "ext-ms-net-eap-sim-l1-1": {"": "eapsimextdesktop.dll"}, "api-ms-win-core-path-l1-1": {"": "kernelbase.dll"}, "ext-ms-win-core-winsrv-l1-1": {"": "winsrvext.dll"}, "api-ms-win-core-processtopology-private-l1-1": {"": "kernelbase.dll"}, "ext-ms-win-netprovision-netprovfw-l1-1": {"": "netprovfw.dll"}, "ext-ms-win-ui-viewmanagement-l1-1": {"": ""}, "ext-ms-win-core-resourcepolicy-l1-1": {"": "resourcepolicyclient.dll"}, "api-ms-win-core-stringansi-l1-1": {"": "kernelbase.dll"}, "api-ms-win-core-file-ansi-l1-1": {"": "kernel32.dll"}, "api-ms-win-core-file-ansi-l2-1": {"": "kernel32.dll"}, "ext-ms-onecore-appdefaults-l1-1": {"": "windows.storage.dll"}, "ext-ms-win-rtcore-gdi-object-l1-1": {"": "gdi32.dll"}, "ext-ms-onecore-hlink-l1-1": {"": "hlink.dll"}, "api-ms-win-security-base-l1-1": {"": "kernelbase.dll"}, "api-ms-win-security-base-l1-2": {"": "kernelbase.dll"}, "ext-ms-win-session-usermgr-l1-1": {"": "usermgrcli.dll"}, "ext-ms-win-session-usermgr-l1-2": {"": "usermgrcli.dll"}, "ext-ms-win-kernel32-errorhandling-l1-1": {"": "kernel32.dll", "kernel32.dll": "faultrep.dll"}, "ext-ms-win-wevtapi-eventlog-l1-1": {"": "wevtapi.dll"}, "api-ms-win-core-systemtopology-l1-1": {"": "kernelbase.dll"}, "api-ms-win-eventing-classicprovider-l1-1": {"": "kernelbase.dll"}, "api-ms-win-security-sddl-l1-1": {"": "sechost.dll"}, "ext-ms-win-fs-vssapi-l1-1": {"": "vssapi.dll"}, "ext-ms-win-gdi-devcaps-l1-1": {"": "gdi32full.dll"}, "ext-ms-win-ntuser-window-l1-1": {"": "user32.dll"}, "api-ms-win-rtcore-session-l1-1": {"": ""}, "api-ms-win-rtcore-session-l1-2": {"": ""}, "ext-ms-onecore-appmodel-pacmanclient-l1-1": {"": ""}, "ext-ms-win-authz-claimpolicies-l1-1": {"": "authz.dll"}, "api-ms-win-core-versionansi-l1-1": {"": "kernelbase.dll"}, "ext-ms-win-security-winscard-l1-1": {"": "winscard.dll"}, "ext-ms-win-mapi-mapi32-l1-1": {"": "mapistub.dll"}, "ext-ms-win-shell-comctl32-init-l1-1": {"": "comctl32.dll"}, "ext-ms-onecore-appmodel-veventdispatcher-l1-1": {"": "veeventdispatcher.dll"}, "api-ms-win-oobe-notification-l1-1": {"": "kernel32.dll"}, "api-ms-win-gaming-expandedresources-l1-1": {"": "gamemode.dll"}, "api-ms-win-gdi-dpiinfo-l1-1": {"": "gdi32.dll"}, "api-ms-win-service-private-l1-1": {"": "sechost.dll"}, "ext-ms-win-gdi-dc-create-l1-1": {"": "gdi32full.dll"}, "ext-ms-win-kernel32-quirks-l1-1": {"": "kernel32.dll"}, "ext-ms-win-gui-dui70-l1-1": {"": "dui70.dll"}}} \ No newline at end of file diff --git a/miasm/os_dep/windows/apiset/__init__.py b/miasm/os_dep/windows/apiset/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/setup.py b/setup.py index a20cf9a10..337aed91d 100644 --- a/setup.py +++ b/setup.py @@ -47,7 +47,7 @@ def win_get_llvm_reg(): except FileNotFoundError: pass return winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, REG_PATH, 0, winreg.KEY_READ) - + def win_find_clang_path(): try: with win_get_llvm_reg() as rkey: @@ -102,6 +102,8 @@ def buil_all(): "miasm/analysis", "miasm/os_dep", "miasm/os_dep/linux", + "miasm/os_dep/windows", + "miasm/os_dep/windows/apiset", "miasm/loader", "miasm/jitter", "miasm/jitter/arch", @@ -239,6 +241,7 @@ def buil_all(): "miasm": [ "jitter/*.h", "jitter/arch/*.h", + "os_dep/windows/apiset/*.json", "VERSION" ] }, diff --git a/utils/apiset_to_json.py b/utils/apiset_to_json.py new file mode 100644 index 000000000..956556e59 --- /dev/null +++ b/utils/apiset_to_json.py @@ -0,0 +1,209 @@ +import sys +import json +import ctypes +from miasm.loader.pe_init import PE +from argparse import ArgumentParser + + +ULONG = ctypes.c_uint32 + + +def extract_409_resource(res): + """ + Find the first resource id 0x409 + """ + if res is None: + return None + for x in res.resentries: + if x.data: + if x.name == 0x409: + return x.data.s + if x.offsettosubdir: + ret = extract_409_resource(x.subdir) + if ret: + return ret + return None + + +class ApiSetWin10(object): + def __init__(self, fname_apisetschema): + self.pe = PE(open(fname_apisetschema, "rb").read()) + self.version = self.get_version() + self.api_section = self.pe.getsectionbyname(".apiset").get_data() + self.hash_factor = self.get_hash_factor() + self.hash_entries = self.get_hash_entries() + self.redirections = self.get_redirection_by_name() + + def get_version(self): + res = self.pe.DirRes.resdesc + + data = extract_409_resource(res) + token = "ProductVersion\x00".encode("utf-16le") + index_start = data.find(token) + assert index_start > 0 + index_start += len(token) + index_stop = data.find(b"\x00\x00", index_start) + assert index_start > 0 + data = data[index_start : index_stop + 1] + data = data.decode("utf-16le") + return data + + class ApiSetHeader(ctypes.Structure): + _fields_ = [ + ("Version", ULONG), + ("Size", ULONG), + ("Flags", ULONG), + ("Count", ULONG), + ("EntryOffset", ULONG), + ("HashOffset", ULONG), + ("HashFactor", ULONG), + ] + + class ApiSetHashEntry(ctypes.Structure): + _fields_ = [ + ("NumberOfEntries", ULONG), + ] + + class ApiSetHosts_win10(ctypes.Structure): + _fields_ = [ + ("Hash", ULONG), + ("Index", ULONG), + ] + + class ApiSetNameSpaceEntry(ctypes.Structure): + _fields_ = [ + ("Flags", ULONG), + ("NameOffset", ULONG), + ("NameLength", ULONG), + ("HashedLength", ULONG), + ("ValueOffset", ULONG), + ("ValueCount", ULONG), + ] + + class ApiSetValueEntry(ctypes.Structure): + _fields_ = [ + ("Flags", ULONG), + ("NameOffset", ULONG), + ("NameLength", ULONG), + ("ValueOffset", ULONG), + ("ValueLength", ULONG), + ] + + def get_hash_factor(self): + hdr = self.ApiSetHeader.from_buffer_copy( + self.api_section[0 : ctypes.sizeof(self.ApiSetHeader)] + ) + # Windows 10 + assert hdr.Version >= 5 + return hdr.HashFactor + + def get_redirection_by_name(self): + hdr = self.ApiSetHeader.from_buffer_copy( + self.api_section[0 : ctypes.sizeof(self.ApiSetHeader)] + ) + # Windows 10 + assert hdr.Version >= 5 + redirections = {} + for i in range(hdr.Count): + addr = hdr.EntryOffset + i * ctypes.sizeof(self.ApiSetNameSpaceEntry) + entry = self.ApiSetNameSpaceEntry.from_buffer_copy( + self.api_section[addr : addr + ctypes.sizeof(self.ApiSetNameSpaceEntry)] + ) + addr = entry.NameOffset + redir_name = self.api_section[addr : addr + entry.NameLength] + redir_name = redir_name.decode("utf-16le") + + addr_descs = entry.ValueOffset + + host_out = {} + for i in range(entry.ValueCount): + addr = addr_descs + i * ctypes.sizeof(self.ApiSetValueEntry) + host = self.ApiSetValueEntry.from_buffer_copy( + self.api_section[addr : addr + ctypes.sizeof(self.ApiSetValueEntry)] + ) + if host.NameOffset != 0: + addr = host.NameOffset + importName = self.api_section[addr : addr + host.NameLength] + importName = importName.decode("utf-16le") + else: + importName = "" + + addr = host.ValueOffset + hostName = self.api_section[addr : addr + host.ValueLength] + hostName = hostName.decode("utf-16le") + host_out[importName] = hostName + redirections[redir_name.lower()] = host_out + + return redirections + + # hash func can be found in ntdll!ApiSetpSearchForApiSet + def compute_hash(self, apiset_lib_name, hashf): + hashk = 0 + for c in apiset_lib_name: + hashk = (hashk * hashf + c) & ((1 << 32) - 1) + return hashk + + def get_hash_entries(self): + hash_entries = {} + hdr = self.ApiSetHeader.from_buffer_copy( + self.api_section[: ctypes.sizeof(self.ApiSetHeader)] + ) + # Windows 10 + assert hdr.Version >= 5 + for i in range(0, hdr.Count): + offset = hdr.HashOffset + i * ctypes.sizeof(self.ApiSetHosts_win10) + hash_entry = self.ApiSetHosts_win10.from_buffer_copy( + self.api_section[ + offset : offset + ctypes.sizeof(self.ApiSetHosts_win10) + ] + ) + offset = hdr.EntryOffset + hash_entry.Index * ctypes.sizeof( + self.ApiSetNameSpaceEntry + ) + namespace_entry = self.ApiSetNameSpaceEntry.from_buffer_copy( + self.api_section[ + offset : offset + ctypes.sizeof(self.ApiSetNameSpaceEntry) + ] + ) + hashed_name = self.api_section[ + namespace_entry.NameOffset : namespace_entry.NameOffset + + namespace_entry.HashedLength + ] + hashed_name = hashed_name.decode("utf-16le") + entries = [] + for c in range(0, namespace_entry.ValueCount): + offset = namespace_entry.ValueOffset + c * ctypes.sizeof( + self.ApiSetValueEntry + ) + value_entry = self.ApiSetValueEntry.from_buffer_copy( + self.api_section[ + offset : offset + ctypes.sizeof(self.ApiSetValueEntry) + ] + ) + value_name = self.api_section[ + value_entry.NameOffset : value_entry.NameOffset + + value_entry.NameLength + ] + value_data = self.api_section[ + value_entry.ValueOffset : value_entry.ValueOffset + + value_entry.ValueLength + ] + name = value_name.decode("utf-16le") + data = value_data.decode("utf-16le") + entries.append((name, data)) + hash_entries[hashed_name] = dict(entries) + return hash_entries + + +parser = ArgumentParser("Extract information from windows apiset dll") +parser.add_argument("filename", help="Windows ApiSet schema dll") +args = parser.parse_args() + +apiset = ApiSetWin10(args.filename) +apiset.get_redirection_by_name() + +export_obj = {} +export_obj["version"] = apiset.version +export_obj["hashes"] = apiset.hash_entries + +open("%s.json" % apiset.version, "w").write(json.dumps(export_obj)) From 8322a0cc36ef1e5372cb717667282f8be06743d4 Mon Sep 17 00:00:00 2001 From: Fabrice Desclaux Date: Fri, 16 Oct 2020 08:25:42 +0200 Subject: [PATCH 07/12] Use apiset & reloc --- miasm/analysis/sandbox.py | 40 ++++++++++----- miasm/jitter/loader/pe.py | 102 ++++++++++++++++++++++++-------------- miasm/loader/pe_init.py | 22 +++++--- 3 files changed, 110 insertions(+), 54 deletions(-) diff --git a/miasm/analysis/sandbox.py b/miasm/analysis/sandbox.py index 5f9ef81a0..0e7b0c2fb 100644 --- a/miasm/analysis/sandbox.py +++ b/miasm/analysis/sandbox.py @@ -223,12 +223,16 @@ def init_stack(self): self.jitter.stack_base = self.STACK_BASE self.jitter.init_stack() - def init_loader(self): + def init_loader(self, options): from miasm.jitter.loader.pe import LoaderWindows from miasm.os_dep.win_api_x86_32 import winobjs # Import manager - loader = LoaderWindows() + if options.loader_start_address: + loader_start_address = int(options.loader_start_address, 0) + else: + loader_start_address = None + loader = LoaderWindows(loader_start_address=loader_start_address) self.loader = loader winobjs.loader = loader @@ -262,7 +266,7 @@ def load_main_pe(self, options): def load_base_dll(self): from miasm.os_dep.win_api_x86_32 import winobjs - from miasm.jitter.loader.pe import vm_load_pe_libs, preload_pe + from miasm.jitter.loader.pe import vm_load_pe_libs, fix_pe_imports # Load libs in memory self.name2module.update( @@ -276,8 +280,8 @@ def load_base_dll(self): ) # Patch libs imports - for pe in viewvalues(self.name2module): - preload_pe(self.jitter.vm, pe, self.loader) + for name, pe in self.name2module.items(): + fix_pe_imports(self.jitter.vm, pe, self.loader, pe_name=name) def load_dependencies(self): from miasm.os_dep.win_api_x86_32 import winobjs @@ -302,25 +306,27 @@ def set_call_handler(self, custom_methods): methods.update(custom_methods) self.jitter.add_lib_handler(self.loader, methods) - def fix_preload_pe(self): + def fix_pe_imports(self): # Fix pe imports - from miasm.jitter.loader.pe import preload_pe + from miasm.jitter.loader.pe import fix_pe_imports - preload_pe(self.jitter.vm, self.pe, self.loader) + fix_pe_imports( + self.jitter.vm, self.pe, self.loader, pe_name=self.fname_basename + ) def __init__(self, jitter, options, custom_methods=None): self.fname_basename = os.path.basename(options.filename).lower() self.jitter = jitter self.init_stack() - self.init_loader() + self.init_loader(options) self.load_main_pe(options) if options.loadbasedll: self.load_base_dll() if options.dependencies: self.load_dependencies() - self.fix_preload_pe() + self.fix_pe_imports() self.set_call_handler(custom_methods) # Manage SEH @@ -358,6 +364,12 @@ def update_parser(cls, parser): action="store_true", help="Don't log function calls", ) + parser.add_argument( + "-x", + "--loader_start_address", + default=None, + help="Reloc libraries starting at load base address", + ) class Sandbox_WinXP_x86_32(Sandbox): @@ -391,7 +403,7 @@ def call(self, addr, *args, **kwargs): class OS_Win10(OS_WinXP32): VERSION = "10.0.15063.0" - def init_loader(self): + def init_loader(self, options): from miasm.jitter.loader.pe import LoaderWindows from miasm.os_dep.windows import apiset from miasm.os_dep.win_api_x86_32 import winobjs @@ -403,7 +415,11 @@ def init_loader(self): apiset = ApiSet(apiset_file) # Import manager - loader = LoaderWindows(apiset=apiset) + if options.loader_start_address: + loader_start_address = int(options.loader_start_address, 0) + else: + loader_start_address = None + loader = LoaderWindows(apiset=apiset, loader_start_address=loader_start_address) self.loader = loader winobjs.loader = loader diff --git a/miasm/jitter/loader/pe.py b/miasm/jitter/loader/pe.py index bd322f137..ac07c4487 100644 --- a/miasm/jitter/loader/pe.py +++ b/miasm/jitter/loader/pe.py @@ -1,5 +1,6 @@ from builtins import map import os +import re import struct import json import logging @@ -22,6 +23,8 @@ log.addHandler(hnd) log.setLevel(logging.INFO) +match_hyphen_digit = re.compile(".*-[\d]+-[\d]+$") + def get_pe_dependencies(pe_obj): """Collect the shared libraries upon which this PE depends. @@ -89,7 +92,7 @@ def get_import_address_pe(e): return import2addr -def preload_pe(vm, e, loader, patch_vm_imp=True): +def fix_pe_imports(vm, e, loader, patch_vm_imp=True, pe_name=None): import_information = get_import_address_pe(e) dyn_funcs = {} # log.debug('imported funcs: %s' % import_information) @@ -97,7 +100,7 @@ def preload_pe(vm, e, loader, patch_vm_imp=True): for ad in ads: libname = force_str(libname) if loader.apiset: - libname = loader.apiset.get_redirection(libname) + libname = loader.apiset.get_redirection(libname, pe_name) ad_base_lib = loader.lib_get_add_base(libname) ad_funcname = loader.lib_get_add_func(ad_base_lib, funcname, ad) @@ -105,7 +108,8 @@ def preload_pe(vm, e, loader, patch_vm_imp=True): dyn_funcs[libname_s] = ad_funcname if patch_vm_imp: vm.set_mem( - ad, struct.pack(cstruct.size2type[e._wsize], ad_funcname)) + ad, struct.pack(cstruct.size2type[e._wsize], ad_funcname) + ) return dyn_funcs @@ -170,7 +174,7 @@ def get_export_name_addr_list(e): return out -def vm_load_pe(vm, fdata, align_s=True, load_hdr=True, name="", winobjs=None, **kargs): +def vm_load_pe(vm, fdata, align_s=True, load_hdr=True, name="", winobjs=None, base_addr=None, **kargs): """Load a PE in memory (@vm) from a data buffer @fdata @vm: VmMngr instance @fdata: data buffer to parse @@ -186,6 +190,10 @@ def vm_load_pe(vm, fdata, align_s=True, load_hdr=True, name="", winobjs=None, ** # Parse and build a PE instance pe = pe_init.PE(fdata, **kargs) + # Optionaly rebase PE + if base_addr is not None: + pe.reloc_to(base_addr) + # Check if all section are aligned aligned = True for section in pe.SHList: @@ -307,7 +315,7 @@ def vm_load_pe_lib(vm, fname_in, loader, lib_path_base, **kargs): fname = os.path.join(lib_path_base, fname_in) with open(fname, "rb") as fstream: - pe = vm_load_pe(vm, fstream.read(), name=fname_in, **kargs) + pe = loader.vm_load_pe(vm, fstream.read(), name=fname_in, **kargs) loader.add_export_lib(pe, fname_in) return pe @@ -325,13 +333,9 @@ def vm_load_pe_libs(vm, libs_name, loader, lib_path_base, **kargs): for fname in libs_name: assert isinstance(fname, str) out[fname] = vm_load_pe_lib(vm, fname, loader, lib_path_base, **kargs) - return out + return out -def vm_fix_imports_pe_libs(lib_imgs, loader, lib_path_base, - patch_vm_imp=True, **kargs): - for e in viewvalues(lib_imgs): - preload_pe(e, loader, patch_vm_imp=patch_vm_imp) def vm2pe(myjit, fname, loader=None, e_orig=None, @@ -424,11 +428,12 @@ def vm2pe(myjit, fname, loader=None, e_orig=None, class LoaderWindows(Loader): - def __init__(self, *args, apiset=None, **kwargs): + def __init__(self, *args, apiset=None, loader_start_address=None, **kwargs): super(LoaderWindows, self).__init__(*args, **kwargs) # dependency -> redirector self.created_redirected_imports = {} self.apiset = apiset + self.loader_start_address = loader_start_address def add_function(self, dllname, imp_ord_or_name, addr): @@ -583,6 +588,19 @@ def gen_new_lib(self, target_pe, filter_import=lambda peobj, ad: True, **kwargs) return new_lib + def vm_load_pe(self, vm, fdata, align_s=True, load_hdr=True, name="", winobjs=None, **kargs): + pe = vm_load_pe( + vm, fdata, + align_s=align_s, + load_hdr=load_hdr, + name=name, winobjs=winobjs, + base_addr=self.loader_start_address, + **kargs + ) + if self.loader_start_address: + self.loader_start_address += pe.NThdr.sizeofimage + 0x1000 + return pe + class limbimp_pe(LoaderWindows): def __init__(self, *args, **kwargs): @@ -621,8 +639,9 @@ def vm_load_pe_and_dependencies(vm, fname, name2module, loader, try: with open(fname, "rb") as fstream: log.info('Loading module name %r', fname) - pe_obj = vm_load_pe( - vm, fstream.read(), name=fname, **kwargs) + pe_obj = loader.vm_load_pe( + vm, fstream.read(), name=fname, **kwargs + ) except IOError: log.error('Cannot open %s' % fname) name2module[name] = None @@ -630,13 +649,14 @@ def vm_load_pe_and_dependencies(vm, fname, name2module, loader, name2module[name] = pe_obj new_dependencies = get_pe_dependencies(pe_obj) - todo += [(name, os.path.join(lib_path_base, name), weight - 1) - for name in new_dependencies] + for libname in new_dependencies: + if loader.apiset: + libname = loader.apiset.get_redirection(libname, name) + todo.append((libname, os.path.join(lib_path_base, libname), weight - 1)) known_export_addresses = {} to_resolve = {} for name, pe_obj in name2module.items(): - print(name) if pe_obj is None: continue if pe_obj.DirExport.expdesc == None: @@ -650,6 +670,9 @@ def vm_load_pe_and_dependencies(vm, fname, name2module, loader, known_export_addresses[(name, imp_ord_or_name)] = ad else: dllname, func_info = ret + + dllname = loader.apiset.get_redirection(dllname, name) + dllname = dllname + '.dll' to_resolve[(name, imp_ord_or_name)] = (dllname, func_info) @@ -688,7 +711,7 @@ def vm_load_pe_and_dependencies(vm, fname, name2module, loader, for dllname, pe_obj in name2module.items(): if pe_obj is None: continue - preload_pe(vm, pe_obj, loader, patch_vm_imp=True) + fix_pe_imports(vm, pe_obj, loader, patch_vm_imp=True, pe_name=dllname) return name2module @@ -709,8 +732,6 @@ class ApiSet(object): def __init__(self, fname): data = json.load(open(fname)) self.version = data['version'] - self.hash_factor = data['hash_factor'] - self.redirections = data['redirections'] self.hash_entries = data['hashes'] def compute_hash(self, apiset_lib_name): @@ -722,26 +743,35 @@ def compute_hash(self, apiset_lib_name): hashk = (hashk * self.hash_factor + ord(c)) & ((1 << 32) - 1) return hashk - def get_redirection(self, libname): + def get_redirected_host(self, libname, entries, parent): + if len(entries) == 1: + assert "" in entries + log.debug("ApiSet %s => %s" % (libname, entries[""])) + libname = entries[""] + else: + if parent in entries: + libname = entries[parent] + else: + libname = entries[""] + return libname + + def get_redirection(self, libname, parent_name): has_dll = libname.endswith(".dll") if has_dll: - libname = libname[:-4] - if libname in self.redirections: - values = self.redirections[libname] - if len(values) == 1: - assert "" in values - log.warn("ApiSet %s => %s" % (libname, values[""])) - libname = values[""] - else: - libname_dll = "%s.dll" % libname - if libname_dll in values: - fds - else: - libname = values[""] - hash_to_search = self.compute_hash(libname) - if hash_to_search in self.hash_entries: - fds + name_nodll = libname[:-4] + else: + name_nodll = libname + # Remove last hyphen part to compute crc + if match_hyphen_digit.match(name_nodll): + cname = name_nodll[:name_nodll.rfind('-')] + else: + cname = name_nodll + values = self.hash_entries.get(cname, None) + if not values: + # No entry found + return libname + libname = self.get_redirected_host(cname, values, parent_name) if has_dll and not libname.endswith('.dll'): libname += ".dll" elif not has_dll and libname.endswith('.dll'): diff --git a/miasm/loader/pe_init.py b/miasm/loader/pe_init.py index 3e0c660e5..2ef84ba0d 100644 --- a/miasm/loader/pe_init.py +++ b/miasm/loader/pe_init.py @@ -620,10 +620,20 @@ def reloc_to(self, imgbase): reloc_type, off = reloc.rel if reloc_type == 0 and off == 0: continue - if reloc_type != 3: - raise NotImplementedError('Reloc type not supported') - off += rva - value = struct.unpack('I', self.rva.get(off, off + 4))[0] - value += offset - self.rva.set(off, struct.pack('I', value & 0xFFFFFFFF)) + if reloc_type == 3: + off += rva + value = struct.unpack('I', self.rva.get(off, off + 4))[0] + value += offset + data = struct.pack('I', value & 0xFFFFFFFF) + self.rva.set(off, data) + self.img_rva[off] = data + elif reloc_type == 10: + off += rva + value = struct.unpack('Q', self.rva.get(off, off + 8))[0] + value += offset + data = struct.pack('Q', value & 0xFFFFFFFFFFFFFFFF) + self.rva.set(off, data) + self.img_rva[off] = data + else: + raise NotImplementedError('Reloc type not supported') self.NThdr.ImageBase = imgbase From 218e03080f9bb83d273ae3f3c134a8aaea395308 Mon Sep 17 00:00:00 2001 From: Fabrice Desclaux Date: Thu, 22 Oct 2020 19:28:32 +0200 Subject: [PATCH 08/12] Refactor module loader --- example/jitter/run_with_linuxenv.py | 1 + example/jitter/unpack_upx.py | 7 +- miasm/analysis/dse.py | 4 +- miasm/analysis/sandbox.py | 70 +---- miasm/jitter/jitload.py | 12 +- miasm/jitter/loader/elf.py | 14 +- miasm/jitter/loader/pe.py | 465 ++++++++++------------------ miasm/jitter/loader/utils.py | 124 +++++--- miasm/os_dep/win_api_x86_32.py | 16 +- 9 files changed, 274 insertions(+), 439 deletions(-) diff --git a/example/jitter/run_with_linuxenv.py b/example/jitter/run_with_linuxenv.py index 9290e6a83..6826661b9 100644 --- a/example/jitter/run_with_linuxenv.py +++ b/example/jitter/run_with_linuxenv.py @@ -58,6 +58,7 @@ ld_path = linux_env.filesystem.resolve_path(ld_path) cont_ld = Container.from_stream( open(ld_path, "rb"), + loc_db=loc_db, vm=jitter.vm, addr=0x80000000, apply_reloc=True diff --git a/example/jitter/unpack_upx.py b/example/jitter/unpack_upx.py index a75e9a797..b6c755bbe 100644 --- a/example/jitter/unpack_upx.py +++ b/example/jitter/unpack_upx.py @@ -25,12 +25,13 @@ def kernel32_GetProcAddress(jitter): # Get the generated address of the library, and store it in memory to # dst_ad - ad = sb.loader.lib_get_add_func(args.libbase, fname, dst_ad) + name = sb.loader.module_base_address_to_name[args.libbase] + addr = sb.loader.resolve_function(name, fname, dst_ad=dst_ad) # Add a breakpoint in case of a call on the resolved function # NOTE: never happens in UPX, just for skeleton - jitter.handle_function(ad) + jitter.handle_function(addr) - jitter.func_ret_stdcall(ret_ad, ad) + jitter.func_ret_stdcall(ret_ad, addr) parser = Sandbox_WinXP_x86_32.parser(description="Generic UPX unpacker") diff --git a/miasm/analysis/dse.py b/miasm/analysis/dse.py index 6fee0a5f0..50fe7ebc7 100644 --- a/miasm/analysis/dse.py +++ b/miasm/analysis/dse.py @@ -258,14 +258,14 @@ def add_lib_handler(self, loader, namespace): # lambda cannot contain statement def default_func(dse): - fname = loader.fad2cname[dse.jitter.pc] + fname = loader.module_base_address_to_name(dse.jitter.pc) if isinstance(fname, tuple): fname = b"%s_%d_symb" % (force_bytes(fname[0]), fname[1]) else: fname = b"%s_symb" % force_bytes(fname) raise RuntimeError("Symbolic stub '%s' not found" % fname) - for addr, fname in viewitems(loader.fad2cname): + for addr, fname in viewitems(loader.function_address_to_canonical_name): if isinstance(fname, tuple): fname = b"%s_%d_symb" % (force_bytes(fname[0]), fname[1]) else: diff --git a/miasm/analysis/sandbox.py b/miasm/analysis/sandbox.py index 0e7b0c2fb..b145c48ca 100644 --- a/miasm/analysis/sandbox.py +++ b/miasm/analysis/sandbox.py @@ -232,7 +232,7 @@ def init_loader(self, options): loader_start_address = int(options.loader_start_address, 0) else: loader_start_address = None - loader = LoaderWindows(loader_start_address=loader_start_address) + loader = LoaderWindows(self.jitter.vm, loader_start_address=loader_start_address) self.loader = loader winobjs.loader = loader @@ -242,7 +242,7 @@ def use_windows_structs(self): win_api_x86_32_seh.main_pe_name = self.fname_basename win_api_x86_32_seh.main_pe = self.pe win_api_x86_32.winobjs.hcurmodule = self.pe.NThdr.ImageBase - win_api_x86_32_seh.name2module = self.name2module + win_api_x86_32_seh.name2module = self.loader.module_name_to_module win_api_x86_32_seh.set_win_fs_0(self.jitter) win_api_x86_32_seh.init_seh(self.jitter) @@ -250,52 +250,11 @@ def load_main_pe(self, options): from miasm.jitter.loader.pe import vm_load_pe from miasm.os_dep.win_api_x86_32 import winobjs - self.name2module = {} - - # Load main pe - with open(options.filename, "rb") as fstream: - self.pe = vm_load_pe( - self.jitter.vm, - fstream.read(), - load_hdr=options.load_hdr, - name=options.filename, - winobjs=winobjs, - ) - self.name2module[self.fname_basename] = self.pe + module_image_base = self.loader.load_module(options.filename) + name = self.loader.module_base_address_to_name[module_image_base] + self.pe = self.loader.module_name_to_module[name] winobjs.current_pe = self.pe - def load_base_dll(self): - from miasm.os_dep.win_api_x86_32 import winobjs - from miasm.jitter.loader.pe import vm_load_pe_libs, fix_pe_imports - - # Load libs in memory - self.name2module.update( - vm_load_pe_libs( - self.jitter.vm, - self.LOADED_DLLS, - self.loader, - self.PATH_DLLS, - winobjs=winobjs, - ) - ) - - # Patch libs imports - for name, pe in self.name2module.items(): - fix_pe_imports(self.jitter.vm, pe, self.loader, pe_name=name) - - def load_dependencies(self): - from miasm.os_dep.win_api_x86_32 import winobjs - from miasm.jitter.loader.pe import vm_load_pe_and_dependencies - - vm_load_pe_and_dependencies( - self.jitter.vm, - self.fname_basename, - self.name2module, - self.loader, - self.PATH_DLLS, - winobjs=winobjs, - ) - def set_call_handler(self, custom_methods): # Library calls handler from miasm.os_dep import win_api_x86_32 @@ -306,14 +265,6 @@ def set_call_handler(self, custom_methods): methods.update(custom_methods) self.jitter.add_lib_handler(self.loader, methods) - def fix_pe_imports(self): - # Fix pe imports - from miasm.jitter.loader.pe import fix_pe_imports - - fix_pe_imports( - self.jitter.vm, self.pe, self.loader, pe_name=self.fname_basename - ) - def __init__(self, jitter, options, custom_methods=None): self.fname_basename = os.path.basename(options.filename).lower() self.jitter = jitter @@ -321,12 +272,7 @@ def __init__(self, jitter, options, custom_methods=None): self.init_stack() self.init_loader(options) self.load_main_pe(options) - if options.loadbasedll: - self.load_base_dll() - if options.dependencies: - self.load_dependencies() - self.fix_pe_imports() self.set_call_handler(custom_methods) # Manage SEH @@ -419,7 +365,7 @@ def init_loader(self, options): loader_start_address = int(options.loader_start_address, 0) else: loader_start_address = None - loader = LoaderWindows(apiset=apiset, loader_start_address=loader_start_address) + loader = LoaderWindows(self.jitter.vm, apiset=apiset, loader_start_address=loader_start_address) self.loader = loader winobjs.loader = loader @@ -503,7 +449,7 @@ def __init__(self, jitter, options, custom_methods=None): self.jitter.init_stack() # Import manager - self.loader = LoaderUnix() + self.loader = LoaderUnix(self.jitter.vm) with open(options.filename, "rb") as fstream: self.elf = vm_load_elf( @@ -562,7 +508,7 @@ def __init__(self, jitter, options, custom_methods=None): self.jitter.init_stack() # Import manager - self.loader = LoaderUnix() + self.loader = LoaderUnix(self.jitter.vm) data = open(options.filename, "rb").read() options.load_base_addr = int(options.load_base_addr, 0) diff --git a/miasm/jitter/jitload.py b/miasm/jitter/jitload.py index 6f3af0331..5c44d2477 100644 --- a/miasm/jitter/jitload.py +++ b/miasm/jitter/jitload.py @@ -491,7 +491,7 @@ def handle_lib(jitter): """Resolve the name of the function which cause the handler call. Then call the corresponding handler from users callback. """ - fname = jitter.libs.fad2cname[jitter.pc] + fname = jitter.loader.function_address_to_canonical_name[jitter.pc] if fname in jitter.user_globals: func = jitter.user_globals[fname] else: @@ -510,21 +510,21 @@ def handle_function(self, f_addr): """Add a breakpoint which will trigger the function handler""" self.add_breakpoint(f_addr, self.handle_lib) - def add_lib_handler(self, libs, user_globals=None): - """Add a function to handle libs call with breakpoints - @libs: libimp instance + def add_lib_handler(self, loader, user_globals=None): + """Add a function to handle loader call with breakpoints + @loader: Loader instance @user_globals: dictionary for defined user function """ if user_globals is None: user_globals = {} - self.libs = libs + self.loader = loader out = {} for name, func in viewitems(user_globals): out[name] = func self.user_globals = out - for f_addr in libs.fad2cname: + for f_addr in loader.function_address_to_canonical_name: self.handle_function(f_addr) def eval_expr(self, expr): diff --git a/miasm/jitter/loader/elf.py b/miasm/jitter/loader/elf.py index 9aa11143a..97100a36e 100644 --- a/miasm/jitter/loader/elf.py +++ b/miasm/jitter/loader/elf.py @@ -43,7 +43,7 @@ def preload_elf(vm, e, loader, patch_vm_imp=True, loc_db=None): continue for ad in ads: ad_base_lib = loader.lib_get_add_base(libname) - ad_libfunc = loader.lib_get_add_func(ad_base_lib, libfunc, ad) + ad_libfunc = loader.resolve_function(vm, ad_base_lib, libfunc, ad) libname_s = canon_libname_libfunc(libname, libfunc) dyn_funcs[libname_s] = ad_libfunc @@ -317,7 +317,17 @@ def vm_load_elf(vm, fdata, name="", base_addr=0, loc_db=None, apply_reloc=False, class LoaderUnix(Loader): - pass + + def lib_get_add_base(self, name): + name = name.lower().strip(' ') + if name in self.module_name_to_base_address: + ad = self.module_name_to_base_address[name] + else: + ad = self.fake_library_entry(name) + return ad + + def resolve_function(self, vm, libad, imp_ord_or_name, dst_ad=None): + return self.fake_resolve_function(libad, imp_ord_or_name, dst_ad=dst_ad) class libimp_elf(LoaderUnix): diff --git a/miasm/jitter/loader/pe.py b/miasm/jitter/loader/pe.py index ac07c4487..a2ff96afb 100644 --- a/miasm/jitter/loader/pe.py +++ b/miasm/jitter/loader/pe.py @@ -26,41 +26,6 @@ match_hyphen_digit = re.compile(".*-[\d]+-[\d]+$") -def get_pe_dependencies(pe_obj): - """Collect the shared libraries upon which this PE depends. - @pe_obj: pe object - Returns a set of strings of DLL names. - Example: - container = miasm.analysis.binary.Container.from_string(buf) - deps = miasm.jitter.loader.pe.get_pe_dependencies(container.executable) - assert sorted(deps)[0] == 'api-ms-win-core-appcompat-l1-1-0.dll' - """ - - if pe_obj.DirImport.impdesc is None: - return set() - out = set() - for dependency in pe_obj.DirImport.impdesc: - libname = dependency.dlldescname.name.lower() - # transform bytes to str - libname = force_str(libname) - out.add(libname) - - # If binary has redirected export, add dependencies - if pe_obj.DirExport.expdesc != None: - addrs = get_export_name_addr_list(pe_obj) - for imp_ord_or_name, ad in addrs: - # if export is a redirection, search redirected dll - # and get function real addr - ret = is_redirected_export(pe_obj, ad) - if ret is False: - continue - dllname, func_info = ret - dllname = dllname + '.dll' - out.add(dllname) - - return out - - def get_import_address_pe(e): """Compute the addresses of imported symbols. @e: pe object @@ -92,27 +57,6 @@ def get_import_address_pe(e): return import2addr -def fix_pe_imports(vm, e, loader, patch_vm_imp=True, pe_name=None): - import_information = get_import_address_pe(e) - dyn_funcs = {} - # log.debug('imported funcs: %s' % import_information) - for (libname, funcname), ads in viewitems(import_information): - for ad in ads: - libname = force_str(libname) - if loader.apiset: - libname = loader.apiset.get_redirection(libname, pe_name) - ad_base_lib = loader.lib_get_add_base(libname) - ad_funcname = loader.lib_get_add_func(ad_base_lib, funcname, ad) - - libname_s = canon_libname_libfunc(libname, funcname) - dyn_funcs[libname_s] = ad_funcname - if patch_vm_imp: - vm.set_mem( - ad, struct.pack(cstruct.size2type[e._wsize], ad_funcname) - ) - return dyn_funcs - - def is_redirected_export(pe_obj, addr): """Test if the @addr is a forwarded export address. If so, return dllname/function name couple. If not, return False. @@ -141,7 +85,7 @@ def is_redirected_export(pe_obj, addr): return dllname, func_info -def get_export_name_addr_list(e): +def get_export_name_addr_list(e, parent=None): """Collect names/ordinals and addresses of symbols exported by the given PE. @e: PE instance Returns a list of tuples: @@ -190,7 +134,7 @@ def vm_load_pe(vm, fdata, align_s=True, load_hdr=True, name="", winobjs=None, ba # Parse and build a PE instance pe = pe_init.PE(fdata, **kargs) - # Optionaly rebase PE + # Optionally rebase PE if base_addr is not None: pe.reloc_to(base_addr) @@ -301,43 +245,6 @@ def vm_load_pe(vm, fdata, align_s=True, load_hdr=True, name="", winobjs=None, ba return pe -def vm_load_pe_lib(vm, fname_in, loader, lib_path_base, **kargs): - """Call vm_load_pe on @fname_in and update @loader accordingly - @vm: VmMngr instance - @fname_in: library name - @loader: LoaderWindows instance - @lib_path_base: DLLs relative path - Return the corresponding PE instance - Extra arguments are passed to vm_load_pe - """ - - log.info('Loading module %r', fname_in) - - fname = os.path.join(lib_path_base, fname_in) - with open(fname, "rb") as fstream: - pe = loader.vm_load_pe(vm, fstream.read(), name=fname_in, **kargs) - loader.add_export_lib(pe, fname_in) - return pe - - -def vm_load_pe_libs(vm, libs_name, loader, lib_path_base, **kargs): - """Call vm_load_pe_lib on each @libs_name filename - @vm: VmMngr instance - @libs_name: list of str - @loader: LoaderWindows instance - @lib_path_base: (optional) DLLs relative path - Return a dictionary Filename -> PE instances - Extra arguments are passed to vm_load_pe_lib - """ - out = {} - for fname in libs_name: - assert isinstance(fname, str) - out[fname] = vm_load_pe_lib(vm, fname, loader, lib_path_base, **kargs) - - return out - - - def vm2pe(myjit, fname, loader=None, e_orig=None, min_addr=None, max_addr=None, min_section_offset=0x1000, img_base=None, @@ -387,11 +294,6 @@ def vm2pe(myjit, fname, loader=None, e_orig=None, data=all_mem[ad]['data']) first = False if loader: - if added_funcs is not None: - for addr, funcaddr in added_funcs: - libbase, dllname = loader.fad2info[funcaddr] - loader.lib_get_add_func(libbase, dllname, addr) - filter_import = kwargs.get( 'filter_import', lambda _, ad: mye.virt.is_addr_in(ad)) new_dll = loader.gen_new_lib(mye, filter_import) @@ -428,108 +330,28 @@ def vm2pe(myjit, fname, loader=None, e_orig=None, class LoaderWindows(Loader): - def __init__(self, *args, apiset=None, loader_start_address=None, **kwargs): - super(LoaderWindows, self).__init__(*args, **kwargs) + def __init__(self, vm, apiset=None, loader_start_address=None, *args, **kwargs): + super(LoaderWindows, self).__init__(vm, *args, **kwargs) + self.library_path = ["win_dll", "./"] # dependency -> redirector self.created_redirected_imports = {} + self.module_name_to_module = {} self.apiset = apiset self.loader_start_address = loader_start_address + def lib_get_add_base(self, name): + name = name.lower().strip(' ') + if not "." in name: + log.warning('warning adding .dll to modulename') + name += '.dll' + log.warning(name) - def add_function(self, dllname, imp_ord_or_name, addr): - assert isinstance(dllname, str) - assert isinstance(imp_ord_or_name, (int, str)) - libad = self.name2off[dllname] - c_name = canon_libname_libfunc( - dllname, imp_ord_or_name - ) - update_entry = True - if addr in self.fad2info: - known_libad, known_imp_ord_or_name = self.fad2info[addr] - if isinstance(imp_ord_or_name, int): - update_entry = False - self.cname2addr[c_name] = addr - log.debug("Add func %s %s", hex(addr), c_name) - if update_entry: - log.debug("Real Add func %s %s", hex(addr), c_name) - self.fad2cname[addr] = c_name - self.fad2info[addr] = libad, imp_ord_or_name - - - def add_export_lib(self, e, name): - if name in self.created_redirected_imports: - log.error("%r has previously been created due to redirect\ - imports due to %r. Change the loading order.", - name, self.created_redirected_imports[name]) - raise RuntimeError('Bad import: loading previously created import') - - self.all_exported_lib.append(e) - # will add real lib addresses to database - if name in self.name2off: - ad = self.name2off[name] - if e is not None and name in self.fake_libs: - log.error( - "You are trying to load %r but it has been faked previously. Try loading this module earlier.", name) - raise RuntimeError("Bad import") + if name in self.module_name_to_base_address: + ad = self.module_name_to_base_address[name] else: - log.debug('new lib %s', name) - ad = e.NThdr.ImageBase - libad = ad - self.name2off[name] = ad - self.libbase2lastad[ad] = ad + 0x1 - self.lib_imp2ad[ad] = {} - self.lib_imp2dstad[ad] = {} - self.libbase_ad += 0x1000 - - ads = get_export_name_addr_list(e) - todo = list(ads) - # done = [] - while todo: - # for imp_ord_or_name, ad in ads: - imp_ord_or_name, ad = todo.pop() - - # if export is a redirection, search redirected dll - # and get function real addr - ret = is_redirected_export(e, ad) - if ret: - exp_dname, exp_fname = ret - exp_dname = exp_dname + '.dll' - exp_dname = exp_dname.lower() - # if dll auto refes in redirection - if exp_dname == name: - libad_tmp = self.name2off[exp_dname] - if isinstance(exp_fname, str): - exp_fname = bytes(ord(c) for c in exp_fname) - found = None - for tmp_func, tmp_addr in ads: - if tmp_func == exp_fname: - found = tmp_addr - assert found is not None - ad = found - else: - # import redirected lib from non loaded dll - if not exp_dname in self.name2off: - self.created_redirected_imports.setdefault( - exp_dname, set()).add(name) - - # Ensure import entry is created - new_lib_base = self.lib_get_add_base(exp_dname) - # Ensure function entry is created - _ = self.lib_get_add_func(new_lib_base, exp_fname) - - libad_tmp = self.name2off[exp_dname] - ad = self.lib_imp2ad[libad_tmp][exp_fname] - - self.lib_imp2ad[libad][imp_ord_or_name] = ad - name_inv = dict( - (value, key) for key, value in viewitems(self.name2off) - ) - c_name = canon_libname_libfunc( - name_inv[libad], imp_ord_or_name) - self.fad2cname[ad] = c_name - self.cname2addr[c_name] = ad - log.debug("Add func %s %s", hex(ad), c_name) - self.fad2info[ad] = libad, imp_ord_or_name + ad = self.fake_library_entry(name) + return ad + def gen_new_lib(self, target_pe, filter_import=lambda peobj, ad: True, **kwargs): """Gen a new DirImport description @@ -538,12 +360,24 @@ def gen_new_lib(self, target_pe, filter_import=lambda peobj, ad: True, **kwargs) """ new_lib = [] - for lib_name, ad in viewitems(self.name2off): + module_to_dsts = {} + for canonical_name, dsts in self.canonical_name_to_dst_addr.items(): + address = self.function_canonical_name_to_address[canonical_name] + module_name, imp_ord_or_name = self.function_address_to_info[address] + if module_name not in module_to_dsts: + module_to_dsts[module_name] = {} + module_to_dsts[module_name].setdefault(imp_ord_or_name, set()).update(dsts) + #for lib_name, ad in viewitems(self.module_name_to_base_address): + for module_name, info_dsts in module_to_dsts.items(): # Build an IMAGE_IMPORT_DESCRIPTOR # Get fixed addresses out_ads = dict() # addr -> func_name - for func_name, dst_addresses in viewitems(self.lib_imp2dstad[ad]): + """ + if ad not in self.lib_imp2dstad: + continue + """ + for func_name, dst_addresses in info_dsts.items(): out_ads.update({addr: func_name for addr in dst_addresses}) # Filter available addresses according to @filter_import @@ -578,7 +412,7 @@ def gen_new_lib(self, target_pe, filter_import=lambda peobj, ad: True, **kwargs) except pe.InvalidOffset: pass else: - new_lib.append(({"name": lib_name, + new_lib.append(({"name": module_name, "firstthunk": rva}, funcs) ) @@ -588,9 +422,9 @@ def gen_new_lib(self, target_pe, filter_import=lambda peobj, ad: True, **kwargs) return new_lib - def vm_load_pe(self, vm, fdata, align_s=True, load_hdr=True, name="", winobjs=None, **kargs): + def vm_load_pe(self, fdata, align_s=True, load_hdr=True, name="", winobjs=None, **kargs): pe = vm_load_pe( - vm, fdata, + self.vm, fdata, align_s=align_s, load_hdr=load_hdr, name=name, winobjs=winobjs, @@ -601,119 +435,131 @@ def vm_load_pe(self, vm, fdata, align_s=True, load_hdr=True, name="", winobjs=No self.loader_start_address += pe.NThdr.sizeofimage + 0x1000 return pe - -class limbimp_pe(LoaderWindows): - def __init__(self, *args, **kwargs): - warnings.warn("DEPRECATION WARNING: Use LoaderWindows instead of limimb_pe") - super(limbimp_pe, self).__init__(*args, **kwargs) + def find_module_path(self, module_name): + """ + Find the real path of module_name + """ + module_name = module_name.lower() + for path in self.library_path: + fname = os.path.join(path, module_name) + if os.access(fname, os.R_OK): + return fname + if module_name in self.unresolved_modules_names: + return None + self.fake_library_entry(module_name) + return None + + + def resolve_function(self, module_name, imp_ord_or_name, parent=None, dst_ad=None): + """ + Resolve the function named @imp_ord_or_name of the module @module_name + Optionally use @parent for ApiSet resolution + Use @dst_ad to hint the destination address of the function + """ + if self.apiset: + # First, try to resolve ApiSet + module_name = self.apiset.get_redirection(module_name, parent) + + if module_name in self.unresolved_modules_names: + module_base_addr = self.module_name_to_base_address[module_name] + addr = self.fake_resolve_function(module_base_addr, imp_ord_or_name, dst_ad=dst_ad) + self.add_function(module_name, imp_ord_or_name, addr, dst_ad=dst_ad) + return addr + + if module_name not in self.module_name_to_module: + raise RuntimeError("Module %r not found" % module_name) + pe = self.module_name_to_module[module_name] + export = self.module_name_to_export[module_name] + addr = export.get(imp_ord_or_name, None) + if addr is None: + raise RuntimeError("Function %r not found in %r" %( imp_ord_or_name, module_name)) + ret = is_redirected_export(pe, addr) + if ret is False: + self.add_function(module_name, imp_ord_or_name, addr, dst_ad=dst_ad) + return addr + + module_target, func_info = ret + log.debug( + "Function %r %r redirected to %r %r", + module_name, imp_ord_or_name, + module_target, func_info + ) -def vm_load_pe_and_dependencies(vm, fname, name2module, loader, - lib_path_base, **kwargs): - """Load a binary and all its dependencies. Returns a dictionary containing - the association between binaries names and it's pe object + module_target += '.dll' - @vm: virtual memory manager instance - @fname: full path of the binary - @name2module: dict containing association between name and pe - object. Updated. - @loader: Loader instance - @lib_path_base: directory of the libraries containing dependencies + # First, try to resolve ApiSet + if self.apiset: + module_target = self.apiset.get_redirection(module_target, module_name) - """ + self.load_module(module_target) + addr = self.resolve_function(module_target, func_info, module_name, dst_ad=dst_ad) + self.add_function(module_target, imp_ord_or_name, addr, dst_ad=dst_ad) + return addr - todo = [(fname, fname, 0)] - weight2name = {} - done = set() + def load_module(self, name): + """ + Load module and it's dependencies + Return image base address of the module + """ + name = name.lower() + fname = self.find_module_path(name) + if fname is None: + raise RuntimeError("Cannot find module %r" % fname) + + if name in self.unresolved_modules_names: + return self.module_name_to_base_address[name] + + module_address = self.module_name_to_base_address.get(name, None) + if module_address is not None: + # Module is already loaded + return module_address + #log.info("load module %r %r", name, fname) + try: + with open(fname, "rb") as fstream: + log.info('Loading module name %r', fname) + pe = self.vm_load_pe( + fstream.read(), name=fname + ) + except IOError: + raise RuntimeError('Cannot open module %s' % fname) + + image_base = pe.NThdr.ImageBase + self.module_name_to_module[name] = pe + exports = get_export_name_addr_list(pe) + self.module_name_to_export[name] = dict(exports) + self.module_name_to_base_address[name] = pe.NThdr.ImageBase + self.module_base_address_to_name[pe.NThdr.ImageBase] = name + + # Resolve imports + if pe.DirImport.impdesc is None: + # No imports + return image_base + out = set() + for dependency in pe.DirImport.impdesc: + libname = dependency.dlldescname.name.lower() + libname = force_str(libname) + if self.apiset: + # Resolve ApiSet + libname = self.apiset.get_redirection(libname, name) + self.load_module(libname) + + # Fix imports + import_information = get_import_address_pe(pe) + dyn_funcs = {} + # log.debug('imported funcs: %s' % import_information) + for (libname, funcname), ads in import_information.items(): + addr_resolved = self.resolve_function(libname, funcname, name) + addr_bytes = struct.pack(cstruct.size2type[pe._wsize], addr_resolved) + for addr in ads: + self.vm.set_mem(addr, addr_bytes) + return image_base - # Walk dependencies recursively - while todo: - name, fname, weight = todo.pop() - if name in done: - continue - done.add(name) - weight2name.setdefault(weight, set()).add(name) - if name in name2module: - pe_obj = name2module[name] - else: - try: - with open(fname, "rb") as fstream: - log.info('Loading module name %r', fname) - pe_obj = loader.vm_load_pe( - vm, fstream.read(), name=fname, **kwargs - ) - except IOError: - log.error('Cannot open %s' % fname) - name2module[name] = None - continue - name2module[name] = pe_obj - - new_dependencies = get_pe_dependencies(pe_obj) - for libname in new_dependencies: - if loader.apiset: - libname = loader.apiset.get_redirection(libname, name) - todo.append((libname, os.path.join(lib_path_base, libname), weight - 1)) - - known_export_addresses = {} - to_resolve = {} - for name, pe_obj in name2module.items(): - if pe_obj is None: - continue - if pe_obj.DirExport.expdesc == None: - continue - addrs = get_export_name_addr_list(pe_obj) - for imp_ord_or_name, ad in addrs: - # if export is a redirection, search redirected dll - # and get function real addr - ret = is_redirected_export(pe_obj, ad) - if ret is False: - known_export_addresses[(name, imp_ord_or_name)] = ad - else: - dllname, func_info = ret - - dllname = loader.apiset.get_redirection(dllname, name) - - dllname = dllname + '.dll' - to_resolve[(name, imp_ord_or_name)] = (dllname, func_info) - - modified = True - while modified: - modified = False - out = {} - for target, dependency in to_resolve.items(): - dllname, funcname = dependency - if dependency in known_export_addresses: - known_export_addresses[target] = known_export_addresses[dependency] - modified = True - else: - log.error("Cannot resolve redirection %r %r", dllname, dependency) - raise RuntimeError('Cannot resolve redirection') - to_resolve = out - for dllname, pe_obj in name2module.items(): - if pe_obj is None: - continue - ad = pe_obj.NThdr.ImageBase - libad = ad - loader.name2off[dllname] = ad - loader.libbase2lastad[ad] = ad + 0x1 - loader.lib_imp2ad[ad] = {} - loader.lib_imp2dstad[ad] = {} - loader.libbase_ad += 0x1000 - - for (dllname, imp_ord_or_name), addr in known_export_addresses.items(): - loader.add_function(dllname, imp_ord_or_name, addr) - libad = loader.name2off[dllname] - loader.lib_imp2ad[libad][imp_ord_or_name] = addr - - assert not to_resolve - - for dllname, pe_obj in name2module.items(): - if pe_obj is None: - continue - fix_pe_imports(vm, pe_obj, loader, patch_vm_imp=True, pe_name=dllname) +class limbimp_pe(LoaderWindows): + def __init__(self, *args, **kwargs): + raise DeprecationWarning("DEPRECATION WARNING: Use LoaderWindows instead of limimb_pe") - return name2module # machine -> arch PE_machine = { @@ -744,6 +590,7 @@ def compute_hash(self, apiset_lib_name): return hashk def get_redirected_host(self, libname, entries, parent): + #log.info("\tlibname %r %r", parent, libname) if len(entries) == 1: assert "" in entries log.debug("ApiSet %s => %s" % (libname, entries[""])) @@ -767,7 +614,13 @@ def get_redirection(self, libname, parent_name): cname = name_nodll[:name_nodll.rfind('-')] else: cname = name_nodll - values = self.hash_entries.get(cname, None) + #log.info("\t cname %r", cname) + values = self.hash_entries.get( + cname, + self.hash_entries.get( + cname+"-1", None + ) + ) if not values: # No entry found return libname diff --git a/miasm/jitter/loader/utils.py b/miasm/jitter/loader/utils.py index 4cd08b13f..547f868fd 100644 --- a/miasm/jitter/loader/utils.py +++ b/miasm/jitter/loader/utils.py @@ -1,4 +1,5 @@ from builtins import int as int_types +import warnings import logging from future.utils import viewitems, viewvalues @@ -23,69 +24,90 @@ def canon_libname_libfunc(libname, libfunc): class Loader(object): - def __init__(self, lib_base_ad=0x71111000, **kargs): - self.name2off = {} - self.libbase2lastad = {} - self.libbase_ad = lib_base_ad - self.lib_imp2ad = {} - self.lib_imp2dstad = {} - self.fad2cname = {} - self.cname2addr = {} - self.fad2info = {} - self.all_exported_lib = [] - self.fake_libs = set() + def __init__(self, vm, lib_base_ad=0x71111000, **kargs): + self.vm = vm + + self.module_name_to_base_address = {} + self.module_base_address_to_name = {} + + self.function_address_to_canonical_name = {} + self.function_canonical_name_to_address = {} + + self.module_base_address_to_last_address = {} + self.last_module_address = lib_base_ad + self.module_name_to_export = {} + self.canonical_name_to_dst_addr = {} + self.function_address_to_info = {} + self.unresolved_modules_names = set() + + def get_name2off(self): + warnings.warn("Deprecated API: use .module_name_to_base_address(name) instead of name2off") + return self.module_name_to_base_address + + def get_fad2cname(self): + warnings.warn("Deprecated API: use .module_address_to_name(addr) instead of fad2cname") + return self.function_address_to_canonical_name + + + name2off = property(get_name2off) + fad2cname = property(get_fad2cname) + + def fake_library_entry(self, module_name): + addr = self.last_module_address + log.warning("Create dummy entry for %r", module_name) + self.unresolved_modules_names.add(module_name) + self.module_name_to_base_address[module_name] = addr + self.module_base_address_to_name[addr] = module_name + self.module_base_address_to_last_address[addr] = addr + 0x4 + self.module_name_to_export[module_name] = {} + self.last_module_address += 0x1000 + return addr def lib_get_add_base(self, name): - assert isinstance(name, basestring) - name = name.lower().strip(' ') - if not "." in name: - log.warning('warning adding .dll to modulename') - name += '.dll' - log.warning(name) - - if name in self.name2off: - ad = self.name2off[name] - else: - ad = self.libbase_ad - log.warning("Create dummy entry for %r", name) - self.fake_libs.add(name) - self.name2off[name] = ad - self.libbase2lastad[ad] = ad + 0x4 - self.lib_imp2ad[ad] = {} - self.lib_imp2dstad[ad] = {} - self.libbase_ad += 0x1000 - return ad + raise NotImplementedError("Implement in sub class") def lib_get_add_func(self, libad, imp_ord_or_name, dst_ad=None): - if not libad in viewvalues(self.name2off): - raise ValueError('unknown lib base!', hex(libad)) + raise DeprecationWarning("Use resolve_function instead of lib_get_add_func") + + def load_module(self, vm, libname): + raise NotImplementedError("Implement in sub class") + + def add_function(self, module_name, imp_ord_or_name, addr, dst_ad=None): + canonical_name = canon_libname_libfunc( + module_name, imp_ord_or_name + ) + self.function_address_to_info[addr] = module_name, imp_ord_or_name + + if dst_ad is not None: + self.canonical_name_to_dst_addr.setdefault(canonical_name, set()).add(dst_ad) + + self.function_address_to_canonical_name[addr] = canonical_name + self.function_canonical_name_to_address[canonical_name] = addr + + return canonical_name + + def fake_resolve_function(self, module_address, imp_ord_or_name, dst_ad=None): + module_name = self.module_base_address_to_name.get(module_address, None) + if module_name is None: + raise ValueError('unknown lib base!', hex(module_address)) # test if not ordinatl # if imp_ord_or_name >0x10000: # imp_ord_or_name = vm_get_str(imp_ord_or_name, 0x100) # imp_ord_or_name = imp_ord_or_name[:imp_ord_or_name.find('\x00')] - #/!\ can have multiple dst ad - if not imp_ord_or_name in self.lib_imp2dstad[libad]: - self.lib_imp2dstad[libad][imp_ord_or_name] = set() - if dst_ad is not None: - self.lib_imp2dstad[libad][imp_ord_or_name].add(dst_ad) - - if imp_ord_or_name in self.lib_imp2ad[libad]: - return self.lib_imp2ad[libad][imp_ord_or_name] + if imp_ord_or_name in self.module_name_to_export[module_name]: + return self.module_name_to_export[module_name][imp_ord_or_name] log.debug('new imp %s %s' % (imp_ord_or_name, dst_ad)) - ad = self.libbase2lastad[libad] - self.libbase2lastad[libad] += 0x10 # arbitrary - self.lib_imp2ad[libad][imp_ord_or_name] = ad + addr = self.module_base_address_to_last_address[module_address] + canonical_name = self.add_function(module_name, imp_ord_or_name, addr, dst_ad=dst_ad) - name_inv = dict( - (value, key) for key, value in viewitems(self.name2off) - ) - c_name = canon_libname_libfunc(name_inv[libad], imp_ord_or_name) - self.fad2cname[ad] = c_name - self.cname2addr[c_name] = ad - self.fad2info[ad] = libad, imp_ord_or_name - return ad + + self.module_base_address_to_last_address[module_address] += 0x10 # arbitrary + self.module_name_to_export[module_name][imp_ord_or_name] = addr + self.function_canonical_name_to_address[canonical_name] = addr + self.function_address_to_info[addr] = module_name, imp_ord_or_name + return addr def check_dst_ad(self): for ad in self.lib_imp2dstad: diff --git a/miasm/os_dep/win_api_x86_32.py b/miasm/os_dep/win_api_x86_32.py index 734666fb6..bc887bd9c 100644 --- a/miasm/os_dep/win_api_x86_32.py +++ b/miasm/os_dep/win_api_x86_32.py @@ -913,11 +913,11 @@ def kernel32_GetModuleFileName(jitter, funcname, set_str): if args.hmodule in [0, winobjs.hcurmodule]: p = winobjs.module_path[:] elif (winobjs.loader and - args.hmodule in viewvalues(winobjs.loader.name2off)): + args.hmodule in viewvalues(winobjs.loader.module_name_to_base_address)): name_inv = dict( [ (x[1], x[0]) - for x in viewitems(winobjs.loader.name2off) + for x in viewitems(winobjs.loader.module_name_to_base_address) ] ) p = name_inv[args.hmodule] @@ -1029,9 +1029,9 @@ def kernel32_LoadLibrary(jitter, get_str): ret_ad, args = jitter.func_args_stdcall(["dllname"]) libname = get_str(args.dllname, 0x100) - ret = winobjs.loader.lib_get_add_base(libname) - log.info("Loading %r ret 0x%x", libname, ret) - jitter.func_ret_stdcall(ret_ad, ret) + module_image_base = winobjs.loader.load_module(libname) + log.info("Loading %r ret 0x%x", libname, module_image_base) + jitter.func_ret_stdcall(ret_ad, module_image_base) def kernel32_LoadLibraryA(jitter): @@ -1069,7 +1069,8 @@ def kernel32_GetProcAddress(jitter): if not fname: fname = None if fname is not None: - ad = winobjs.loader.lib_get_add_func(args.libbase, fname) + name = winobjs.loader.module_base_address_to_name[args.libbase] + ad = winobjs.loader.resolve_function(name, fname) else: ad = 0 log.info("GetProcAddress %r %r ret 0x%x", args.libbase, fname, ad) @@ -2010,7 +2011,8 @@ def ntdll_LdrGetProcedureAddress(jitter): l1, l2, p_src = struct.unpack('HHI', jitter.vm.get_mem(args.pfname, 0x8)) fname = get_win_str_a(jitter, p_src) - ad = winobjs.loader.lib_get_add_func(args.libbase, fname) + name = winobjs.loader.module_base_address_to_name[args.libbase] + ad = winobjs.resolve_function(name, fname) jitter.add_breakpoint(ad, jitter.handle_lib) jitter.vm.set_u32(args.p_ad, ad) From b591cb9b62c5f648371ccebd10bf95b14ca42c9c Mon Sep 17 00:00:00 2001 From: Fabrice Desclaux Date: Mon, 2 Nov 2020 17:15:02 +0100 Subject: [PATCH 09/12] Fix absent reloc --- miasm/loader/pe_init.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/miasm/loader/pe_init.py b/miasm/loader/pe_init.py index 2ef84ba0d..5319f20c1 100644 --- a/miasm/loader/pe_init.py +++ b/miasm/loader/pe_init.py @@ -612,8 +612,9 @@ def export_funcs(self): def reloc_to(self, imgbase): offset = imgbase - self.NThdr.ImageBase - if self.DirReloc is None: - log.warn('no relocation found!') + if self.DirReloc is None or self.DirReloc.reldesc is None: + log.warn('No relocation found') + return for rel in self.DirReloc.reldesc: rva = rel.rva for reloc in rel.rels: From 9cb6e2255852d4cbcf1fd821df186bdf63a7b740 Mon Sep 17 00:00:00 2001 From: Fabrice Desclaux Date: Mon, 2 Nov 2020 17:16:46 +0100 Subject: [PATCH 10/12] Add load resolved module --- miasm/analysis/sandbox.py | 2 +- miasm/jitter/loader/pe.py | 14 +++++++++++--- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/miasm/analysis/sandbox.py b/miasm/analysis/sandbox.py index b145c48ca..e97b1d5f2 100644 --- a/miasm/analysis/sandbox.py +++ b/miasm/analysis/sandbox.py @@ -250,7 +250,7 @@ def load_main_pe(self, options): from miasm.jitter.loader.pe import vm_load_pe from miasm.os_dep.win_api_x86_32 import winobjs - module_image_base = self.loader.load_module(options.filename) + module_image_base = self.loader.load_resolved_module(options.filename, options.filename) name = self.loader.module_base_address_to_name[module_image_base] self.pe = self.loader.module_name_to_module[name] winobjs.current_pe = self.pe diff --git a/miasm/jitter/loader/pe.py b/miasm/jitter/loader/pe.py index a2ff96afb..10133de92 100644 --- a/miasm/jitter/loader/pe.py +++ b/miasm/jitter/loader/pe.py @@ -499,16 +499,24 @@ def resolve_function(self, module_name, imp_ord_or_name, parent=None, dst_ad=Non def load_module(self, name): """ - Load module and it's dependencies + Resolve the path of @name and load module and it's dependencies + Return image base address of the module + """ name = name.lower() fname = self.find_module_path(name) - if fname is None: - raise RuntimeError("Cannot find module %r" % fname) + return self.load_resolved_module(name, fname) + def load_resolved_module(self, name, fname): + """ + Load module @name using its @fname path and it's dependencies + Return image base address of the module + """ if name in self.unresolved_modules_names: return self.module_name_to_base_address[name] + if fname is None: + raise RuntimeError("Cannot find module %r" % fname) module_address = self.module_name_to_base_address.get(name, None) if module_address is not None: From 8dce07ab9575efb87e34e67ac54ed2ce50ea24df Mon Sep 17 00:00:00 2001 From: Fabrice Desclaux Date: Mon, 2 Nov 2020 17:17:38 +0100 Subject: [PATCH 11/12] Add fake dll load --- miasm/analysis/sandbox.py | 16 ++++++++++++++-- miasm/jitter/loader/pe.py | 6 +++++- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/miasm/analysis/sandbox.py b/miasm/analysis/sandbox.py index e97b1d5f2..b18ebf956 100644 --- a/miasm/analysis/sandbox.py +++ b/miasm/analysis/sandbox.py @@ -232,7 +232,10 @@ def init_loader(self, options): loader_start_address = int(options.loader_start_address, 0) else: loader_start_address = None - loader = LoaderWindows(self.jitter.vm, loader_start_address=loader_start_address) + loader = LoaderWindows( + self.jitter.vm, loader_start_address=loader_start_address, + fake_dll_load=options.fake_dll_load + ) self.loader = loader winobjs.loader = loader @@ -298,6 +301,12 @@ def update_parser(cls, parser): parser.add_argument( "-r", "--parse-resources", action="store_true", help="Load resources" ) + parser.add_argument( + "-f", + "--fake-dll-load", + action="store_true", + help="Don't load dll real dll, create fake entries", + ) parser.add_argument( "-i", "--dependencies", @@ -365,7 +374,10 @@ def init_loader(self, options): loader_start_address = int(options.loader_start_address, 0) else: loader_start_address = None - loader = LoaderWindows(self.jitter.vm, apiset=apiset, loader_start_address=loader_start_address) + loader = LoaderWindows( + self.jitter.vm, apiset=apiset, loader_start_address=loader_start_address, + fake_dll_load=options.fake_dll_load + ) self.loader = loader winobjs.loader = loader diff --git a/miasm/jitter/loader/pe.py b/miasm/jitter/loader/pe.py index 10133de92..3d87a74fc 100644 --- a/miasm/jitter/loader/pe.py +++ b/miasm/jitter/loader/pe.py @@ -330,7 +330,7 @@ def vm2pe(myjit, fname, loader=None, e_orig=None, class LoaderWindows(Loader): - def __init__(self, vm, apiset=None, loader_start_address=None, *args, **kwargs): + def __init__(self, vm, apiset=None, loader_start_address=None, fake_dll_load=False, *args, **kwargs): super(LoaderWindows, self).__init__(vm, *args, **kwargs) self.library_path = ["win_dll", "./"] # dependency -> redirector @@ -338,6 +338,7 @@ def __init__(self, vm, apiset=None, loader_start_address=None, *args, **kwargs): self.module_name_to_module = {} self.apiset = apiset self.loader_start_address = loader_start_address + self.fake_dll_load = fake_dll_load def lib_get_add_base(self, name): name = name.lower().strip(' ') @@ -440,6 +441,9 @@ def find_module_path(self, module_name): Find the real path of module_name """ module_name = module_name.lower() + if self.fake_dll_load: + self.fake_library_entry(module_name) + return None for path in self.library_path: fname = os.path.join(path, module_name) if os.access(fname, os.R_OK): From ae9a47b5fb511db04f66d5e716e6056e1ea469da Mon Sep 17 00:00:00 2001 From: Fabrice Desclaux Date: Thu, 7 Jan 2021 11:44:24 +0100 Subject: [PATCH 12/12] Add ir_arch deprecation warning --- miasm/jitter/jitload.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/miasm/jitter/jitload.py b/miasm/jitter/jitload.py index 5c44d2477..2ea4e0a88 100644 --- a/miasm/jitter/jitload.py +++ b/miasm/jitter/jitload.py @@ -261,6 +261,11 @@ def __init__(self, lifter, jit_type="gcc"): self.init_exceptions_handler() self.exec_cb = None + @property + def ir_arch(self): + warnings.warn('DEPRECATION WARNING: use ".lifter" instead of ".ir_arch"') + return self.lifter + def init_exceptions_handler(self): "Add common exceptions handlers"