diff options
Diffstat (limited to 'miasm/analysis/sandbox.py')
| -rw-r--r-- | miasm/analysis/sandbox.py | 1033 |
1 files changed, 0 insertions, 1033 deletions
diff --git a/miasm/analysis/sandbox.py b/miasm/analysis/sandbox.py deleted file mode 100644 index e51fd45a..00000000 --- a/miasm/analysis/sandbox.py +++ /dev/null @@ -1,1033 +0,0 @@ -from __future__ import print_function -from builtins import range - -import os -import logging -from argparse import ArgumentParser - -from future.utils import viewitems, viewvalues -from past.builtins import basestring - -from miasm.analysis.machine import Machine -from miasm.jitter.csts import PAGE_READ, PAGE_WRITE -from miasm.analysis import debugging -from miasm.jitter.jitload import log_func -from miasm.core.utils import force_bytes - - -class Sandbox(object): - - """ - Parent class for Sandbox abstraction - """ - - CALL_FINISH_ADDR = 0x13371acc - - @staticmethod - def code_sentinelle(jitter): - jitter.running = False - 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 - ) - - if not self.options.quiet_function_calls: - log_func.setLevel(logging.INFO) - - @classmethod - def parser(cls, *args, **kwargs): - """ - Return instance of instance parser with expecting options. - Extra parameters are passed to parser initialisation. - """ - - 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) - return parser - - 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: - addr = int(self.options.address, 0) - - if any([self.options.debugging, self.options.gdbserver]): - dbg = debugging.Debugguer(self.jitter) - self.dbg = dbg - dbg.init_run(addr) - - if self.options.gdbserver: - port = self.options.gdbserver - print("Listen on port %d" % port) - gdb = self.machine.gdbserver(dbg, port) - self.gdb = gdb - gdb.run() - else: - cmd = debugging.DebugCmd(dbg) - self.cmd = cmd - cmd.cmdloop() - - else: - self.jitter.init_run(addr) - self.jitter.continue_run() - - def call(self, prepare_cb, addr, *args): - """ - Direct call of the function at @addr, with arguments @args prepare in - calling convention implemented by @prepare_cb - @prepare_cb: func(ret_addr, *args) - @addr: address of the target function - @args: arguments - """ - self.jitter.init_run(addr) - self.jitter.add_breakpoint(self.CALL_FINISH_ADDR, self.code_sentinelle) - prepare_cb(self.CALL_FINISH_ADDR, *args) - self.jitter.continue_run() - - - -class OS(object): - - """ - Parent class for OS abstraction - """ - - def __init__(self, custom_methods, **kwargs): - pass - - @classmethod - def update_parser(cls, parser): - pass - - -class Arch(object): - - """ - Parent class for Arch abstraction - """ - - # Architecture name - _ARCH_ = None - - 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 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", - ] - 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 - 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__)) - methods.update(custom_methods) - - super(OS_Win, self).__init__(methods, *args, **kwargs) - - # Import manager - libs = libimp_pe() - self.libs = libs - win_api_x86_32.winobjs.runtime_dll = libs - - self.name2module = {} - fname_basename = os.path.basename(self.fname).lower() - - # Load main pe - with open(self.fname, "rb") as fstream: - self.pe = vm_load_pe( - self.jitter.vm, - fstream.read(), - load_hdr=self.options.load_hdr, - name=self.fname, - winobjs=win_api_x86_32.winobjs, - **kwargs - ) - self.name2module[fname_basename] = self.pe - - # Load library - if self.options.loadbasedll: - - # Load libs in memory - self.name2module.update( - vm_load_pe_libs( - self.jitter.vm, - self.ALL_IMP_DLL, - libs, - self.modules_path, - winobjs=win_api_x86_32.winobjs, - **kwargs - ) - ) - - # Patch libs imports - for pe in viewvalues(self.name2module): - preload_pe(self.jitter.vm, pe, libs) - - if self.options.dependencies: - vm_load_pe_and_dependencies( - self.jitter.vm, - fname_basename, - self.name2module, - libs, - self.modules_path, - 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) - - # Library calls handler - self.jitter.add_lib_handler(libs, methods) - - # Manage SEH - if self.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.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" - ) - - # 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 Arch_x86_32(Arch_x86): - _ARCH_ = "x86_32" - - -class Arch_x86_64(Arch_x86): - _ARCH_ = "x86_64" - - -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) - - # Init stack - self.jitter.stack_size = self.STACK_SIZE - self.jitter.stack_base = self.STACK_BASE - self.jitter.init_stack() - - -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() - - -class Arch_armtl(Arch): - _ARCH_ = "armtl" - STACK_SIZE = 0x100000 - STACK_BASE = 0x100000 - - 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 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() - - -class Arch_aarch64l(Arch): - _ARCH_ = "aarch64l" - STACK_SIZE = 0x100000 - STACK_BASE = 0x100000 - - def __init__(self, loc_db, **kwargs): - super(Arch_aarch64l, 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 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() - -class Arch_ppc(Arch): - _ARCH_ = None - -class Arch_ppc32(Arch): - _ARCH_ = None - -class Arch_ppc32b(Arch_ppc32): - _ARCH_ = "ppc32b" - -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) - - # 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) - - # 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_Win_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_stdcall) - super(self.__class__, self).call(prepare_cb, addr, *args) - - -class Sandbox_Win_x86_64(Sandbox, Arch_x86_64, OS_Win): - - def __init__(self, loc_db, *args, **kwargs): - Sandbox.__init__(self, loc_db, *args, **kwargs) - - # reserve stack for local reg - for _ in range(0x4): - self.jitter.push_uint64_t(0) - - # Pre-stack return address - 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 - ) - - 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, Arch_x86_32, 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.ESP -= len(env) - ptr = self.jitter.cpu.ESP - 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.ESP -= len(arg) - ptr = self.jitter.cpu.ESP - self.jitter.vm.set_mem(ptr, arg) - argv_ptrs.append(ptr) - - self.jitter.push_uint32_t(self.CALL_FINISH_ADDR) - self.jitter.push_uint32_t(0) - for ptr in reversed(env_ptrs): - self.jitter.push_uint32_t(ptr) - self.jitter.push_uint32_t(0) - for ptr in reversed(argv_ptrs): - self.jitter.push_uint32_t(ptr) - self.jitter.push_uint32_t(len(self.argv)) - else: - 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 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) - - # 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) - - 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_arml(Sandbox, Arch_arml, 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.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.SP -= len(arg) - ptr = self.jitter.cpu.SP - self.jitter.vm.set_mem(ptr, arg) - argv_ptrs.append(ptr) - - # Round SP to 4 - self.jitter.cpu.SP = self.jitter.cpu.SP & ~ 3 - - self.jitter.push_uint32_t(0) - for ptr in reversed(env_ptrs): - self.jitter.push_uint32_t(ptr) - self.jitter.push_uint32_t(0) - for ptr in reversed(argv_ptrs): - self.jitter.push_uint32_t(ptr) - self.jitter.push_uint32_t(len(self.argv)) - - self.jitter.cpu.LR = 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 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) - - -class Sandbox_Linux_armtl(Sandbox, Arch_armtl, 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.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.SP -= len(arg) - ptr = self.jitter.cpu.SP - self.jitter.vm.set_mem(ptr, arg) - argv_ptrs.append(ptr) - - # Round SP to 4 - self.jitter.cpu.SP = self.jitter.cpu.SP & ~ 3 - - self.jitter.push_uint32_t(0) - for ptr in reversed(env_ptrs): - self.jitter.push_uint32_t(ptr) - self.jitter.push_uint32_t(0) - for ptr in reversed(argv_ptrs): - self.jitter.push_uint32_t(ptr) - self.jitter.push_uint32_t(len(self.argv)) - - self.jitter.cpu.LR = 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 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) - - - -class Sandbox_Linux_mips32b(Sandbox, Arch_mips32b, 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.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.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.push_uint32_t(0) - for ptr in reversed(argv_ptrs): - self.jitter.push_uint32_t(ptr) - self.jitter.push_uint32_t(len(self.argv)) - - self.jitter.cpu.RA = 0x1337beef - - # Set the runtime guard - self.jitter.add_breakpoint( - 0x1337beef, - 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_armb_str(Sandbox, Arch_armb, OS_Linux_str): - - def __init__(self, loc_db, *args, **kwargs): - Sandbox.__init__(self, loc_db, *args, **kwargs) - - self.jitter.cpu.LR = 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): - - def __init__(self, loc_db, *args, **kwargs): - Sandbox.__init__(self, loc_db, *args, **kwargs) - - self.jitter.cpu.LR = 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_arml_str, self).run(addr) - - -class Sandbox_Linux_aarch64l(Sandbox, Arch_aarch64l, 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.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.SP -= len(arg) - ptr = self.jitter.cpu.SP - self.jitter.vm.set_mem(ptr, arg) - argv_ptrs.append(ptr) - - 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)) - - self.jitter.cpu.LR = 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 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_ppc32b(Sandbox, Arch_ppc32b, OS_Linux): - - STACK_SIZE = 0x10000 - STACK_BASE = 0xbfce0000 - - # 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) - - # 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 - - # 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.R1 -= len(env) - ptr = self.jitter.cpu.R1 - 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.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.cpu.LR = 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 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) |