Top

miasm2.jitter.jitload module

mport logging
mport warnings
rom functools import wraps
rom collections import Sequence, namedtuple, Iterator
rom miasm2.jitter.csts import *
rom miasm2.core.utils import *
rom miasm2.core.bin_stream import bin_stream_vm
rom miasm2.core.interval import interval
rom miasm2.jitter.emulatedsymbexec import EmulatedSymbExec
rom miasm2.jitter.codegen import CGen
rom miasm2.jitter.jitcore_cc_base import JitCore_Cc_Base
nd = logging.StreamHandler()
nd.setFormatter(logging.Formatter("[%(levelname)s]: %(message)s"))
og = logging.getLogger('jitload.py')
og.addHandler(hnd)
og.setLevel(logging.CRITICAL)
og_func = logging.getLogger('jit function call')
og_func.addHandler(hnd)
og_func.setLevel(logging.CRITICAL)
ry:
   from miasm2.jitter import VmMngr
xcept ImportError:
   log.error('cannot import VmMngr')
ef named_arguments(func):
   """Function decorator to allow the use of .func_args_*() methods
   with either the number of arguments or the list of the argument
   names.
   The wrapper is also used to log the argument values.
   @func: function
   """
   @wraps(func)
   def newfunc(self, args):
       if isinstance(args, Sequence):
           ret_ad, arg_vals = func(self, len(args))
           arg_vals = namedtuple("args", args)(*arg_vals)
           # func_name(arguments) return address
           log_func.info('%s(%s) ret addr: %s',
                         get_caller_name(1),
                         ', '.join("%s=0x%x" % (field, value)
                                   for field, value in arg_vals._asdict(
                                   ).iteritems()),
                        hex(ret_ad))
           return ret_ad, namedtuple("args", args)(*arg_vals)
       else:
           ret_ad, arg_vals = func(self, args)
           # func_name(arguments) return address
           log_func.info('%s(%s) ret addr: %s',
               get_caller_name(1),
               ', '.join(hex(arg) for arg in arg_vals),
               hex(ret_ad))
           return ret_ad, arg_vals
   return newfunc
lass CallbackHandler(object):
   "Handle a list of callback"
   def __init__(self):
       self.callbacks = {}  # Key -> [callback list]
   def add_callback(self, 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'"
       self.callbacks[name] = list(args)
   def get_callbacks(self, name):
       "Return the list of callbacks associated to key 'name'"
       return self.callbacks.get(name, [])
   def remove_callback(self, callback):
       """Remove the callback from the list.
       Return the list of empty keys (removed)"""
       to_check = set()
       for key, cb_list in self.callbacks.items():
           try:
               cb_list.remove(callback)
               to_check.add(key)
           except ValueError:
               pass
       empty_keys = []
       for key in to_check:
           if len(self.callbacks[key]) == 0:
               empty_keys.append(key)
               del(self.callbacks[key])
       return empty_keys
   def has_callbacks(self, name):
       return name in self.callbacks
   def call_callbacks(self, name, *args):
       """Call callbacks associated to key 'name' with arguments args. While
       callbacks return True, continue with next callback.
       Iterator on other results."""
       res = True
       for c in self.get_callbacks(name):
           res = c(*args)
           if res is not True:
               yield res
   def __call__(self, name, *args):
       "Wrapper for call_callbacks"
       return self.call_callbacks(name, *args)
lass CallbackHandlerBitflag(CallbackHandler):
   "Handle a list of callback with conditions on bitflag"
   def call_callbacks(self, bitflag, *args):
       """Call each callbacks associated with bit set in bitflag. While
       callbacks return True, continue with next callback.
       Iterator on other results"""
       res = True
       for bitflag_expected in self.callbacks:
           if bitflag_expected & bitflag == bitflag_expected:
               # If the flag matched
               for res in super(CallbackHandlerBitflag,
                                self).call_callbacks(bitflag_expected, *args):
                   if res is not True:
                       yield res
lass ExceptionHandle():
   "Return type for exception handler"
   def __init__(self, except_flag):
       self.except_flag = except_flag
   @classmethod
   def memoryBreakpoint(cls):
       return cls(EXCEPT_BREAKPOINT_MEMORY)
   def __eq__(self, to_cmp):
       if not isinstance(to_cmp, ExceptionHandle):
           return False
       return (self.except_flag == to_cmp.except_flag)
   def __ne__(self, to_cmp):
       return not self.__eq__(to_cmp)
lass Jitter(object):
   "Main class for JIT handling"
   C_Gen = CGen
   def __init__(self, ir_arch, jit_type="gcc"):
       """Init an instance of jitter.
       @ir_arch: ir instance for this architecture
       @jit_type: JiT backend to use. Available options are:
           - "gcc"
           - "llvm"
           - "python"
       """
       self.arch = ir_arch.arch
       self.attrib = ir_arch.attrib
       arch_name = ir_arch.arch.name  # (ir_arch.arch.name, ir_arch.attrib)
       try:
           if arch_name == "x86":
               from miasm2.jitter.arch import JitCore_x86 as jcore
           elif arch_name == "arm":
               from miasm2.jitter.arch import JitCore_arm as jcore
           elif arch_name == "armt":
               from miasm2.jitter.arch import JitCore_arm as jcore
               ir_arch.arch.name = 'arm'
           elif arch_name == "aarch64":
               from miasm2.jitter.arch import JitCore_aarch64 as jcore
           elif arch_name == "msp430":
               from miasm2.jitter.arch import JitCore_msp430 as jcore
           elif arch_name == "mips32":
               from miasm2.jitter.arch import JitCore_mips32 as jcore
           elif arch_name == "ppc32":
               from miasm2.jitter.arch import JitCore_ppc32 as jcore
           elif arch_name == "mep":
               from miasm2.jitter.arch import JitCore_mep as jcore
           else:
               raise ValueError("unknown jit arch: %s" % arch_name)
       except ImportError:
           raise RuntimeError('Unsupported jit arch: %s' % arch_name)
       self.vm = VmMngr.Vm()
       self.cpu = jcore.JitCpu()
       self.ir_arch = ir_arch
       self.bs = bin_stream_vm(self.vm)
       self.ircfg = self.ir_arch.new_ircfg()
       self.symbexec = EmulatedSymbExec(
           self.cpu, self.vm, self.ir_arch, {}
       )
       self.symbexec.reset_regs()
       try:
           if jit_type == "llvm":
               from miasm2.jitter.jitcore_llvm import JitCore_LLVM as JitCore
           elif jit_type == "python":
               from miasm2.jitter.jitcore_python import JitCore_Python as JitCore
           elif jit_type == "gcc":
               from miasm2.jitter.jitcore_gcc import JitCore_Gcc as JitCore
           else:
               raise ValueError("Unknown jitter %s" % jit_type)
       except ImportError:
           raise RuntimeError('Unsupported jitter: %s' % jit_type)
       self.jit = JitCore(self.ir_arch, self.bs)
       if isinstance(self.jit, JitCore_Cc_Base):
           self.jit.init_codegen(self.C_Gen(self.ir_arch))
       elif jit_type == "python":
           self.jit.set_cpu_vm(self.cpu, self.vm)
       self.cpu.init_regs()
       self.vm.init_memory_page_pool()
       self.vm.init_code_bloc_pool()
       self.vm.init_memory_breakpoint()
       self.jit.load()
       self.cpu.vmmngr = self.vm
       self.cpu.jitter = self.jit
       self.stack_size = 0x10000
       self.stack_base = 0x1230000
       # Init callback handler
       self.breakpoints_handler = CallbackHandler()
       self.exceptions_handler = CallbackHandlerBitflag()
       self.init_exceptions_handler()
       self.exec_cb = None
   def init_exceptions_handler(self):
       "Add common exceptions handlers"
       def exception_automod(jitter):
           "Tell the JiT backend to update blocks modified"
           self.jit.updt_automod_code(jitter.vm)
           self.vm.set_exception(0)
           return True
       def exception_memory_breakpoint(jitter):
           "Stop the execution and return an identifier"
           return ExceptionHandle.memoryBreakpoint()
       self.add_exception_handler(EXCEPT_CODE_AUTOMOD, exception_automod)
       self.add_exception_handler(EXCEPT_BREAKPOINT_MEMORY,
                                  exception_memory_breakpoint)
   def add_breakpoint(self, addr, callback):
       """Add a callback associated with addr.
       @addr: breakpoint address
       @callback: function with definition (jitter instance)
       """
       self.breakpoints_handler.add_callback(addr, callback)
       self.jit.add_disassembly_splits(addr)
       # De-jit previously jitted blocks
       self.jit.updt_automod_code_range(self.vm, [(addr, addr)])
   def set_breakpoint(self, addr, *args):
       """Set callbacks associated with addr.
       @addr: breakpoint address
       @args: functions with definition (jitter instance)
       """
       self.breakpoints_handler.set_callback(addr, *args)
       self.jit.add_disassembly_splits(addr)
   def get_breakpoint(self, addr):
       """
       Return breakpoints handlers for address @addr
       @addr: integer
       """
       return self.breakpoints_handler.get_callbacks(addr)
   def remove_breakpoints_by_callback(self, callback):
       """Remove callbacks associated with breakpoint.
       @callback: callback to remove
       """
       empty_keys = self.breakpoints_handler.remove_callback(callback)
       for key in empty_keys:
           self.jit.remove_disassembly_splits(key)
   def add_exception_handler(self, flag, callback):
       """Add a callback associated with an exception flag.
       @flag: bitflag
       @callback: function with definition (jitter instance)
       """
       self.exceptions_handler.add_callback(flag, callback)
   def run_at(self, pc):
       """Wrapper on JiT backend. Run the code at PC and return the next PC.
       @pc: address of code to run"""
       return self.jit.run_at(
           self.cpu, pc,
           set(self.breakpoints_handler.callbacks.keys())
       )
   def runiter_once(self, pc):
       """Iterator on callbacks results on code running from PC.
       Check exceptions before breakpoints."""
       self.pc = pc
       # Callback called before exec
       if self.exec_cb is not None:
           res = self.exec_cb(self)
           if res is not True:
               yield res
       # Check breakpoints
       old_pc = self.pc
       for res in self.breakpoints_handler.call_callbacks(self.pc, self):
           if res is not True:
               if isinstance(res, collections.Iterator):
                   # If the breakpoint is a generator, yield it step by step
                   for tmp in res:
                       yield tmp
               else:
                   yield res
       # Check exceptions (raised by breakpoints)
       exception_flag = self.get_exception()
       for res in self.exceptions_handler(exception_flag, self):
           if res is not True:
               if isinstance(res, collections.Iterator):
                   for tmp in res:
                       yield tmp
               else:
                   yield res
       # If a callback changed pc, re call every callback
       if old_pc != self.pc:
           return
       # Exceptions should never be activated before run
       assert(self.get_exception() == 0)
       # Run the bloc at PC
       self.pc = self.run_at(self.pc)
       # Check exceptions (raised by the execution of the block)
       exception_flag = self.get_exception()
       for res in self.exceptions_handler(exception_flag, self):
           if res is not True:
               if isinstance(res, collections.Iterator):
                   for tmp in res:
                       yield tmp
               else:
                   yield res
   def init_run(self, pc):
       """Create an iterator on pc with runiter.
       @pc: address of code to run
       """
       self.run_iterator = self.runiter_once(pc)
       self.pc = pc
       self.run = True
   def continue_run(self, step=False):
       """PRE: init_run.
       Continue the run of the current session until iterator returns or run is
       set to False.
       If step is True, run only one time.
       Return the iterator value"""
       while self.run:
           try:
               return self.run_iterator.next()
           except StopIteration:
               pass
           self.run_iterator = self.runiter_once(self.pc)
           if step is True:
               return None
       return None
   def init_stack(self):
       self.vm.add_memory_page(
           self.stack_base, PAGE_READ | PAGE_WRITE, "\x00" * self.stack_size,
           "Stack")
       sp = self.arch.getsp(self.attrib)
       setattr(self.cpu, sp.name, self.stack_base + self.stack_size)
       # regs = self.cpu.get_gpreg()
       # regs[sp.name] = self.stack_base+self.stack_size
       # self.cpu.set_gpreg(regs)
   def get_exception(self):
       return self.cpu.get_exception() | self.vm.get_exception()
   # commun functions
   def get_str_ansi(self, addr, max_char=None):
       """Get ansi str from vm.
       @addr: address in memory
       @max_char: maximum len"""
       l = 0
       tmp = addr
       while ((max_char is None or l < max_char) and
              self.vm.get_mem(tmp, 1) != "\x00"):
           tmp += 1
           l += 1
       return self.vm.get_mem(addr, l)
   def get_str_unic(self, addr, max_char=None):
       """Get unicode str from vm.
       @addr: address in memory
       @max_char: maximum len"""
       l = 0
       tmp = addr
       while ((max_char is None or l < max_char) and
              self.vm.get_mem(tmp, 2) != "\x00\x00"):
           tmp += 2
           l += 2
       s = self.vm.get_mem(addr, l)
       s = s[::2]  # TODO: real unicode decoding
       return s
   def set_str_ansi(self, addr, s):
       """Set an ansi string in memory"""
       s = s + "\x00"
       self.vm.set_mem(addr, s)
   def set_str_unic(self, addr, s):
       """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('%r', fname)
           raise ValueError('unknown api', hex(jitter.pc), repr(fname))
       ret = func(jitter)
       jitter.pc = getattr(jitter.cpu, jitter.ir_arch.pc.name)
       # Don't break on a None return
       if ret is None:
           return True
       else:
           return ret
   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
       @user_globals: dictionary 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)
   def eval_expr(self, expr):
       """Eval expression @expr in the context of the current instance. Side
       effects are passed on it"""
       self.symbexec.update_engine_from_cpu()
       ret = self.symbexec.eval_updt_expr(expr)
       self.symbexec.update_cpu_from_engine()
       return ret
   def set_trace_log(self,
                     trace_instr=True, trace_regs=True,
                     trace_new_blocks=False):
       """
       Activate/Deactivate trace log options
       @trace_instr: activate instructions tracing log
       @trace_regs: activate registers tracing log
       @trace_new_blocks: dump new code blocks log
       """
       # As trace state changes, clear already jitted blocks
       self.jit.clear_jitted_blocks()
       self.jit.log_mn = trace_instr
       self.jit.log_regs = trace_regs
       self.jit.log_newbloc = trace_new_blocks
lass jitter(Jitter):
   """
   DEPRECATED object
   Use Jitter instead of jitter
   """
   def __init__(self, *args, **kwargs):
       warnings.warn("Deprecated API: use Jitter")
       super(jitter, self).__init__(*args, **kwargs)

Module variables

var BREAKPOINT_READ

var BREAKPOINT_WRITE

var EXCEPT_ACCESS_VIOL

var EXCEPT_BREAKPOINT_INTERN

var EXCEPT_BREAKPOINT_MEMORY

var EXCEPT_CODE_AUTOMOD

var EXCEPT_DIV_BY_ZERO

var EXCEPT_DO_NOT_UPDATE_PC

var EXCEPT_ILLEGAL_INSN

var EXCEPT_INT_XX

var EXCEPT_NUM_UPDT_EIP

var EXCEPT_PRIV_INSN

var EXCEPT_SOFT_BP

var EXCEPT_SPR_ACCESS

var EXCEPT_UNK_MNEMO

var PAGE_EXEC

var PAGE_READ

var PAGE_WRITE

var hnd

var log

var log_func

var pck

Functions

def named_arguments(

func)

Function decorator to allow the use of .func_args_*() methods with either the number of arguments or the list of the argument names.

The wrapper is also used to log the argument values.

@func: function

def named_arguments(func):
    """Function decorator to allow the use of .func_args_*() methods
    with either the number of arguments or the list of the argument
    names.

    The wrapper is also used to log the argument values.

    @func: function

    """
    @wraps(func)
    def newfunc(self, args):
        if isinstance(args, Sequence):
            ret_ad, arg_vals = func(self, len(args))
            arg_vals = namedtuple("args", args)(*arg_vals)
            # func_name(arguments) return address
            log_func.info('%s(%s) ret addr: %s',
                          get_caller_name(1),
                          ', '.join("%s=0x%x" % (field, value)
                                    for field, value in arg_vals._asdict(
                                    ).iteritems()),
                         hex(ret_ad))
            return ret_ad, namedtuple("args", args)(*arg_vals)
        else:
            ret_ad, arg_vals = func(self, args)
            # func_name(arguments) return address
            log_func.info('%s(%s) ret addr: %s',
                get_caller_name(1),
                ', '.join(hex(arg) for arg in arg_vals),
                hex(ret_ad))
            return ret_ad, arg_vals
    return newfunc

Classes

class CallbackHandler

Handle a list of callback

class CallbackHandler(object):

    "Handle a list of callback"

    def __init__(self):
        self.callbacks = {}  # Key -> [callback list]

    def add_callback(self, 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'"
        self.callbacks[name] = list(args)

    def get_callbacks(self, name):
        "Return the list of callbacks associated to key 'name'"
        return self.callbacks.get(name, [])

    def remove_callback(self, callback):
        """Remove the callback from the list.
        Return the list of empty keys (removed)"""

        to_check = set()
        for key, cb_list in self.callbacks.items():
            try:
                cb_list.remove(callback)
                to_check.add(key)
            except ValueError:
                pass

        empty_keys = []
        for key in to_check:
            if len(self.callbacks[key]) == 0:
                empty_keys.append(key)
                del(self.callbacks[key])

        return empty_keys

    def has_callbacks(self, name):
        return name in self.callbacks

    def call_callbacks(self, name, *args):
        """Call callbacks associated to key 'name' with arguments args. While
        callbacks return True, continue with next callback.
        Iterator on other results."""

        res = True

        for c in self.get_callbacks(name):
            res = c(*args)
            if res is not True:
                yield res

    def __call__(self, name, *args):
        "Wrapper for call_callbacks"
        return self.call_callbacks(name, *args)

Ancestors (in MRO)

Instance variables

var callbacks

Methods

def __init__(

self)

def __init__(self):
    self.callbacks = {}  # Key -> [callback list]

def add_callback(

self, name, callback)

Add a callback to the key @name, iff the @callback isn't already assigned to it

def add_callback(self, 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 call_callbacks(

self, name, *args)

Call callbacks associated to key 'name' with arguments args. While callbacks return True, continue with next callback. Iterator on other results.

def call_callbacks(self, name, *args):
    """Call callbacks associated to key 'name' with arguments args. While
    callbacks return True, continue with next callback.
    Iterator on other results."""
    res = True
    for c in self.get_callbacks(name):
        res = c(*args)
        if res is not True:
            yield res

def get_callbacks(

self, name)

Return the list of callbacks associated to key 'name'

def get_callbacks(self, name):
    "Return the list of callbacks associated to key 'name'"
    return self.callbacks.get(name, [])

def has_callbacks(

self, name)

def has_callbacks(self, name):
    return name in self.callbacks

def remove_callback(

self, callback)

Remove the callback from the list. Return the list of empty keys (removed)

def remove_callback(self, callback):
    """Remove the callback from the list.
    Return the list of empty keys (removed)"""
    to_check = set()
    for key, cb_list in self.callbacks.items():
        try:
            cb_list.remove(callback)
            to_check.add(key)
        except ValueError:
            pass
    empty_keys = []
    for key in to_check:
        if len(self.callbacks[key]) == 0:
            empty_keys.append(key)
            del(self.callbacks[key])
    return empty_keys

def set_callback(

self, name, *args)

Set the list of callback for key 'name'

def set_callback(self, name, *args):
    "Set the list of callback for key 'name'"
    self.callbacks[name] = list(args)

class CallbackHandlerBitflag

Handle a list of callback with conditions on bitflag

class CallbackHandlerBitflag(CallbackHandler):

    "Handle a list of callback with conditions on bitflag"

    def call_callbacks(self, bitflag, *args):
        """Call each callbacks associated with bit set in bitflag. While
        callbacks return True, continue with next callback.
        Iterator on other results"""

        res = True
        for bitflag_expected in self.callbacks:
            if bitflag_expected & bitflag == bitflag_expected:
                # If the flag matched
                for res in super(CallbackHandlerBitflag,
                                 self).call_callbacks(bitflag_expected, *args):
                    if res is not True:
                        yield res

Ancestors (in MRO)

Instance variables

var callbacks

Inheritance: CallbackHandler.callbacks

Methods

def __init__(

self)

Inheritance: CallbackHandler.__init__

def __init__(self):
    self.callbacks = {}  # Key -> [callback list]

def add_callback(

self, name, callback)

Inheritance: CallbackHandler.add_callback

Add a callback to the key @name, iff the @callback isn't already assigned to it

def add_callback(self, 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 call_callbacks(

self, bitflag, *args)

Inheritance: CallbackHandler.call_callbacks

Call each callbacks associated with bit set in bitflag. While callbacks return True, continue with next callback. Iterator on other results

def call_callbacks(self, bitflag, *args):
    """Call each callbacks associated with bit set in bitflag. While
    callbacks return True, continue with next callback.
    Iterator on other results"""
    res = True
    for bitflag_expected in self.callbacks:
        if bitflag_expected & bitflag == bitflag_expected:
            # If the flag matched
            for res in super(CallbackHandlerBitflag,
                             self).call_callbacks(bitflag_expected, *args):
                if res is not True:
                    yield res

def get_callbacks(

self, name)

Inheritance: CallbackHandler.get_callbacks

Return the list of callbacks associated to key 'name'

def get_callbacks(self, name):
    "Return the list of callbacks associated to key 'name'"
    return self.callbacks.get(name, [])

def has_callbacks(

self, name)

Inheritance: CallbackHandler.has_callbacks

def has_callbacks(self, name):
    return name in self.callbacks

def remove_callback(

self, callback)

Inheritance: CallbackHandler.remove_callback

Remove the callback from the list. Return the list of empty keys (removed)

def remove_callback(self, callback):
    """Remove the callback from the list.
    Return the list of empty keys (removed)"""
    to_check = set()
    for key, cb_list in self.callbacks.items():
        try:
            cb_list.remove(callback)
            to_check.add(key)
        except ValueError:
            pass
    empty_keys = []
    for key in to_check:
        if len(self.callbacks[key]) == 0:
            empty_keys.append(key)
            del(self.callbacks[key])
    return empty_keys

def set_callback(

self, name, *args)

Inheritance: CallbackHandler.set_callback

Set the list of callback for key 'name'

def set_callback(self, name, *args):
    "Set the list of callback for key 'name'"
    self.callbacks[name] = list(args)

class ExceptionHandle

Return type for exception handler

class ExceptionHandle():

    "Return type for exception handler"

    def __init__(self, except_flag):
        self.except_flag = except_flag

    @classmethod
    def memoryBreakpoint(cls):
        return cls(EXCEPT_BREAKPOINT_MEMORY)

    def __eq__(self, to_cmp):
        if not isinstance(to_cmp, ExceptionHandle):
            return False
        return (self.except_flag == to_cmp.except_flag)

    def __ne__(self, to_cmp):
        return not self.__eq__(to_cmp)

Ancestors (in MRO)

Instance variables

var except_flag

Methods

def __init__(

self, except_flag)

def __init__(self, except_flag):
    self.except_flag = except_flag

def memoryBreakpoint(

cls)

@classmethod
def memoryBreakpoint(cls):
    return cls(EXCEPT_BREAKPOINT_MEMORY)

class Jitter

Main class for JIT handling

class Jitter(object):

    "Main class for JIT handling"

    C_Gen = CGen

    def __init__(self, ir_arch, jit_type="gcc"):
        """Init an instance of jitter.
        @ir_arch: ir instance for this architecture
        @jit_type: JiT backend to use. Available options are:
            - "gcc"
            - "llvm"
            - "python"
        """

        self.arch = ir_arch.arch
        self.attrib = ir_arch.attrib
        arch_name = ir_arch.arch.name  # (ir_arch.arch.name, ir_arch.attrib)

        try:
            if arch_name == "x86":
                from miasm2.jitter.arch import JitCore_x86 as jcore
            elif arch_name == "arm":
                from miasm2.jitter.arch import JitCore_arm as jcore
            elif arch_name == "armt":
                from miasm2.jitter.arch import JitCore_arm as jcore
                ir_arch.arch.name = 'arm'
            elif arch_name == "aarch64":
                from miasm2.jitter.arch import JitCore_aarch64 as jcore
            elif arch_name == "msp430":
                from miasm2.jitter.arch import JitCore_msp430 as jcore
            elif arch_name == "mips32":
                from miasm2.jitter.arch import JitCore_mips32 as jcore
            elif arch_name == "ppc32":
                from miasm2.jitter.arch import JitCore_ppc32 as jcore
            elif arch_name == "mep":
                from miasm2.jitter.arch import JitCore_mep as jcore
            else:
                raise ValueError("unknown jit arch: %s" % arch_name)
        except ImportError:
            raise RuntimeError('Unsupported jit arch: %s' % arch_name)

        self.vm = VmMngr.Vm()
        self.cpu = jcore.JitCpu()
        self.ir_arch = ir_arch
        self.bs = bin_stream_vm(self.vm)
        self.ircfg = self.ir_arch.new_ircfg()

        self.symbexec = EmulatedSymbExec(
            self.cpu, self.vm, self.ir_arch, {}
        )
        self.symbexec.reset_regs()

        try:
            if jit_type == "llvm":
                from miasm2.jitter.jitcore_llvm import JitCore_LLVM as JitCore
            elif jit_type == "python":
                from miasm2.jitter.jitcore_python import JitCore_Python as JitCore
            elif jit_type == "gcc":
                from miasm2.jitter.jitcore_gcc import JitCore_Gcc as JitCore
            else:
                raise ValueError("Unknown jitter %s" % jit_type)
        except ImportError:
            raise RuntimeError('Unsupported jitter: %s' % jit_type)

        self.jit = JitCore(self.ir_arch, self.bs)
        if isinstance(self.jit, JitCore_Cc_Base):
            self.jit.init_codegen(self.C_Gen(self.ir_arch))
        elif jit_type == "python":
            self.jit.set_cpu_vm(self.cpu, self.vm)

        self.cpu.init_regs()
        self.vm.init_memory_page_pool()
        self.vm.init_code_bloc_pool()
        self.vm.init_memory_breakpoint()

        self.jit.load()
        self.cpu.vmmngr = self.vm
        self.cpu.jitter = self.jit
        self.stack_size = 0x10000
        self.stack_base = 0x1230000

        # Init callback handler
        self.breakpoints_handler = CallbackHandler()
        self.exceptions_handler = CallbackHandlerBitflag()
        self.init_exceptions_handler()
        self.exec_cb = None

    def init_exceptions_handler(self):
        "Add common exceptions handlers"

        def exception_automod(jitter):
            "Tell the JiT backend to update blocks modified"

            self.jit.updt_automod_code(jitter.vm)
            self.vm.set_exception(0)

            return True

        def exception_memory_breakpoint(jitter):
            "Stop the execution and return an identifier"
            return ExceptionHandle.memoryBreakpoint()

        self.add_exception_handler(EXCEPT_CODE_AUTOMOD, exception_automod)
        self.add_exception_handler(EXCEPT_BREAKPOINT_MEMORY,
                                   exception_memory_breakpoint)

    def add_breakpoint(self, addr, callback):
        """Add a callback associated with addr.
        @addr: breakpoint address
        @callback: function with definition (jitter instance)
        """
        self.breakpoints_handler.add_callback(addr, callback)
        self.jit.add_disassembly_splits(addr)
        # De-jit previously jitted blocks
        self.jit.updt_automod_code_range(self.vm, [(addr, addr)])

    def set_breakpoint(self, addr, *args):
        """Set callbacks associated with addr.
        @addr: breakpoint address
        @args: functions with definition (jitter instance)
        """
        self.breakpoints_handler.set_callback(addr, *args)
        self.jit.add_disassembly_splits(addr)

    def get_breakpoint(self, addr):
        """
        Return breakpoints handlers for address @addr
        @addr: integer
        """
        return self.breakpoints_handler.get_callbacks(addr)

    def remove_breakpoints_by_callback(self, callback):
        """Remove callbacks associated with breakpoint.
        @callback: callback to remove
        """
        empty_keys = self.breakpoints_handler.remove_callback(callback)
        for key in empty_keys:
            self.jit.remove_disassembly_splits(key)

    def add_exception_handler(self, flag, callback):
        """Add a callback associated with an exception flag.
        @flag: bitflag
        @callback: function with definition (jitter instance)
        """
        self.exceptions_handler.add_callback(flag, callback)

    def run_at(self, pc):
        """Wrapper on JiT backend. Run the code at PC and return the next PC.
        @pc: address of code to run"""

        return self.jit.run_at(
            self.cpu, pc,
            set(self.breakpoints_handler.callbacks.keys())
        )

    def runiter_once(self, pc):
        """Iterator on callbacks results on code running from PC.
        Check exceptions before breakpoints."""

        self.pc = pc
        # Callback called before exec
        if self.exec_cb is not None:
            res = self.exec_cb(self)
            if res is not True:
                yield res

        # Check breakpoints
        old_pc = self.pc
        for res in self.breakpoints_handler.call_callbacks(self.pc, self):
            if res is not True:
                if isinstance(res, collections.Iterator):
                    # If the breakpoint is a generator, yield it step by step
                    for tmp in res:
                        yield tmp
                else:
                    yield res

        # Check exceptions (raised by breakpoints)
        exception_flag = self.get_exception()
        for res in self.exceptions_handler(exception_flag, self):
            if res is not True:
                if isinstance(res, collections.Iterator):
                    for tmp in res:
                        yield tmp
                else:
                    yield res

        # If a callback changed pc, re call every callback
        if old_pc != self.pc:
            return

        # Exceptions should never be activated before run
        assert(self.get_exception() == 0)

        # Run the bloc at PC
        self.pc = self.run_at(self.pc)

        # Check exceptions (raised by the execution of the block)
        exception_flag = self.get_exception()
        for res in self.exceptions_handler(exception_flag, self):
            if res is not True:
                if isinstance(res, collections.Iterator):
                    for tmp in res:
                        yield tmp
                else:
                    yield res

    def init_run(self, pc):
        """Create an iterator on pc with runiter.
        @pc: address of code to run
        """
        self.run_iterator = self.runiter_once(pc)
        self.pc = pc
        self.run = True

    def continue_run(self, step=False):
        """PRE: init_run.
        Continue the run of the current session until iterator returns or run is
        set to False.
        If step is True, run only one time.
        Return the iterator value"""

        while self.run:
            try:
                return self.run_iterator.next()
            except StopIteration:
                pass

            self.run_iterator = self.runiter_once(self.pc)

            if step is True:
                return None

        return None

    def init_stack(self):
        self.vm.add_memory_page(
            self.stack_base, PAGE_READ | PAGE_WRITE, "\x00" * self.stack_size,
            "Stack")
        sp = self.arch.getsp(self.attrib)
        setattr(self.cpu, sp.name, self.stack_base + self.stack_size)
        # regs = self.cpu.get_gpreg()
        # regs[sp.name] = self.stack_base+self.stack_size
        # self.cpu.set_gpreg(regs)

    def get_exception(self):
        return self.cpu.get_exception() | self.vm.get_exception()

    # commun functions
    def get_str_ansi(self, addr, max_char=None):
        """Get ansi str from vm.
        @addr: address in memory
        @max_char: maximum len"""
        l = 0
        tmp = addr
        while ((max_char is None or l < max_char) and
               self.vm.get_mem(tmp, 1) != "\x00"):
            tmp += 1
            l += 1
        return self.vm.get_mem(addr, l)

    def get_str_unic(self, addr, max_char=None):
        """Get unicode str from vm.
        @addr: address in memory
        @max_char: maximum len"""
        l = 0
        tmp = addr
        while ((max_char is None or l < max_char) and
               self.vm.get_mem(tmp, 2) != "\x00\x00"):
            tmp += 2
            l += 2
        s = self.vm.get_mem(addr, l)
        s = s[::2]  # TODO: real unicode decoding
        return s

    def set_str_ansi(self, addr, s):
        """Set an ansi string in memory"""
        s = s + "\x00"
        self.vm.set_mem(addr, s)

    def set_str_unic(self, addr, s):
        """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('%r', fname)
            raise ValueError('unknown api', hex(jitter.pc), repr(fname))
        ret = func(jitter)
        jitter.pc = getattr(jitter.cpu, jitter.ir_arch.pc.name)

        # Don't break on a None return
        if ret is None:
            return True
        else:
            return ret

    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
        @user_globals: dictionary 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)

    def eval_expr(self, expr):
        """Eval expression @expr in the context of the current instance. Side
        effects are passed on it"""
        self.symbexec.update_engine_from_cpu()
        ret = self.symbexec.eval_updt_expr(expr)
        self.symbexec.update_cpu_from_engine()

        return ret

    def set_trace_log(self,
                      trace_instr=True, trace_regs=True,
                      trace_new_blocks=False):
        """
        Activate/Deactivate trace log options

        @trace_instr: activate instructions tracing log
        @trace_regs: activate registers tracing log
        @trace_new_blocks: dump new code blocks log
        """

        # As trace state changes, clear already jitted blocks
        self.jit.clear_jitted_blocks()

        self.jit.log_mn = trace_instr
        self.jit.log_regs = trace_regs
        self.jit.log_newbloc = trace_new_blocks

Ancestors (in MRO)

Class variables

var C_Gen

Static methods

def handle_lib(

jitter)

Resolve the name of the function which cause the handler call. Then call the corresponding handler from users callback.

@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('%r', fname)
        raise ValueError('unknown api', hex(jitter.pc), repr(fname))
    ret = func(jitter)
    jitter.pc = getattr(jitter.cpu, jitter.ir_arch.pc.name)
    # Don't break on a None return
    if ret is None:
        return True
    else:
        return ret

Instance variables

var arch

var attrib

var breakpoints_handler

var bs

var cpu

var exceptions_handler

var exec_cb

var ir_arch

var ircfg

var jit

var stack_base

var stack_size

var symbexec

var vm

Methods

def __init__(

self, ir_arch, jit_type='gcc')

Init an instance of jitter. @ir_arch: ir instance for this architecture @jit_type: JiT backend to use. Available options are: - "gcc" - "llvm" - "python"

def __init__(self, ir_arch, jit_type="gcc"):
    """Init an instance of jitter.
    @ir_arch: ir instance for this architecture
    @jit_type: JiT backend to use. Available options are:
        - "gcc"
        - "llvm"
        - "python"
    """
    self.arch = ir_arch.arch
    self.attrib = ir_arch.attrib
    arch_name = ir_arch.arch.name  # (ir_arch.arch.name, ir_arch.attrib)
    try:
        if arch_name == "x86":
            from miasm2.jitter.arch import JitCore_x86 as jcore
        elif arch_name == "arm":
            from miasm2.jitter.arch import JitCore_arm as jcore
        elif arch_name == "armt":
            from miasm2.jitter.arch import JitCore_arm as jcore
            ir_arch.arch.name = 'arm'
        elif arch_name == "aarch64":
            from miasm2.jitter.arch import JitCore_aarch64 as jcore
        elif arch_name == "msp430":
            from miasm2.jitter.arch import JitCore_msp430 as jcore
        elif arch_name == "mips32":
            from miasm2.jitter.arch import JitCore_mips32 as jcore
        elif arch_name == "ppc32":
            from miasm2.jitter.arch import JitCore_ppc32 as jcore
        elif arch_name == "mep":
            from miasm2.jitter.arch import JitCore_mep as jcore
        else:
            raise ValueError("unknown jit arch: %s" % arch_name)
    except ImportError:
        raise RuntimeError('Unsupported jit arch: %s' % arch_name)
    self.vm = VmMngr.Vm()
    self.cpu = jcore.JitCpu()
    self.ir_arch = ir_arch
    self.bs = bin_stream_vm(self.vm)
    self.ircfg = self.ir_arch.new_ircfg()
    self.symbexec = EmulatedSymbExec(
        self.cpu, self.vm, self.ir_arch, {}
    )
    self.symbexec.reset_regs()
    try:
        if jit_type == "llvm":
            from miasm2.jitter.jitcore_llvm import JitCore_LLVM as JitCore
        elif jit_type == "python":
            from miasm2.jitter.jitcore_python import JitCore_Python as JitCore
        elif jit_type == "gcc":
            from miasm2.jitter.jitcore_gcc import JitCore_Gcc as JitCore
        else:
            raise ValueError("Unknown jitter %s" % jit_type)
    except ImportError:
        raise RuntimeError('Unsupported jitter: %s' % jit_type)
    self.jit = JitCore(self.ir_arch, self.bs)
    if isinstance(self.jit, JitCore_Cc_Base):
        self.jit.init_codegen(self.C_Gen(self.ir_arch))
    elif jit_type == "python":
        self.jit.set_cpu_vm(self.cpu, self.vm)
    self.cpu.init_regs()
    self.vm.init_memory_page_pool()
    self.vm.init_code_bloc_pool()
    self.vm.init_memory_breakpoint()
    self.jit.load()
    self.cpu.vmmngr = self.vm
    self.cpu.jitter = self.jit
    self.stack_size = 0x10000
    self.stack_base = 0x1230000
    # Init callback handler
    self.breakpoints_handler = CallbackHandler()
    self.exceptions_handler = CallbackHandlerBitflag()
    self.init_exceptions_handler()
    self.exec_cb = None

def add_breakpoint(

self, addr, callback)

Add a callback associated with addr. @addr: breakpoint address @callback: function with definition (jitter instance)

def add_breakpoint(self, addr, callback):
    """Add a callback associated with addr.
    @addr: breakpoint address
    @callback: function with definition (jitter instance)
    """
    self.breakpoints_handler.add_callback(addr, callback)
    self.jit.add_disassembly_splits(addr)
    # De-jit previously jitted blocks
    self.jit.updt_automod_code_range(self.vm, [(addr, addr)])

def add_exception_handler(

self, flag, callback)

Add a callback associated with an exception flag. @flag: bitflag @callback: function with definition (jitter instance)

def add_exception_handler(self, flag, callback):
    """Add a callback associated with an exception flag.
    @flag: bitflag
    @callback: function with definition (jitter instance)
    """
    self.exceptions_handler.add_callback(flag, callback)

def add_lib_handler(

self, libs, user_globals=None)

Add a function to handle libs call with breakpoints @libs: libimp instance @user_globals: dictionary for defined user function

def add_lib_handler(self, libs, user_globals=None):
    """Add a function to handle libs call with breakpoints
    @libs: libimp instance
    @user_globals: dictionary 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)

def continue_run(

self, step=False)

PRE: init_run. Continue the run of the current session until iterator returns or run is set to False. If step is True, run only one time. Return the iterator value

def continue_run(self, step=False):
    """PRE: init_run.
    Continue the run of the current session until iterator returns or run is
    set to False.
    If step is True, run only one time.
    Return the iterator value"""
    while self.run:
        try:
            return self.run_iterator.next()
        except StopIteration:
            pass
        self.run_iterator = self.runiter_once(self.pc)
        if step is True:
            return None
    return None

def eval_expr(

self, expr)

Eval expression @expr in the context of the current instance. Side effects are passed on it

def eval_expr(self, expr):
    """Eval expression @expr in the context of the current instance. Side
    effects are passed on it"""
    self.symbexec.update_engine_from_cpu()
    ret = self.symbexec.eval_updt_expr(expr)
    self.symbexec.update_cpu_from_engine()
    return ret

def get_breakpoint(

self, addr)

Return breakpoints handlers for address @addr @addr: integer

def get_breakpoint(self, addr):
    """
    Return breakpoints handlers for address @addr
    @addr: integer
    """
    return self.breakpoints_handler.get_callbacks(addr)

def get_exception(

self)

def get_exception(self):
    return self.cpu.get_exception() | self.vm.get_exception()

def get_str_ansi(

self, addr, max_char=None)

Get ansi str from vm. @addr: address in memory @max_char: maximum len

def get_str_ansi(self, addr, max_char=None):
    """Get ansi str from vm.
    @addr: address in memory
    @max_char: maximum len"""
    l = 0
    tmp = addr
    while ((max_char is None or l < max_char) and
           self.vm.get_mem(tmp, 1) != "\x00"):
        tmp += 1
        l += 1
    return self.vm.get_mem(addr, l)

def get_str_unic(

self, addr, max_char=None)

Get unicode str from vm. @addr: address in memory @max_char: maximum len

def get_str_unic(self, addr, max_char=None):
    """Get unicode str from vm.
    @addr: address in memory
    @max_char: maximum len"""
    l = 0
    tmp = addr
    while ((max_char is None or l < max_char) and
           self.vm.get_mem(tmp, 2) != "\x00\x00"):
        tmp += 2
        l += 2
    s = self.vm.get_mem(addr, l)
    s = s[::2]  # TODO: real unicode decoding
    return s

def handle_function(

self, f_addr)

Add a breakpoint which will trigger the function handler

def handle_function(self, f_addr):
    """Add a breakpoint which will trigger the function handler"""
    self.add_breakpoint(f_addr, self.handle_lib)

def init_exceptions_handler(

self)

Add common exceptions handlers

def init_exceptions_handler(self):
    "Add common exceptions handlers"
    def exception_automod(jitter):
        "Tell the JiT backend to update blocks modified"
        self.jit.updt_automod_code(jitter.vm)
        self.vm.set_exception(0)
        return True
    def exception_memory_breakpoint(jitter):
        "Stop the execution and return an identifier"
        return ExceptionHandle.memoryBreakpoint()
    self.add_exception_handler(EXCEPT_CODE_AUTOMOD, exception_automod)
    self.add_exception_handler(EXCEPT_BREAKPOINT_MEMORY,
                               exception_memory_breakpoint)

def init_run(

self, pc)

Create an iterator on pc with runiter. @pc: address of code to run

def init_run(self, pc):
    """Create an iterator on pc with runiter.
    @pc: address of code to run
    """
    self.run_iterator = self.runiter_once(pc)
    self.pc = pc
    self.run = True

def init_stack(

self)

def init_stack(self):
    self.vm.add_memory_page(
        self.stack_base, PAGE_READ | PAGE_WRITE, "\x00" * self.stack_size,
        "Stack")
    sp = self.arch.getsp(self.attrib)
    setattr(self.cpu, sp.name, self.stack_base + self.stack_size)

def remove_breakpoints_by_callback(

self, callback)

Remove callbacks associated with breakpoint. @callback: callback to remove

def remove_breakpoints_by_callback(self, callback):
    """Remove callbacks associated with breakpoint.
    @callback: callback to remove
    """
    empty_keys = self.breakpoints_handler.remove_callback(callback)
    for key in empty_keys:
        self.jit.remove_disassembly_splits(key)

def run_at(

self, pc)

Wrapper on JiT backend. Run the code at PC and return the next PC. @pc: address of code to run

def run_at(self, pc):
    """Wrapper on JiT backend. Run the code at PC and return the next PC.
    @pc: address of code to run"""
    return self.jit.run_at(
        self.cpu, pc,
        set(self.breakpoints_handler.callbacks.keys())
    )

def runiter_once(

self, pc)

Iterator on callbacks results on code running from PC. Check exceptions before breakpoints.

def runiter_once(self, pc):
    """Iterator on callbacks results on code running from PC.
    Check exceptions before breakpoints."""
    self.pc = pc
    # Callback called before exec
    if self.exec_cb is not None:
        res = self.exec_cb(self)
        if res is not True:
            yield res
    # Check breakpoints
    old_pc = self.pc
    for res in self.breakpoints_handler.call_callbacks(self.pc, self):
        if res is not True:
            if isinstance(res, collections.Iterator):
                # If the breakpoint is a generator, yield it step by step
                for tmp in res:
                    yield tmp
            else:
                yield res
    # Check exceptions (raised by breakpoints)
    exception_flag = self.get_exception()
    for res in self.exceptions_handler(exception_flag, self):
        if res is not True:
            if isinstance(res, collections.Iterator):
                for tmp in res:
                    yield tmp
            else:
                yield res
    # If a callback changed pc, re call every callback
    if old_pc != self.pc:
        return
    # Exceptions should never be activated before run
    assert(self.get_exception() == 0)
    # Run the bloc at PC
    self.pc = self.run_at(self.pc)
    # Check exceptions (raised by the execution of the block)
    exception_flag = self.get_exception()
    for res in self.exceptions_handler(exception_flag, self):
        if res is not True:
            if isinstance(res, collections.Iterator):
                for tmp in res:
                    yield tmp
            else:
                yield res

def set_breakpoint(

self, addr, *args)

Set callbacks associated with addr. @addr: breakpoint address @args: functions with definition (jitter instance)

def set_breakpoint(self, addr, *args):
    """Set callbacks associated with addr.
    @addr: breakpoint address
    @args: functions with definition (jitter instance)
    """
    self.breakpoints_handler.set_callback(addr, *args)
    self.jit.add_disassembly_splits(addr)

def set_str_ansi(

self, addr, s)

Set an ansi string in memory

def set_str_ansi(self, addr, s):
    """Set an ansi string in memory"""
    s = s + "\x00"
    self.vm.set_mem(addr, s)

def set_str_unic(

self, addr, s)

Set an unicode string in memory

def set_str_unic(self, addr, s):
    """Set an unicode string in memory"""
    s = "\x00".join(list(s)) + '\x00' * 3
    self.vm.set_mem(addr, s)

def set_trace_log(

self, trace_instr=True, trace_regs=True, trace_new_blocks=False)

Activate/Deactivate trace log options

@trace_instr: activate instructions tracing log @trace_regs: activate registers tracing log @trace_new_blocks: dump new code blocks log

def set_trace_log(self,
                  trace_instr=True, trace_regs=True,
                  trace_new_blocks=False):
    """
    Activate/Deactivate trace log options
    @trace_instr: activate instructions tracing log
    @trace_regs: activate registers tracing log
    @trace_new_blocks: dump new code blocks log
    """
    # As trace state changes, clear already jitted blocks
    self.jit.clear_jitted_blocks()
    self.jit.log_mn = trace_instr
    self.jit.log_regs = trace_regs
    self.jit.log_newbloc = trace_new_blocks

class jitter

DEPRECATED object Use Jitter instead of jitter

class jitter(Jitter):
    """
    DEPRECATED object
    Use Jitter instead of jitter
    """


    def __init__(self, *args, **kwargs):
        warnings.warn("Deprecated API: use Jitter")
        super(jitter, self).__init__(*args, **kwargs)

Ancestors (in MRO)

Class variables

var C_Gen

Inheritance: Jitter.C_Gen

Static methods

def handle_lib(

jitter)

Inheritance: Jitter.handle_lib

Resolve the name of the function which cause the handler call. Then call the corresponding handler from users callback.

@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('%r', fname)
        raise ValueError('unknown api', hex(jitter.pc), repr(fname))
    ret = func(jitter)
    jitter.pc = getattr(jitter.cpu, jitter.ir_arch.pc.name)
    # Don't break on a None return
    if ret is None:
        return True
    else:
        return ret

Instance variables

var arch

Inheritance: Jitter.arch

var attrib

Inheritance: Jitter.attrib

var breakpoints_handler

Inheritance: Jitter.breakpoints_handler

var bs

Inheritance: Jitter.bs

var cpu

Inheritance: Jitter.cpu

var exceptions_handler

Inheritance: Jitter.exceptions_handler

var exec_cb

Inheritance: Jitter.exec_cb

var ir_arch

Inheritance: Jitter.ir_arch

var ircfg

Inheritance: Jitter.ircfg

var jit

Inheritance: Jitter.jit

var stack_base

Inheritance: Jitter.stack_base

var stack_size

Inheritance: Jitter.stack_size

var symbexec

Inheritance: Jitter.symbexec

var vm

Inheritance: Jitter.vm

Methods

def __init__(

self, *args, **kwargs)

Inheritance: Jitter.__init__

Init an instance of jitter. @ir_arch: ir instance for this architecture @jit_type: JiT backend to use. Available options are: - "gcc" - "llvm" - "python"

def __init__(self, *args, **kwargs):
    warnings.warn("Deprecated API: use Jitter")
    super(jitter, self).__init__(*args, **kwargs)

def add_breakpoint(

self, addr, callback)

Inheritance: Jitter.add_breakpoint

Add a callback associated with addr. @addr: breakpoint address @callback: function with definition (jitter instance)

def add_breakpoint(self, addr, callback):
    """Add a callback associated with addr.
    @addr: breakpoint address
    @callback: function with definition (jitter instance)
    """
    self.breakpoints_handler.add_callback(addr, callback)
    self.jit.add_disassembly_splits(addr)
    # De-jit previously jitted blocks
    self.jit.updt_automod_code_range(self.vm, [(addr, addr)])

def add_exception_handler(

self, flag, callback)

Inheritance: Jitter.add_exception_handler

Add a callback associated with an exception flag. @flag: bitflag @callback: function with definition (jitter instance)

def add_exception_handler(self, flag, callback):
    """Add a callback associated with an exception flag.
    @flag: bitflag
    @callback: function with definition (jitter instance)
    """
    self.exceptions_handler.add_callback(flag, callback)

def add_lib_handler(

self, libs, user_globals=None)

Inheritance: Jitter.add_lib_handler

Add a function to handle libs call with breakpoints @libs: libimp instance @user_globals: dictionary for defined user function

def add_lib_handler(self, libs, user_globals=None):
    """Add a function to handle libs call with breakpoints
    @libs: libimp instance
    @user_globals: dictionary 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)

def continue_run(

self, step=False)

Inheritance: Jitter.continue_run

PRE: init_run. Continue the run of the current session until iterator returns or run is set to False. If step is True, run only one time. Return the iterator value

def continue_run(self, step=False):
    """PRE: init_run.
    Continue the run of the current session until iterator returns or run is
    set to False.
    If step is True, run only one time.
    Return the iterator value"""
    while self.run:
        try:
            return self.run_iterator.next()
        except StopIteration:
            pass
        self.run_iterator = self.runiter_once(self.pc)
        if step is True:
            return None
    return None

def eval_expr(

self, expr)

Inheritance: Jitter.eval_expr

Eval expression @expr in the context of the current instance. Side effects are passed on it

def eval_expr(self, expr):
    """Eval expression @expr in the context of the current instance. Side
    effects are passed on it"""
    self.symbexec.update_engine_from_cpu()
    ret = self.symbexec.eval_updt_expr(expr)
    self.symbexec.update_cpu_from_engine()
    return ret

def get_breakpoint(

self, addr)

Inheritance: Jitter.get_breakpoint

Return breakpoints handlers for address @addr @addr: integer

def get_breakpoint(self, addr):
    """
    Return breakpoints handlers for address @addr
    @addr: integer
    """
    return self.breakpoints_handler.get_callbacks(addr)

def get_exception(

self)

Inheritance: Jitter.get_exception

def get_exception(self):
    return self.cpu.get_exception() | self.vm.get_exception()

def get_str_ansi(

self, addr, max_char=None)

Inheritance: Jitter.get_str_ansi

Get ansi str from vm. @addr: address in memory @max_char: maximum len

def get_str_ansi(self, addr, max_char=None):
    """Get ansi str from vm.
    @addr: address in memory
    @max_char: maximum len"""
    l = 0
    tmp = addr
    while ((max_char is None or l < max_char) and
           self.vm.get_mem(tmp, 1) != "\x00"):
        tmp += 1
        l += 1
    return self.vm.get_mem(addr, l)

def get_str_unic(

self, addr, max_char=None)

Inheritance: Jitter.get_str_unic

Get unicode str from vm. @addr: address in memory @max_char: maximum len

def get_str_unic(self, addr, max_char=None):
    """Get unicode str from vm.
    @addr: address in memory
    @max_char: maximum len"""
    l = 0
    tmp = addr
    while ((max_char is None or l < max_char) and
           self.vm.get_mem(tmp, 2) != "\x00\x00"):
        tmp += 2
        l += 2
    s = self.vm.get_mem(addr, l)
    s = s[::2]  # TODO: real unicode decoding
    return s

def handle_function(

self, f_addr)

Inheritance: Jitter.handle_function

Add a breakpoint which will trigger the function handler

def handle_function(self, f_addr):
    """Add a breakpoint which will trigger the function handler"""
    self.add_breakpoint(f_addr, self.handle_lib)

def init_exceptions_handler(

self)

Inheritance: Jitter.init_exceptions_handler

Add common exceptions handlers

def init_exceptions_handler(self):
    "Add common exceptions handlers"
    def exception_automod(jitter):
        "Tell the JiT backend to update blocks modified"
        self.jit.updt_automod_code(jitter.vm)
        self.vm.set_exception(0)
        return True
    def exception_memory_breakpoint(jitter):
        "Stop the execution and return an identifier"
        return ExceptionHandle.memoryBreakpoint()
    self.add_exception_handler(EXCEPT_CODE_AUTOMOD, exception_automod)
    self.add_exception_handler(EXCEPT_BREAKPOINT_MEMORY,
                               exception_memory_breakpoint)

def init_run(

self, pc)

Inheritance: Jitter.init_run

Create an iterator on pc with runiter. @pc: address of code to run

def init_run(self, pc):
    """Create an iterator on pc with runiter.
    @pc: address of code to run
    """
    self.run_iterator = self.runiter_once(pc)
    self.pc = pc
    self.run = True

def init_stack(

self)

Inheritance: Jitter.init_stack

def init_stack(self):
    self.vm.add_memory_page(
        self.stack_base, PAGE_READ | PAGE_WRITE, "\x00" * self.stack_size,
        "Stack")
    sp = self.arch.getsp(self.attrib)
    setattr(self.cpu, sp.name, self.stack_base + self.stack_size)

def remove_breakpoints_by_callback(

self, callback)

Inheritance: Jitter.remove_breakpoints_by_callback

Remove callbacks associated with breakpoint. @callback: callback to remove

def remove_breakpoints_by_callback(self, callback):
    """Remove callbacks associated with breakpoint.
    @callback: callback to remove
    """
    empty_keys = self.breakpoints_handler.remove_callback(callback)
    for key in empty_keys:
        self.jit.remove_disassembly_splits(key)

def run_at(

self, pc)

Inheritance: Jitter.run_at

Wrapper on JiT backend. Run the code at PC and return the next PC. @pc: address of code to run

def run_at(self, pc):
    """Wrapper on JiT backend. Run the code at PC and return the next PC.
    @pc: address of code to run"""
    return self.jit.run_at(
        self.cpu, pc,
        set(self.breakpoints_handler.callbacks.keys())
    )

def runiter_once(

self, pc)

Inheritance: Jitter.runiter_once

Iterator on callbacks results on code running from PC. Check exceptions before breakpoints.

def runiter_once(self, pc):
    """Iterator on callbacks results on code running from PC.
    Check exceptions before breakpoints."""
    self.pc = pc
    # Callback called before exec
    if self.exec_cb is not None:
        res = self.exec_cb(self)
        if res is not True:
            yield res
    # Check breakpoints
    old_pc = self.pc
    for res in self.breakpoints_handler.call_callbacks(self.pc, self):
        if res is not True:
            if isinstance(res, collections.Iterator):
                # If the breakpoint is a generator, yield it step by step
                for tmp in res:
                    yield tmp
            else:
                yield res
    # Check exceptions (raised by breakpoints)
    exception_flag = self.get_exception()
    for res in self.exceptions_handler(exception_flag, self):
        if res is not True:
            if isinstance(res, collections.Iterator):
                for tmp in res:
                    yield tmp
            else:
                yield res
    # If a callback changed pc, re call every callback
    if old_pc != self.pc:
        return
    # Exceptions should never be activated before run
    assert(self.get_exception() == 0)
    # Run the bloc at PC
    self.pc = self.run_at(self.pc)
    # Check exceptions (raised by the execution of the block)
    exception_flag = self.get_exception()
    for res in self.exceptions_handler(exception_flag, self):
        if res is not True:
            if isinstance(res, collections.Iterator):
                for tmp in res:
                    yield tmp
            else:
                yield res

def set_breakpoint(

self, addr, *args)

Inheritance: Jitter.set_breakpoint

Set callbacks associated with addr. @addr: breakpoint address @args: functions with definition (jitter instance)

def set_breakpoint(self, addr, *args):
    """Set callbacks associated with addr.
    @addr: breakpoint address
    @args: functions with definition (jitter instance)
    """
    self.breakpoints_handler.set_callback(addr, *args)
    self.jit.add_disassembly_splits(addr)

def set_str_ansi(

self, addr, s)

Inheritance: Jitter.set_str_ansi

Set an ansi string in memory

def set_str_ansi(self, addr, s):
    """Set an ansi string in memory"""
    s = s + "\x00"
    self.vm.set_mem(addr, s)

def set_str_unic(

self, addr, s)

Inheritance: Jitter.set_str_unic

Set an unicode string in memory

def set_str_unic(self, addr, s):
    """Set an unicode string in memory"""
    s = "\x00".join(list(s)) + '\x00' * 3
    self.vm.set_mem(addr, s)

def set_trace_log(

self, trace_instr=True, trace_regs=True, trace_new_blocks=False)

Inheritance: Jitter.set_trace_log

Activate/Deactivate trace log options

@trace_instr: activate instructions tracing log @trace_regs: activate registers tracing log @trace_new_blocks: dump new code blocks log

def set_trace_log(self,
                  trace_instr=True, trace_regs=True,
                  trace_new_blocks=False):
    """
    Activate/Deactivate trace log options
    @trace_instr: activate instructions tracing log
    @trace_regs: activate registers tracing log
    @trace_new_blocks: dump new code blocks log
    """
    # As trace state changes, clear already jitted blocks
    self.jit.clear_jitted_blocks()
    self.jit.log_mn = trace_instr
    self.jit.log_regs = trace_regs
    self.jit.log_newbloc = trace_new_blocks