about summary refs log tree commit diff stats
path: root/miasm2
diff options
context:
space:
mode:
Diffstat (limited to 'miasm2')
-rw-r--r--miasm2/analysis/sandbox.py22
-rw-r--r--miasm2/arch/arm/jit.py27
-rw-r--r--miasm2/arch/x86/arch.py6
-rw-r--r--miasm2/arch/x86/jit.py58
-rw-r--r--miasm2/arch/x86/sem.py27
-rw-r--r--miasm2/expression/expression_helper.py30
-rw-r--r--miasm2/jitter/jitload.py39
-rw-r--r--miasm2/jitter/loader/pe.py9
-rw-r--r--miasm2/os_dep/win_api_x86_32.py2
9 files changed, 101 insertions, 119 deletions
diff --git a/miasm2/analysis/sandbox.py b/miasm2/analysis/sandbox.py
index ca6dcfe6..22bd2094 100644
--- a/miasm2/analysis/sandbox.py
+++ b/miasm2/analysis/sandbox.py
@@ -160,8 +160,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()
@@ -187,7 +190,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:
@@ -217,8 +220,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()
@@ -230,12 +236,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()
@@ -246,7 +256,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/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)