diff options
Diffstat (limited to 'miasm2')
| -rw-r--r-- | miasm2/analysis/sandbox.py | 22 | ||||
| -rw-r--r-- | miasm2/arch/arm/jit.py | 27 | ||||
| -rw-r--r-- | miasm2/arch/x86/arch.py | 6 | ||||
| -rw-r--r-- | miasm2/arch/x86/jit.py | 58 | ||||
| -rw-r--r-- | miasm2/arch/x86/sem.py | 27 | ||||
| -rw-r--r-- | miasm2/expression/expression_helper.py | 30 | ||||
| -rw-r--r-- | miasm2/ir/symbexec.py | 2 | ||||
| -rw-r--r-- | miasm2/jitter/jitload.py | 39 | ||||
| -rw-r--r-- | miasm2/jitter/loader/pe.py | 9 | ||||
| -rw-r--r-- | miasm2/os_dep/win_api_x86_32.py | 2 |
10 files changed, 102 insertions, 120 deletions
diff --git a/miasm2/analysis/sandbox.py b/miasm2/analysis/sandbox.py index 938772fc..c5873a85 100644 --- a/miasm2/analysis/sandbox.py +++ b/miasm2/analysis/sandbox.py @@ -158,8 +158,11 @@ class OS_Win(OS): def __init__(self, custom_methods, *args, **kwargs): from miasm2.jitter.loader.pe import vm_load_pe, vm_load_pe_libs, preload_pe, libimp_pe + from miasm2.os_dep import win_api_x86_32 + methods = win_api_x86_32.__dict__ + methods.update(custom_methods) - super(OS_Win, self).__init__(custom_methods, *args, **kwargs) + super(OS_Win, self).__init__(methods, *args, **kwargs) # Import manager libs = libimp_pe() @@ -185,7 +188,7 @@ class OS_Win(OS): preload_pe(self.jitter.vm, self.pe, libs) # Library calls handler - self.jitter.add_lib_handler(libs, custom_methods) + self.jitter.add_lib_handler(libs, methods) # Manage SEH if self.options.use_seh: @@ -215,8 +218,11 @@ class OS_Linux(OS): 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 + methods = linux_stdlib.__dict__ + methods.update(custom_methods) - super(OS_Linux, self).__init__(custom_methods, *args, **kwargs) + super(OS_Linux, self).__init__(methods, *args, **kwargs) # Import manager self.libs = libimp_elf() @@ -228,12 +234,16 @@ class OS_Linux(OS): self.entry_point = self.elf.Ehdr.entry # Library calls handler - self.jitter.add_lib_handler(self.libs, custom_methods) + self.jitter.add_lib_handler(self.libs, methods) class OS_Linux_str(OS): def __init__(self, custom_methods, *args, **kwargs): from miasm2.jitter.loader.elf import libimp_elf - super(OS_Linux_str, self).__init__(custom_methods, *args, **kwargs) + from miasm2.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() @@ -244,7 +254,7 @@ class OS_Linux_str(OS): self.jitter.vm.add_memory_page(self.options.load_base_addr, PAGE_READ | PAGE_WRITE, data) # Library calls handler - self.jitter.add_lib_handler(libs, custom_methods) + self.jitter.add_lib_handler(libs, methods) @classmethod def update_parser(cls, parser): diff --git a/miasm2/arch/arm/jit.py b/miasm2/arch/arm/jit.py index d089bafb..8803725e 100644 --- a/miasm2/arch/arm/jit.py +++ b/miasm2/arch/arm/jit.py @@ -58,33 +58,6 @@ class jitter_arml(jitter): arg = self.get_stack_arg(n-4) return arg - def add_lib_handler(self, libs, user_globals=None): - """Add a function to handle libs call with breakpoints - @libs: libimp instance - @user_globals: dictionnary for defined user function - """ - if user_globals is None: - user_globals = {} - - from miasm2.os_dep import linux_stdlib - - def handle_lib(jitter): - fname = libs.fad2cname[jitter.pc] - if fname in user_globals: - f = user_globals[fname] - elif fname in linux_stdlib.__dict__: - f = linux_stdlib.__dict__[fname] - else: - log.debug('%s' % repr(fname)) - raise ValueError('unknown api', hex(jitter.pop_uint32_t()), repr(fname)) - f(jitter) - jitter.pc = getattr(jitter.cpu, jitter.ir_arch.pc.name) - return True - - for f_addr in libs.fad2cname: - self.add_breakpoint(f_addr, handle_lib) - - def init_run(self, *args, **kwargs): jitter.init_run(self, *args, **kwargs) self.cpu.PC = self.pc diff --git a/miasm2/arch/x86/arch.py b/miasm2/arch/x86/arch.py index 85356468..e75c22a9 100644 --- a/miasm2/arch/x86/arch.py +++ b/miasm2/arch/x86/arch.py @@ -20,8 +20,10 @@ conditional_branch = ["JO", "JNO", "JB", "JAE", "JZ", "JNZ", "JBE", "JA", "JS", "JNS", "JPE", "JNP", #"L", "NL", "NG", "G"] - "JL", "JGE", "JLE", "JG"] -unconditional_branch = ['JMP'] + "JL", "JGE", "JLE", "JG", + "JCXZ", "JECXZ", "JRCXZ"] + +unconditional_branch = ['JMP', 'JMPF'] f_isad = "AD" f_s08 = "S08" diff --git a/miasm2/arch/x86/jit.py b/miasm2/arch/x86/jit.py index 36afcce5..08bac4db 100644 --- a/miasm2/arch/x86/jit.py +++ b/miasm2/arch/x86/jit.py @@ -106,32 +106,6 @@ class jitter_x86_32(jitter): self.cpu.EIP = ret_addr self.cpu.EAX = ret_value - def add_lib_handler(self, libs, user_globals=None): - """Add a function to handle libs call with breakpoints - @libs: libimp instance - @user_globals: dictionnary for defined user function - """ - if user_globals is None: - user_globals = {} - - from miasm2.os_dep import win_api_x86_32 - - def handle_lib(jitter): - fname = libs.fad2cname[jitter.pc] - if fname in user_globals: - f = user_globals[fname] - elif fname in win_api_x86_32.__dict__: - f = win_api_x86_32.__dict__[fname] - else: - log.debug('%s' % repr(fname)) - raise ValueError('unknown api', hex(jitter.pop_uint32_t()), repr(fname)) - f(jitter) - jitter.pc = getattr(jitter.cpu, jitter.ir_arch.pc.name) - return True - - for f_addr in libs.fad2cname: - self.add_breakpoint(f_addr, handle_lib) - def init_run(self, *args, **kwargs): jitter.init_run(self, *args, **kwargs) self.cpu.EIP = self.pc @@ -165,10 +139,6 @@ class jitter_x86_64(jitter): x = upck64(self.vm.get_mem(self.cpu.RSP + 8 * n, 8)) return x - def init_run(self, *args, **kwargs): - jitter.init_run(self, *args, **kwargs) - self.cpu.RIP = self.pc - def func_args_stdcall(self, n_args): args_regs = ['RCX', 'RDX', 'R8', 'R9'] ret_ad = self.pop_uint64_t() @@ -207,28 +177,6 @@ class jitter_x86_64(jitter): self.cpu.RAX = ret_value return True - def add_lib_handler(self, libs, user_globals=None): - """Add a function to handle libs call with breakpoints - @libs: libimp instance - @user_globals: dictionnary for defined user function - """ - if user_globals is None: - user_globals = {} - - from miasm2.os_dep import win_api_x86_32 - - def handle_lib(jitter): - fname = libs.fad2cname[jitter.pc] - if fname in user_globals: - f = user_globals[fname] - elif fname in win_api_x86_32.__dict__: - f = win_api_x86_32.__dict__[fname] - else: - log.debug('%s' % repr(fname)) - raise ValueError('unknown api', hex(jitter.pop_uint64_t()), repr(fname)) - f(jitter) - jitter.pc = getattr(jitter.cpu, jitter.ir_arch.pc.name) - return True - - for f_addr in libs.fad2cname: - self.add_breakpoint(f_addr, handle_lib) + def init_run(self, *args, **kwargs): + jitter.init_run(self, *args, **kwargs) + self.cpu.RIP = self.pc diff --git a/miasm2/arch/x86/sem.py b/miasm2/arch/x86/sem.py index 22e8c276..36d8e618 100644 --- a/miasm2/arch/x86/sem.py +++ b/miasm2/arch/x86/sem.py @@ -635,7 +635,9 @@ def pop(ir, instr, a): if not s in [16, 32, 64]: raise ValueError('bad size stacker!') new_esp = mRSP[instr.mode][:s] + ExprInt_fromsize(s, off / 8) - e.append(ExprAff(mRSP[instr.mode][:s], new_esp)) + # don't generate ESP incrementation on POP ESP + if a != ir.sp: + e.append(ExprAff(mRSP[instr.mode][:s], new_esp)) # XXX FIX XXX for pop [esp] if isinstance(a, ExprMem): a = a.replace_expr({mRSP[instr.mode]: new_esp}) @@ -1821,16 +1823,16 @@ def fucomip(ir, instr, a, b): def fcomp(ir, instr, a, b = None): - dst, e, extra = fcom(ir, instr, a, b) + e, extra = fcom(ir, instr, a, b) e += float_pop() e += set_float_cs_eip(instr) - return dst, e, extra + return e, extra def ficomp(ir, instr, a, b = None): - dst, e, extra = ficom(ir, instr, a, b) + e, extra = ficom(ir, instr, a, b) e += float_pop() e += set_float_cs_eip(instr) - return dst, e, extra + return e, extra def fld(ir, instr, a): @@ -1872,9 +1874,9 @@ def fst(ir, instr, a): def fstp(ir, instr, a): - dst, e, extra = fst(ir, instr, a) + e, extra = fst(ir, instr, a) e += float_pop(a) - return dst, e, extra + return e, extra def fist(ir, instr, a): @@ -1885,9 +1887,9 @@ def fist(ir, instr, a): return e, [] def fistp(ir, instr, a): - dst, e, extra = fist(ir, instr, a) + e, extra = fist(ir, instr, a) e += float_pop(a) - return dst, e, extra + return e, extra def fist(ir, instr, a): e = [] @@ -1910,9 +1912,9 @@ def fild(ir, instr, a): src = ExprOp('int_%.2d_to_double' % a.size, a) e = [] e += set_float_cs_eip(instr) - dst, e_fld, extra = fld(ir, instr, src) + e_fld, extra = fld(ir, instr, src) e += e_fld - return dst, e, extra + return e, extra def fldz(ir, instr): @@ -2003,6 +2005,9 @@ def fnstenv(ir, instr, a): ]) s = instr.mode + # The behaviour in 64bit is identical to 64 bit + # This will truncate addresses + s = min(32, s) ad = ExprMem(a.arg, size=16) e.append(ExprAff(ad, float_control)) ad = ExprMem(a.arg + ExprInt_from(a.arg, s / 8 * 1), size=16) diff --git a/miasm2/expression/expression_helper.py b/miasm2/expression/expression_helper.py index 2f0bd4e7..825cad60 100644 --- a/miasm2/expression/expression_helper.py +++ b/miasm2/expression/expression_helper.py @@ -17,7 +17,6 @@ # # Expressions manipulation functions -import re import itertools import collections import random @@ -210,16 +209,20 @@ class Variables_Identifier(object): - original expression with variables translated """ - var_identifier = re.compile("v\d+") + # Attribute used to distinguish created variables from original ones + is_var_ident = "is_var_ident" - def __init__(self, expr): + def __init__(self, expr, var_prefix="v"): """Set the expression @expr to handle and launch variable identification - process""" + process + @expr: Expr instance + @var_prefix: (optional) prefix of the variable name, default is 'v'""" # Init self.var_indice = itertools.count() self.var_asked = set() self._vars = {} # VarID -> Expr + self.var_prefix = var_prefix # Launch recurrence self.find_variables_rec(expr) @@ -254,9 +257,13 @@ class Variables_Identifier(object): ## Build initial needs for var_id, var_expr in self._vars.iteritems(): + ### Handle corner cases while using Variable Identifier on an + ### already computed equation needs[var_id] = [var_name for var_name in var_expr.get_r(mem_read=True) - if self.is_var_identifier(var_name)] + if self.is_var_identifier(var_name) and \ + var_name in todo and \ + var_name != var_id] ## Build order list while todo: @@ -268,7 +275,6 @@ class Variables_Identifier(object): # A dependency is not met all_met = False break - if not all_met: continue @@ -282,12 +288,12 @@ class Variables_Identifier(object): @classmethod def is_var_identifier(cls, expr): - "Return True iff expr seems to be a variable identifier" + "Return True iff @expr is a variable identifier" if not isinstance(expr, m2_expr.ExprId): return False - match = cls.var_identifier.match(expr.name) - return match is not None and match.group(0) == expr.name + return hasattr(expr, cls.is_var_ident) and \ + getattr(expr, cls.is_var_ident) == True def find_variables_rec(self, expr): """Recursive method called by find_variable to expand @expr. @@ -301,8 +307,10 @@ class Variables_Identifier(object): if (expr not in self._vars.values()): # Create var - identifier = m2_expr.ExprId("v%s" % self.var_indice.next(), - size = expr.size) + identifier = m2_expr.ExprId("%s%s" % (self.var_prefix, + self.var_indice.next()), + size = expr.size) + setattr(identifier, self.__class__.is_var_ident, True) self._vars[identifier] = expr # Recursion stop case diff --git a/miasm2/ir/symbexec.py b/miasm2/ir/symbexec.py index 5bdcac2f..26eff2f6 100644 --- a/miasm2/ir/symbexec.py +++ b/miasm2/ir/symbexec.py @@ -153,7 +153,7 @@ class symbexec(object): if out: missing_slice = self.rest_slice(out, 0, a.size) for sa, sb in missing_slice: - ptr = self.expr_simp(a_val + ExprInt32(sa / 8)) + ptr = self.expr_simp(a_val + ExprInt_from(a_val, sa / 8)) mm = ExprMem(ptr, size=sb - sa) mm.is_term = True mm.is_simp = True diff --git a/miasm2/jitter/jitload.py b/miasm2/jitter/jitload.py index c297ba50..0405b46d 100644 --- a/miasm2/jitter/jitload.py +++ b/miasm2/jitter/jitload.py @@ -40,8 +40,10 @@ class CallbackHandler(object): self.callbacks = {} # Key -> [callback list] def add_callback(self, name, callback): - "Add a callback to the key 'name'" - self.callbacks[name] = self.callbacks.get(name, []) + [callback] + """Add a callback to the key @name, iff the @callback isn't already + assigned to it""" + if callback not in self.callbacks.get(name, []): + self.callbacks[name] = self.callbacks.get(name, []) + [callback] def set_callback(self, name, *args): "Set the list of callback for key 'name'" @@ -351,3 +353,36 @@ class jitter: """Set an unicode string in memory""" s = "\x00".join(list(s)) + '\x00' * 3 self.vm.set_mem(addr, s) + + @staticmethod + 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] + if fname in jitter.user_globals: + func = jitter.user_globals[fname] + else: + log.debug('%s' % repr(fname)) + raise ValueError('unknown api', hex(jitter.pc), repr(fname)) + func(jitter) + jitter.pc = getattr(jitter.cpu, jitter.ir_arch.pc.name) + return True + + def handle_function(self, f_addr): + """Add a brakpoint 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 + @user_globals: dictionnary for defined user function + """ + if user_globals is None: + user_globals = {} + + self.libs = libs + self.user_globals = user_globals + + for f_addr in libs.fad2cname: + self.handle_function(f_addr) diff --git a/miasm2/jitter/loader/pe.py b/miasm2/jitter/loader/pe.py index 6b19fc16..0b63583d 100644 --- a/miasm2/jitter/loader/pe.py +++ b/miasm2/jitter/loader/pe.py @@ -164,8 +164,9 @@ def vm_load_pe(vm, fdata, align_s=True, load_hdr=True, **kargs): # Update min and max addresses if min_addr is None or section.addr < min_addr: min_addr = section.addr - if max_addr is None or section.addr + section.size > max_addr: - max_addr = section.addr + max(section.size, len(section.data)) + max_section_len = max(section.size, len(section.data)) + if max_addr is None or section.addr + max_section_len > max_addr: + max_addr = section.addr + max_section_len min_addr = pe.rva2virt(min_addr) max_addr = pe.rva2virt(max_addr) @@ -179,8 +180,8 @@ def vm_load_pe(vm, fdata, align_s=True, load_hdr=True, **kargs): # Copy each sections content in memory for section in pe.SHList: - log.debug('Map 0x%x bytes to 0x%x' % (len(s.data), pe.rva2virt(s.addr))) - vm.set_mem(pe.rva2virt(s.addr), str(s.data)) + log.debug('Map 0x%x bytes to 0x%x' % (len(section.data), pe.rva2virt(section.addr))) + vm.set_mem(pe.rva2virt(section.addr), str(section.data)) return pe diff --git a/miasm2/os_dep/win_api_x86_32.py b/miasm2/os_dep/win_api_x86_32.py index a4c07e59..0996d616 100644 --- a/miasm2/os_dep/win_api_x86_32.py +++ b/miasm2/os_dep/win_api_x86_32.py @@ -954,7 +954,7 @@ def kernel32_GetProcAddress(jitter): else: ad = 0 ad = winobjs.runtime_dll.lib_get_add_func(libbase, fname) - + jitter.add_breakpoint(ad, jitter.handle_lib) jitter.func_ret_stdcall(ret_ad, ad) |