diff options
| -rwxr-xr-x | example/jitter/arm.py | 3 | ||||
| -rw-r--r-- | example/jitter/sandbox_call.py | 23 | ||||
| -rw-r--r-- | miasm2/analysis/sandbox.py | 230 | ||||
| -rw-r--r-- | miasm2/arch/aarch64/jit.py | 14 | ||||
| -rw-r--r-- | miasm2/arch/arm/jit.py | 20 | ||||
| -rw-r--r-- | miasm2/arch/x86/jit.py | 72 | ||||
| -rw-r--r-- | miasm2/os_dep/linux_stdlib.py | 86 | ||||
| -rw-r--r-- | test/arch/x86/qemu/testqemu.py | 8 | ||||
| -rwxr-xr-x | test/os_dep/linux/test_env.aarch64l | bin | 0 -> 6168 bytes | |||
| -rwxr-xr-x | test/os_dep/linux/test_env.arml | bin | 0 -> 5608 bytes | |||
| -rw-r--r-- | test/os_dep/linux/test_env.c | 10 | ||||
| -rw-r--r-- | test/os_dep/linux/test_env.py | 36 | ||||
| -rwxr-xr-x | test/os_dep/linux/test_env.x86_32 | bin | 0 -> 5588 bytes | |||
| -rwxr-xr-x | test/os_dep/linux/test_env.x86_64 | bin | 0 -> 6312 bytes | |||
| -rwxr-xr-x | test/test_all.py | 9 |
15 files changed, 435 insertions, 76 deletions
diff --git a/example/jitter/arm.py b/example/jitter/arm.py index eac6c0e6..e475abeb 100755 --- a/example/jitter/arm.py +++ b/example/jitter/arm.py @@ -24,8 +24,5 @@ else: if options.verbose is True: print sb.jitter.vm -if options.address is None: - raise ValueError('Invalid address') - # Run the code sb.run() diff --git a/example/jitter/sandbox_call.py b/example/jitter/sandbox_call.py new file mode 100644 index 00000000..49365004 --- /dev/null +++ b/example/jitter/sandbox_call.py @@ -0,0 +1,23 @@ +"""This example illustrate the Sandbox.call API, for direct call of a given +function""" + +from miasm2.analysis.sandbox import Sandbox_Linux_arml +from miasm2.analysis.binary import Container +from miasm2.os_dep.linux_stdlib import linobjs +from miasm2.core.utils import hexdump + +# Parse arguments +parser = Sandbox_Linux_arml.parser(description="ELF sandboxer") +parser.add_argument("filename", help="ELF Filename") +options = parser.parse_args() + +sb = Sandbox_Linux_arml(options.filename, options, globals()) + +with open(options.filename) as fdesc: + cont = Container.from_stream(fdesc) + addr_to_call = cont.symbol_pool.getby_name("md5_starts").offset + +# Calling md5_starts(malloc(0x64)) +addr = linobjs.heap.alloc(sb.jitter, 0x64) +sb.call(addr_to_call, addr) +hexdump(sb.jitter.vm.get_mem(addr, 0x64)) diff --git a/miasm2/analysis/sandbox.py b/miasm2/analysis/sandbox.py index 87e84caf..3c29ace0 100644 --- a/miasm2/analysis/sandbox.py +++ b/miasm2/analysis/sandbox.py @@ -14,6 +14,8 @@ class Sandbox(object): Parent class for Sandbox abstraction """ + CALL_FINNISH_ADDR = 0x1337babe + @staticmethod def code_sentinelle(jitter): jitter.run = False @@ -126,6 +128,20 @@ class Sandbox(object): 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_FINNISH_ADDR, self.code_sentinelle) + prepare_cb(self.CALL_FINNISH_ADDR, *args) + self.jitter.continue_run() + + class OS(object): @@ -248,6 +264,8 @@ class OS_Win(OS): class OS_Linux(OS): + PROGRAM_PATH = "./program" + def __init__(self, custom_methods, *args, **kwargs): from miasm2.jitter.loader.elf import vm_load_elf, preload_elf, libimp_elf from miasm2.os_dep import linux_stdlib @@ -269,9 +287,30 @@ class OS_Linux(OS): # Library calls handler self.jitter.add_lib_handler(self.libs, methods) + # 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 miasm2.jitter.loader.elf import libimp_elf from miasm2.os_dep import linux_stdlib @@ -293,8 +332,25 @@ class OS_Linux_str(OS): # Library calls handler self.jitter.add_lib_handler(libs, methods) + # 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") @@ -409,6 +465,15 @@ class Sandbox_Win_x86_32(Sandbox, Arch_x86_32, OS_Win): 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): @@ -433,6 +498,15 @@ class Sandbox_Win_x86_64(Sandbox, Arch_x86_64, OS_Win): 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): @@ -440,10 +514,32 @@ class Sandbox_Linux_x86_32(Sandbox, Arch_x86_32, OS_Linux): Sandbox.__init__(self, *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(0x1337beef) + if self.options.mimic_env: + env_ptrs = [] + for env in self.envp: + env += "\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 += "\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(0x1337beef) + 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(0x1337beef) # Set the runtime guard self.jitter.add_breakpoint(0x1337beef, self.__class__.code_sentinelle) @@ -456,18 +552,49 @@ class Sandbox_Linux_x86_32(Sandbox, Arch_x86_32, OS_Linux): 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, *args, **kwargs): Sandbox.__init__(self, *args, **kwargs) - # reserve stack for local reg - for _ in xrange(0x4): + # Pre-stack some arguments + if self.options.mimic_env: + env_ptrs = [] + for env in self.envp: + env += "\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 += "\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(0x1337beef) self.jitter.push_uint64_t(0) - - # Pre-stack return address - self.jitter.push_uint64_t(0x1337beef) + 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(0x1337beef) # Set the runtime guard self.jitter.add_breakpoint(0x1337beef, self.__class__.code_sentinelle) @@ -480,22 +607,65 @@ class Sandbox_Linux_x86_64(Sandbox, Arch_x86_64, OS_Linux): 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, *args, **kwargs): Sandbox.__init__(self, *args, **kwargs) + # Pre-stack some arguments + if self.options.mimic_env: + env_ptrs = [] + for env in self.envp: + env += "\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 += "\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.LR = 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 not None: - addr = int(self.options.address, 16) + 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_armb_str(Sandbox, Arch_armb, OS_Linux_str): @@ -534,12 +704,46 @@ class Sandbox_Linux_aarch64l(Sandbox, Arch_aarch64l, OS_Linux): def __init__(self, *args, **kwargs): Sandbox.__init__(self, *args, **kwargs) + # Pre-stack some arguments + if self.options.mimic_env: + env_ptrs = [] + for env in self.envp: + env += "\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 += "\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 = 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 not None: - addr = int(self.options.address, 0) + 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) diff --git a/miasm2/arch/aarch64/jit.py b/miasm2/arch/aarch64/jit.py index 255bb91d..31570f52 100644 --- a/miasm2/arch/aarch64/jit.py +++ b/miasm2/arch/aarch64/jit.py @@ -37,7 +37,7 @@ class jitter_aarch64l(jitter): def func_args_stdcall(self, n_args): args = [] for i in xrange(min(n_args, self.max_reg_arg)): - args.append(self.cpu.get_gpreg()['X%d' % i]) + args.append(getattr(self.cpu, 'X%d' % i)) for i in xrange(max(0, n_args - self.max_reg_arg)): args.append(self.get_stack_arg(i)) ret_ad = self.cpu.LR @@ -56,6 +56,18 @@ class jitter_aarch64l(jitter): arg = self.get_stack_arg(index - self.max_reg_arg) return arg + def func_prepare_stdcall(self, ret_addr, *args): + for index in xrange(min(len(args), 4)): + setattr(self.cpu, 'X%d' % index, args[index]) + for index in xrange(4, len(args)): + self.vm.set_mem(self.cpu.SP + 8 * (index - 4), pck64(args[index])) + self.cpu.LR = ret_addr + + func_args_systemv = func_args_stdcall + func_ret_systemv = func_ret_stdcall + get_arg_n_systemv = get_arg_n_stdcall + func_prepare_systemv = func_prepare_stdcall + def init_run(self, *args, **kwargs): jitter.init_run(self, *args, **kwargs) self.cpu.PC = self.pc diff --git a/miasm2/arch/arm/jit.py b/miasm2/arch/arm/jit.py index 70c708e1..545d60de 100644 --- a/miasm2/arch/arm/jit.py +++ b/miasm2/arch/arm/jit.py @@ -34,11 +34,7 @@ class jitter_arml(jitter): @named_arguments def func_args_stdcall(self, n_args): - args = [] - for i in xrange(min(n_args, 4)): - args.append(self.cpu.get_gpreg()['R%d' % i]) - for i in xrange(max(0, n_args - 4)): - args.append(self.get_stack_arg(i)) + args = [self.get_arg_n_stdcall(i) for i in xrange(n_args)] ret_ad = self.cpu.LR return ret_ad, args @@ -48,13 +44,25 @@ class jitter_arml(jitter): self.cpu.R0 = ret_value return True + def func_prepare_stdcall(self, ret_addr, *args): + for index in xrange(min(len(args), 4)): + setattr(self.cpu, 'R%d' % index, args[index]) + for index in xrange(4, len(args)): + self.vm.set_mem(self.cpu.SP + 4 * (index - 4), pck32(args[index])) + self.cpu.LR = ret_addr + def get_arg_n_stdcall(self, index): if index < 4: - arg = self.cpu.get_gpreg()['R%d' % index] + arg = getattr(self.cpu, 'R%d' % index) else: arg = self.get_stack_arg(index-4) return arg + func_args_systemv = func_args_stdcall + func_ret_systemv = func_ret_stdcall + func_prepare_systemv = func_prepare_stdcall + get_arg_n_systemv = get_arg_n_stdcall + def init_run(self, *args, **kwargs): jitter.init_run(self, *args, **kwargs) self.cpu.PC = self.pc diff --git a/miasm2/arch/x86/jit.py b/miasm2/arch/x86/jit.py index cfdabf8c..ef1f162b 100644 --- a/miasm2/arch/x86/jit.py +++ b/miasm2/arch/x86/jit.py @@ -92,6 +92,10 @@ class jitter_x86_32(jitter): def get_stack_arg(self, index): return upck32(self.vm.get_mem(self.cpu.ESP + 4 * index, 4)) + def init_run(self, *args, **kwargs): + jitter.init_run(self, *args, **kwargs) + self.cpu.EIP = self.pc + # calling conventions # stdcall @@ -108,6 +112,13 @@ class jitter_x86_32(jitter): if ret_value2 is not None: self.cpu.EDX = ret_value2 + def func_prepare_stdcall(self, ret_addr, *args): + for arg in reversed(args): + self.push_uint32_t(arg) + self.push_uint32_t(ret_addr) + + get_arg_n_stdcall = get_stack_arg + # cdecl @named_arguments def func_args_cdecl(self, n_args): @@ -115,18 +126,24 @@ class jitter_x86_32(jitter): args = [self.get_stack_arg(i) for i in xrange(n_args)] return ret_ad, args - def func_ret_cdecl(self, ret_addr, ret_value): + def func_ret_cdecl(self, ret_addr, ret_value=None): self.cpu.EIP = ret_addr - self.cpu.EAX = ret_value + if ret_value is not None: + self.cpu.EAX = ret_value - def init_run(self, *args, **kwargs): - jitter.init_run(self, *args, **kwargs) - self.cpu.EIP = self.pc + get_arg_n_cdecl = get_stack_arg + + # System V + func_args_systemv = func_args_cdecl + func_ret_systemv = func_ret_cdecl + func_prepare_systemv = func_prepare_stdcall + get_arg_n_systemv = get_stack_arg class jitter_x86_64(jitter): C_Gen = x86_64_CGen + args_regs_systemv = ['RDI', 'RSI', 'RDX', 'RCX', 'R8', 'R9'] def __init__(self, *args, **kwargs): sp = asmblock.AsmSymbolPool() @@ -152,6 +169,13 @@ class jitter_x86_64(jitter): def get_stack_arg(self, index): return upck64(self.vm.get_mem(self.cpu.RSP + 8 * index, 8)) + def init_run(self, *args, **kwargs): + jitter.init_run(self, *args, **kwargs) + self.cpu.RIP = self.pc + + # calling conventions + + # stdcall @named_arguments def func_args_stdcall(self, n_args): args_regs = ['RCX', 'RDX', 'R8', 'R9'] @@ -169,23 +193,31 @@ class jitter_x86_64(jitter): self.cpu.RAX = ret_value return True + # cdecl + func_args_cdecl = func_args_stdcall + func_ret_cdecl = func_ret_stdcall + + # System V + + def get_arg_n_systemv(self, index): + args_regs = self.args_regs_systemv + if index < len(args_regs): + return getattr(self.cpu, args_regs[index]) + return self.get_stack_arg(index - len(args_regs)) + @named_arguments - def func_args_cdecl(self, n_args): - args_regs = ['RCX', 'RDX', 'R8', 'R9'] + def func_args_systemv(self, n_args): ret_ad = self.pop_uint64_t() - args = [] - for i in xrange(min(n_args, 4)): - args.append(self.cpu.get_gpreg()[args_regs[i]]) - for i in xrange(max(0, n_args - 4)): - args.append(self.get_stack_arg(i)) + args = [self.get_arg_n_systemv(index) for index in xrange(n_args)] return ret_ad, args - def func_ret_cdecl(self, ret_addr, ret_value=None): - self.pc = self.cpu.RIP = ret_addr - if ret_value is not None: - self.cpu.RAX = ret_value - return True + func_ret_systemv = func_ret_cdecl - def init_run(self, *args, **kwargs): - jitter.init_run(self, *args, **kwargs) - self.cpu.RIP = self.pc + def func_prepare_systemv(self, ret_addr, *args): + args_regs = self.args_regs_systemv + self.push_uint64_t(ret_addr) + for i in xrange(min(len(args), len(args_regs))): + setattr(self.cpu, args_regs[i], args[i]) + remaining_args = args[len(args_regs):] + for arg in reversed(remaining_args): + self.push_uint64_t(arg) diff --git a/miasm2/os_dep/linux_stdlib.py b/miasm2/os_dep/linux_stdlib.py index b05b2cd9..9e68454c 100644 --- a/miasm2/os_dep/linux_stdlib.py +++ b/miasm2/os_dep/linux_stdlib.py @@ -17,6 +17,36 @@ class c_linobjs(object): linobjs = c_linobjs() +ABORT_ADDR = 0x1337beef + +def xxx___libc_start_main(jitter): + """Basic implementation of __libc_start_main + + int __libc_start_main(int *(main) (int, char * *, char * *), int argc, + char * * ubp_av, void (*init) (void), + void (*fini) (void), void (*rtld_fini) (void), + void (* stack_end)); + + Note: + - init, fini, rtld_fini are ignored + - return address is forced to ABORT_ADDR, to avoid calling abort/hlt/... + + """ + global ABORT_ADDR + ret_ad, args = jitter.func_args_systemv(["main", "argc", "ubp_av", "init", + "fini", "rtld_fini", "stack_end"]) + + # done by __libc_init_first + size = jitter.ir_arch.pc.size / 8 + argv = args.ubp_av + envp = argv + (args.argc + 1) * size + + # Call int main(int argc, char** argv, char** envp) + jitter.func_ret_systemv(args.main) + ret_ad = ABORT_ADDR + jitter.func_prepare_systemv(ret_ad, args.argc, argv, envp) + return True + def xxx_isprint(jitter): ''' @@ -25,9 +55,9 @@ def xxx_isprint(jitter): checks for any printable character including space. ''' - ret_addr, args = jitter.func_args_stdcall(['c']) + ret_addr, args = jitter.func_args_systemv(['c']) ret = 1 if chr(args.c & 0xFF) in printable else 0 - return jitter.func_ret_stdcall(ret_addr, ret) + return jitter.func_ret_systemv(ret_addr, ret) def xxx_memcpy(jitter): @@ -37,9 +67,9 @@ def xxx_memcpy(jitter): copies n bytes from memory area src to memory area dest. ''' - ret_addr, args = jitter.func_args_stdcall(['dest', 'src', 'n']) + ret_addr, args = jitter.func_args_systemv(['dest', 'src', 'n']) jitter.vm.set_mem(args.dest, jitter.vm.get_mem(args.src, args.n)) - return jitter.func_ret_stdcall(ret_addr, args.dest) + return jitter.func_ret_systemv(ret_addr, args.dest) def xxx_memset(jitter): @@ -50,9 +80,9 @@ def xxx_memset(jitter): fills the first n bytes of the memory area pointed to by s with the constant byte c.''' - ret_addr, args = jitter.func_args_stdcall(['dest', 'c', 'n']) + ret_addr, args = jitter.func_args_systemv(['dest', 'c', 'n']) jitter.vm.set_mem(args.dest, chr(args.c & 0xFF) * args.n) - return jitter.func_ret_stdcall(ret_addr, args.dest) + return jitter.func_ret_systemv(ret_addr, args.dest) def xxx_puts(jitter): @@ -62,7 +92,7 @@ def xxx_puts(jitter): writes the string s and a trailing newline to stdout. ''' - ret_addr, args = jitter.func_args_stdcall(['s']) + ret_addr, args = jitter.func_args_systemv(['s']) index = args.s char = jitter.vm.get_mem(index, 1) while char != '\x00': @@ -70,7 +100,7 @@ def xxx_puts(jitter): index += 1 char = jitter.vm.get_mem(index, 1) stdout.write('\n') - return jitter.func_ret_stdcall(ret_addr, 1) + return jitter.func_ret_systemv(ret_addr, 1) def get_fmt_args(jitter, fmt, cur_arg): @@ -89,9 +119,9 @@ def get_fmt_args(jitter, fmt, cur_arg): if char.lower() in '%cdfsux': break if token.endswith('s'): - arg = jitter.get_str_ansi(jitter.get_arg_n_stdcall(cur_arg)) + arg = jitter.get_str_ansi(jitter.get_arg_n_systemv(cur_arg)) else: - arg = jitter.get_arg_n_stdcall(cur_arg) + arg = jitter.get_arg_n_systemv(cur_arg) char = token % arg cur_arg += 1 output += char @@ -99,67 +129,67 @@ def get_fmt_args(jitter, fmt, cur_arg): def xxx_snprintf(jitter): - ret_addr, args = jitter.func_args_stdcall(['string', 'size', 'fmt']) + ret_addr, args = jitter.func_args_systemv(['string', 'size', 'fmt']) cur_arg, fmt = 3, args.fmt size = args.size if args.size else 1 output = get_fmt_args(jitter, fmt, cur_arg) output = output[:size - 1] ret = len(output) jitter.vm.set_mem(args.string, output + '\x00') - return jitter.func_ret_stdcall(ret_addr, ret) + return jitter.func_ret_systemv(ret_addr, ret) def xxx_sprintf(jitter): - ret_addr, args = jitter.func_args_stdcall(['string', 'fmt']) + ret_addr, args = jitter.func_args_systemv(['string', 'fmt']) cur_arg, fmt = 2, args.fmt output = get_fmt_args(jitter, fmt, cur_arg) ret = len(output) jitter.vm.set_mem(args.string, output + '\x00') - return jitter.func_ret_stdcall(ret_addr, ret) + return jitter.func_ret_systemv(ret_addr, ret) def xxx_printf(jitter): - ret_addr, args = jitter.func_args_stdcall(['fmt']) + ret_addr, args = jitter.func_args_systemv(['fmt']) cur_arg, fmt = 1, args.fmt output = get_fmt_args(jitter, fmt, cur_arg) ret = len(output) print output, - return jitter.func_ret_stdcall(ret_addr, ret) + return jitter.func_ret_systemv(ret_addr, ret) def xxx_strcpy(jitter): - ret_ad, args = jitter.func_args_stdcall(["dst", "src"]) + ret_ad, args = jitter.func_args_systemv(["dst", "src"]) str_src = jitter.get_str_ansi(args.src) + '\x00' jitter.vm.set_mem(args.dst, str_src) - jitter.func_ret_stdcall(ret_ad, args.dst) + jitter.func_ret_systemv(ret_ad, args.dst) def xxx_strlen(jitter): - ret_ad, args = jitter.func_args_stdcall(["src"]) + ret_ad, args = jitter.func_args_systemv(["src"]) str_src = jitter.get_str_ansi(args.src) - jitter.func_ret_stdcall(ret_ad, len(str_src)) + jitter.func_ret_systemv(ret_ad, len(str_src)) def xxx_malloc(jitter): - ret_ad, args = jitter.func_args_stdcall(["msize"]) + ret_ad, args = jitter.func_args_systemv(["msize"]) addr = linobjs.heap.alloc(jitter, args.msize) - jitter.func_ret_stdcall(ret_ad, addr) + jitter.func_ret_systemv(ret_ad, addr) def xxx_free(jitter): - ret_ad, args = jitter.func_args_stdcall(["ptr"]) - jitter.func_ret_stdcall(ret_ad, 0) + ret_ad, args = jitter.func_args_systemv(["ptr"]) + jitter.func_ret_systemv(ret_ad, 0) def xxx_strcmp(jitter): - ret_ad, args = jitter.func_args_stdcall(["ptr_str1", "ptr_str2"]) + ret_ad, args = jitter.func_args_systemv(["ptr_str1", "ptr_str2"]) s1 = jitter.get_str_ansi(args.ptr_str1) s2 = jitter.get_str_ansi(args.ptr_str2) - jitter.func_ret_stdcall(ret_ad, cmp(s1, s2)) + jitter.func_ret_systemv(ret_ad, cmp(s1, s2)) def xxx_strncmp(jitter): - ret_ad, args = jitter.func_args_stdcall(["ptr_str1", "ptr_str2", "size"]) + ret_ad, args = jitter.func_args_systemv(["ptr_str1", "ptr_str2", "size"]) s1 = jitter.get_str_ansi(args.ptr_str1, args.size) s2 = jitter.get_str_ansi(args.ptr_str2, args.size) - jitter.func_ret_stdcall(ret_ad, cmp(s1, s2)) + jitter.func_ret_systemv(ret_ad, cmp(s1, s2)) diff --git a/test/arch/x86/qemu/testqemu.py b/test/arch/x86/qemu/testqemu.py index 5f26d6f3..e6c487f2 100644 --- a/test/arch/x86/qemu/testqemu.py +++ b/test/arch/x86/qemu/testqemu.py @@ -40,7 +40,7 @@ nb_tests = 1 def xxx___printf_chk(jitter): """Tiny implementation of printf_chk""" global nb_tests - ret_ad, args = jitter.func_args_cdecl(["out", "format"]) + ret_ad, args = jitter.func_args_systemv(["out", "format"]) if args.out != 1: raise RuntimeError("Not implemented") fmt = jitter.get_str_ansi(args.format) @@ -89,7 +89,7 @@ def xxx___printf_chk(jitter): sys.stdout.write("[%d] %s" % (nb_tests, output)) nb_tests += 1 - jitter.func_ret_cdecl(ret_ad, 0) + jitter.func_ret_systemv(ret_ad, 0) def xxx_puts(jitter): ''' @@ -98,7 +98,7 @@ def xxx_puts(jitter): writes the string s and a trailing newline to stdout. ''' - ret_addr, args = jitter.func_args_cdecl(['target']) + ret_addr, args = jitter.func_args_systemv(['target']) output = jitter.get_str_ansi(args.target) # Check with expected result line = expected.next() @@ -106,7 +106,7 @@ def xxx_puts(jitter): print "Expected:", line print "Obtained:", output raise RuntimeError("Bad semantic") - return jitter.func_ret_cdecl(ret_addr, 1) + return jitter.func_ret_systemv(ret_addr, 1) # Parse arguments parser = Sandbox_Linux_x86_32.parser(description="ELF sandboxer") diff --git a/test/os_dep/linux/test_env.aarch64l b/test/os_dep/linux/test_env.aarch64l new file mode 100755 index 00000000..19e97780 --- /dev/null +++ b/test/os_dep/linux/test_env.aarch64l Binary files differdiff --git a/test/os_dep/linux/test_env.arml b/test/os_dep/linux/test_env.arml new file mode 100755 index 00000000..c24d061e --- /dev/null +++ b/test/os_dep/linux/test_env.arml Binary files differdiff --git a/test/os_dep/linux/test_env.c b/test/os_dep/linux/test_env.c new file mode 100644 index 00000000..7b265561 --- /dev/null +++ b/test/os_dep/linux/test_env.c @@ -0,0 +1,10 @@ +#include<stdlib.h> +#include<stdio.h> + +int main(int argc, char** argv, char** envp) +{ + printf("argc %d\n", argc); + printf("argv[0] %s\n", argv[0]); + printf("argv[1] %s\n", argv[1]); + printf("envp[0] %s\n", envp[0]); +} diff --git a/test/os_dep/linux/test_env.py b/test/os_dep/linux/test_env.py new file mode 100644 index 00000000..a44d62c4 --- /dev/null +++ b/test/os_dep/linux/test_env.py @@ -0,0 +1,36 @@ +import os +import sys +from pdb import pm +from miasm2.analysis.binary import Container +from miasm2.analysis.sandbox import Sandbox_Linux_x86_32, Sandbox_Linux_x86_64,\ + Sandbox_Linux_arml, Sandbox_Linux_aarch64l + +if len(sys.argv) < 2: + print "Usage: %s <arch> ..." % sys.argv[0] + exit(0) + +arch = sys.argv[1] + +if arch == "x86_32": + sandbox = Sandbox_Linux_x86_32 +elif arch == "x86_64": + sandbox = Sandbox_Linux_x86_64 +elif arch == "arml": + sandbox = Sandbox_Linux_arml +elif arch == "aarch64l": + sandbox = Sandbox_Linux_aarch64l +else: + raise ValueError("Unsuported arch: %s" % arch) + +# Parse arguments +parser = sandbox.parser(description="ELF sandboxer") +parser.add_argument("filename", help="ELF Filename") +options = parser.parse_args(sys.argv[2:]) + +# Create sandbox +sb = sandbox(options.filename, options, globals()) + +# Run +sb.run() + +assert(sb.jitter.run is False) diff --git a/test/os_dep/linux/test_env.x86_32 b/test/os_dep/linux/test_env.x86_32 new file mode 100755 index 00000000..9f0f96bc --- /dev/null +++ b/test/os_dep/linux/test_env.x86_32 Binary files differdiff --git a/test/os_dep/linux/test_env.x86_64 b/test/os_dep/linux/test_env.x86_64 new file mode 100755 index 00000000..f9d78a1d --- /dev/null +++ b/test/os_dep/linux/test_env.x86_64 Binary files differdiff --git a/test/test_all.py b/test/test_all.py index 0a29d4d3..f76019c4 100755 --- a/test/test_all.py +++ b/test/test_all.py @@ -257,6 +257,12 @@ for script in ["win_api_x86_32.py", ]: testset += RegressionTest([script], base_dir="os_dep", tags=[TAGS['tcc']]) +for arch in ["x86_32", "x86_64", "arml", "aarch64l"]: + testset += RegressionTest(["test_env.py", arch, "test_env.%s" % arch, "-c", + "arg1", "-c", "arg2", "--environment-vars", + "TEST=TOTO", "--mimic-env"], + base_dir="os_dep/linux", tags=[TAGS['tcc']]) + ## Analysis testset += RegressionTest(["depgraph.py"], base_dir="analysis", products=[fname for fnames in ( @@ -608,7 +614,7 @@ for jitter in ExampleJitter.jitter_engines: tags=tags.get(jitter, [])) for script, dep in [(["x86_32.py", Example.get_sample("x86_32_sc.bin")], []), - (["arm.py", Example.get_sample("md5_arm"), "-a", "A684"], + (["arm.py", Example.get_sample("md5_arm"), "--mimic-env"], []), (["sandbox_elf_aarch64l.py", Example.get_sample("md5_aarch64l"), "-a", "0x400A00"], []), @@ -620,6 +626,7 @@ for script, dep in [(["x86_32.py", Example.get_sample("x86_32_sc.bin")], []), "b", "-a", "0"], [test_armb]), (["arm_sc.py", "0", Example.get_sample("demo_arm_l.bin"), "l", "-a", "0"], [test_arml]), + (["sandbox_call.py", Example.get_sample("md5_arm")], []), ] + [(["sandbox_pe_x86_32.py", Example.get_sample("x86_32_" + name + ".bin")], [test_box[name]]) |