Esempio n. 1
0
    def blocks_to_memrange(self, blocks):
        """Return an interval instance standing for blocks addresses
        @blocks: list of AsmBlock instances
        """

        mem_range = interval()

        for block in blocks:
            mem_range += interval([(block.ad_min, block.ad_max - 1)])

        return mem_range
Esempio n. 2
0
    def __init__(self, ir_arch, bin_stream):
        """Initialise a JitCore instance.
        @ir_arch: ir instance for current architecture
        @bin_stream: bin_stream instance
        """
        # Arch related
        self.ir_arch = ir_arch
        self.ircfg = self.ir_arch.new_ircfg()
        self.arch_name = "%s%s" % (self.ir_arch.arch.name, self.ir_arch.attrib)

        # Structures for block tracking
        self.offset_to_jitted_func = BoundedDict(self.jitted_block_max_size,
                                       delete_cb=self.jitted_block_delete_cb)
        self.loc_key_to_block = {}
        self.blocks_mem_interval = interval()

        # Logging & options
        self.log_mn = False
        self.log_regs = False
        self.log_newbloc = False
        self.options = {"jit_maxline": 50,  # Maximum number of line jitted
                        "max_exec_per_call": 0 # 0 means no limit
                        }

        # Disassembly Engine
        self.split_dis = set()
        self.mdis = disasmEngine(
            ir_arch.arch, ir_arch.attrib, bin_stream,
            lines_wd=self.options["jit_maxline"],
            loc_db=ir_arch.loc_db,
            follow_call=False,
            dontdis_retcall=False,
            split_dis=self.split_dis,
        )
Esempio n. 3
0
    def add_block_to_mem_interval(self, vm, block):
        "Update vm to include block addresses in its memory range"
        self.blocks_mem_interval += interval([(block.ad_min, block.ad_max - 1)])

        vm.reset_code_bloc_pool()
        for a, b in self.blocks_mem_interval:
            vm.add_code_bloc(a, b + 1)
Esempio n. 4
0
File: elf.py Progetto: cea-sec/miasm
def vm_load_elf(vm, fdata, name="", base_addr=0, loc_db=None, apply_reloc=False,
                **kargs):
    """
    Very dirty elf loader
    TODO XXX: implement real loader
    """
    elf = elf_init.ELF(fdata, **kargs)
    i = interval()
    all_data = {}

    for p in elf.ph.phlist:
        if p.ph.type != elf_csts.PT_LOAD:
            continue
        log.debug(
            '0x%x 0x%x 0x%x 0x%x 0x%x', p.ph.vaddr, p.ph.memsz, p.ph.offset,
                  p.ph.filesz, p.ph.type)
        data_o = elf._content[p.ph.offset:p.ph.offset + p.ph.filesz]
        addr_o = p.ph.vaddr + base_addr
        a_addr = addr_o & ~0xFFF
        b_addr = addr_o + max(p.ph.memsz, p.ph.filesz)
        b_addr = (b_addr + 0xFFF) & ~0xFFF
        all_data[addr_o] = data_o
        # -2: Trick to avoid merging 2 consecutive pages
        i += [(a_addr, b_addr - 2)]
    for a, b in i.intervals:
        vm.add_memory_page(
            a,
            PAGE_READ | PAGE_WRITE,
            b"\x00" * (b + 2 - a),
            repr(name)
        )

    for r_vaddr, data in viewitems(all_data):
        vm.set_mem(r_vaddr, data)

    if loc_db is not None:
        fill_loc_db_with_symbols(elf, loc_db, base_addr)

    if apply_reloc:
        arch = guess_arch(elf)
        sections = []
        for section in elf.sh:
            if not hasattr(section, 'reltab'):
                continue
            if isinstance(section, elf_init.RelATable):
                pass
            elif isinstance(section, elf_init.RelTable):
                if arch == "x86_64":
                    log.warning("REL section should not happen in x86_64")
            else:
                raise RuntimeError("Unknown relocation section type: %r" % section)
            sections.append(section)
        for section in sections:
            if arch in ["x86_64", "x86_32"]:
                apply_reloc_x86(elf, vm, section, base_addr, loc_db)
            else:
                log.debug("Unsupported relocation for arch %r" % arch)

    return elf
Esempio n. 5
0
def gen_all_intervals(size):
    """Return every possible interval for element of @size bit
    -> 2**(2**size) (number of partition)
    """
    nb_elements = 1 << size
    for bvec in range(1 << nb_elements):
        # Bit vector: if bit i is on, i is in the interval
        to_ret = interval()
        for i in range(nb_elements):
            if bvec & i == i:
                to_ret += [(i, i)]
        yield to_ret
Esempio n. 6
0
from miasm.core import asmblock
from miasm.arch.x86 import arch
from miasm.core import parse_asm
from miasm.core.interval import interval

my_mn = arch.mn_x86

asmcfg, loc_db = parse_asm.parse_txt(
    my_mn, 64, r'''
main:
  PUSH   RBP
  MOV    RBP, RSP
loop_dec:
  CMP    RCX, RDX
  JB    loop_dec
end:
  MOV    RSP, RBP
  POP    RBP
  RET

''')

loc_db.set_location_offset(loc_db.get_name_location("main"), 0x100001000)
dst_interval = interval([(0x100001000, 0x100002000)])
patches = asmblock.asm_resolve_final(my_mn, asmcfg, loc_db, dst_interval)
Esempio n. 7
0
 def ret_func(self, *args):
     ret = interval()
     for x_min, x_max in self.intervals:
         ret += func(self, x_min, x_max, *args)
     return self.__class__(self.size, ret)
Esempio n. 8
0
 def ret_func(self, target):
     ret = interval()
     for left_i, right_i in product(self.intervals, target.intervals):
         ret += func(self, left_i[0], left_i[1], right_i[0], right_i[1])
     return self.__class__(self.size, ret)
Esempio n. 9
0
        # Second chance, try with symbol
        loc_key = mdis.loc_db.get_name_location(addr)
        offset = mdis.loc_db.get_location_offset(loc_key)
        addrs.append(offset)

if len(addrs) == 0 and default_addr is not None:
    addrs.append(default_addr)
for ad in addrs:
    todo += [(mdis, None, ad)]

done = set()
all_funcs = set()
all_funcs_blocks = {}


done_interval = interval()
finish = False

entry_points = set()
# Main disasm loop
while not finish and todo:
    while not finish and todo:
        mdis, caller, ad = todo.pop(0)
        if ad in done:
            continue
        done.add(ad)
        asmcfg = mdis.dis_multiblock(ad)
        entry_points.add(mdis.loc_db.get_offset_location(ad))

        log.info('func ok %.16x (%d)' % (ad, len(all_funcs)))
Esempio n. 10
0
File: full.py Progetto: w4kfu/miasm
    except ValueError:
        # Second chance, try with symbol
        loc_key = mdis.loc_db.get_name_location(addr)
        offset = mdis.loc_db.get_location_offset(loc_key)
        addrs.append(offset)

if len(addrs) == 0 and default_addr is not None:
    addrs.append(default_addr)
for ad in addrs:
    todo += [(mdis, None, ad)]

done = set()
all_funcs = set()
all_funcs_blocks = {}

done_interval = interval()
finish = False

entry_points = set()
# Main disasm loop
while not finish and todo:
    while not finish and todo:
        mdis, caller, ad = todo.pop(0)
        if ad in done:
            continue
        done.add(ad)
        asmcfg = mdis.dis_multiblock(ad)
        entry_points.add(mdis.loc_db.get_offset_location(ad))

        log.info('func ok %.16x (%d)' % (ad, len(all_funcs)))
Esempio n. 11
0
    def mmap(self, addr, len_, prot, flags, fd, off, vmmngr):
        """Stub for 'mmap' syscall

        'mmap2' must be implemented by calling this function with off * 4096
        """
        if addr == 0:
            addr = self.mmap_current
            self.mmap_current += (len_ + 0x1000) & ~0xfff

        all_mem = vmmngr.get_all_memory()
        mapped = interval(
            [
                (start, start + info["size"] - 1)
                for start, info in viewitems(all_mem)
            ]
        )

        MAP_FIXED = 0x10
        if flags & MAP_FIXED:
            # Alloc missing and override
            missing = interval([(addr, addr + len_ - 1)]) - mapped
            for start, stop in missing:
                vmmngr.add_memory_page(
                    start,
                    PAGE_READ|PAGE_WRITE,
                    b"\x00" * (stop - start + 1),
                    "mmap allocated"
                )
        else:
            # Find first candidate segment nearby addr
            for start, stop in mapped:
                if stop < addr:
                    continue
                rounded = (stop + 1 + 0x1000) & ~0xfff
                if (interval([(rounded, rounded + len_)]) & mapped).empty:
                    addr = rounded
                    break
            else:
                assert (interval([(addr, addr + len_)]) & mapped).empty

            vmmngr.add_memory_page(
                addr,
                PAGE_READ|PAGE_WRITE,
                b"\x00" * len_,
                "mmap allocated"
            )


        if fd == 0xffffffff:
            if off != 0:
                raise RuntimeError("Not implemented")
            data = b"\x00" * len_
        else:
            fdesc = self.file_descriptors[fd]
            cur_pos = fdesc.tell()
            fdesc.seek(off)
            data = fdesc.read(len_)
            fdesc.seek(cur_pos)

        vmmngr.set_mem(addr, data)
        return addr
Esempio n. 12
0
    pe = pe_init.PE(wsize=size)
    s_text = pe.SHList.add_section(name="text", addr=0x1000, rawsize=0x1000)
    s_iat = pe.SHList.add_section(name="iat", rawsize=0x100)
    new_dll = [({
        "name": "USER32.dll",
        "firstthunk": s_iat.addr
    }, ["MessageBoxA"])]
    pe.DirImport.add_dlldesc(new_dll)
    s_myimp = pe.SHList.add_section(name="myimp", rawsize=len(pe.DirImport))
    pe.DirImport.set_rva(s_myimp.addr)
    pe.Opthdr.AddressOfEntryPoint = s_text.addr

    addr_main = pe.rva2virt(s_text.addr)
    virt = pe.virt
    output = pe
    dst_interval = interval([(pe.rva2virt(s_text.addr),
                              pe.rva2virt(s_text.addr + s_text.size))])
else:
    st = StrPatchwork()

    addr_main = 0
    virt = st
    output = st

# Get and parse the source code
with open(args.source) as fstream:
    source = fstream.read()

loc_db = LocationDB()

asmcfg = parse_asm.parse_txt(machine.mn, attrib, source, loc_db)
Esempio n. 13
0
def run(jitter_setup, dse_setup):
  JitCore_Python.SymbExecClass = ESETrackMemory
  # Create sandbox
  parser = Sandbox_Linux_x86_64.parser(description='PE sandboxer')
  parser.add_argument('filename', help='PE Filename')
  parser.add_argument('-if', '--infile', nargs='?', help='Input buffer from file')
  parser.add_argument('-is', '--insize', nargs='?', default='32', help='Input buffer size')
  parser.add_argument('-fs', '--fullsymb', action='store_true', default=False, help='Forbid fallback to concretizing')
  parser.add_argument('-v', '--verbose', nargs='?', default='2', help='Verbosity level (0-4)')
  parser.add_argument('-df', '--dump', action='store_true', default=False, help='Dump crashing data blobs to files')
  options = parser.parse_args()
  # First thing, set log level
  log.setLevel(50-int(options.verbose)*10)
  options.jitter = 'llvm'
  options.mimic_env= True
  #options.singlestep = True
  # Input params
  if options.infile:
    with open(options.infile, 'rb') as f:
      input_buf= f.read()
  else:
    input_buf = os.urandom(int(options.insize, 0))
  # Instantiate
  loc_db = LocationDB()
  sb = Sandbox_Linux_x86_64(loc_db, options.filename, options, globals())
  jitter_setup(sb.jitter, int(options.address, 16), input_buf, len(input_buf))
  # Create and attach DSE
  dse = SecDSE(sb.machine, loc_db)
  dse.add_lib_handler(sb.libs, globals())
  dse.attach(sb.jitter)
  # Record valid memory ranges
  dse.refresh_valid_jitter_ranges()
  dse.update_state_from_concrete()
  # Configure DSE
  dse_setup(dse, input_buf)
  # Take snapshot
  snapshot = dse.take_snapshot()
  nb_run=0
  while dse.todos:
    nb_run+=1
    current = dse.get_todo()
    # Restore concrete & symb contexts
    dse.restore_snapshot(snapshot, keep_known_solutions=True)
    dse.symbolize_memory(current.to_symbolize)
    # Update the buffer in concrete engine
    sb.jitter.vm.set_mem(dse.input_buffer_ptr, current.buf)
    log.error('-'*80 + ' RUN #%i | %i INSTR visited | %i todos | %i crashes' % (nb_run, len(dse.visited_bbls), \
                                                                          len(dse.todos), len(dse.crashes) \
                                                                         )
             )
    log.error('SYMBOLIZED %s (%i/%i bytes)' % (str(current.to_symbolize), current.to_symbolize.length, len(input_buf)))
    try:
      sb.jitter.continue_run()
    except DriftException as e:
      print(hex(dse.jitter.pc) + ' ' + str(e))
      break
    # TODO: Rename to SymbToConcException
    except MemSquareException as e:
      # TODO: We can just concretize the byte and continue from here
      print(hex(dse.jitter.pc) + ' ' + str(e.info))
      dse.done()
      new_to_symbolize = current.to_symbolize
      for mem in e.ptr:
        # Concretize that byte and retry
        new_to_symbolize -= interval([(mem, mem)])
      # Compute all possible concrete bytes
      if options.fullsymb:
        for buf in dse.gen_new_bufs(e.ptr):
          dse.todos.append(todo(buf, current.to_symbolize)) # Put it in the todo list
      else:
        print('CONCRETIZING: ' + hex(mem))
        dse.todos.insert(0, todo(current.buf, new_to_symbolize))
      # Continue the current run?
      #import pdb; pdb.set_trace()
      continue
    except RuntimeError as e:
      message = str(e)
      log.warning(f'LIVE 0x{dse.jitter.pc:08X}: AV with "{message:s}"')
      dse.crashes.append(crash(dse.jitter.pc, None, 'UNDEFINED', current.buf))
      dse.done()
      continue
    except FnReturnException as e:
      log.info('FUNCTION RET')
      dse.done()
      continue
    except KeyboardInterrupt:
      break
    except Exception as e:
      dse.done()
      print(hex(dse.jitter.pc) + ' ' + str(type(e)) + ': ' + str(e))
      import pdb; pdb.set_trace()
      continue
  log.error('-'*80 + ' RESULTS | %i INSTR visited | %i todos | %i unique crashes' % (len(dse.visited_bbls), \
                                                                                   len(dse.todos), len(set(dse.crashes)) \
                                                                           )
           )
  for i, record in enumerate(set(dse.crashes)):
    if options.dump:
      hashval = record.__hash__()
      with open(f'crash_{hashval:X}', 'wb') as f:
        f.write(record.buf)
    log.error(str(record))
  log.error('-'*80)
Esempio n. 14
0
 def clear_jitted_blocks(self):
     "Reset all jitted blocks"
     self.offset_to_jitted_func.clear()
     self.loc_key_to_block.clear()
     self.blocks_mem_interval = interval()
Esempio n. 15
0
    def _process_jmp_table(self, cur_bloc, mn, attrib, loc_db, pool_bin,
                           offsets_to_dis):
        # TODO add support for jump tables with "AND cntrl_var, range" boundary check; such jmp tables were present only
        #   in library functions in Stantinko samples
        # add current block to the asmcfg to make it accessible in the ircfg edges, add_block is called anyway right
        # after this callback, it will notice that the block has been already added
        self.add_block(cur_bloc)
        dst_address = loc_db.get_location_offset(cur_bloc.loc_key)

        logger.info("Possible jump table addr: 0x%x" % dst_address)

        ira = get_ira(mn, attrib)

        ir_arch = ira(loc_db)

        ircfg = ir_arch.new_ircfg_from_asmcfg(self)

        # the previous blocks should have exactly 1 predecessor dictating range
        predecessors = self.predecessors(cur_bloc.loc_key)
        if len(predecessors) != 1:
            logger.info("Expected exactly one predecessor")
            return
        predecessor = ircfg.blocks[predecessors.pop()]

        irdst_block = ircfg.blocks[cur_bloc.loc_key]
        if len(irdst_block.assignblks) != len(cur_bloc.lines):
            processed = set()
            todo = {irdst_block.loc_key}
            while not irdst_block.dst.is_mem():
                loc_key = todo.pop()
                if loc_key in processed:
                    continue
                processed.add(loc_key)
                irdst_block = ircfg.blocks[loc_key]
                todo.update(ircfg.successors(loc_key))

        # we shouldn't stumble upon crashing segm and call operators even thought implicit is required to process
        # initial IRDst(mentioned operators cause crashes of the engine behind implicit) since we operate only on the
        # 2 crucial basic blocks. The predecessor contains range of the jump table, we use it to determine constructs
        # of the jump table and track back base code segment address assignment to target the msvc compiler and x64
        # architecture, other compilers use directly RIP related addressing to get the address.

        # get real predecessor
        asm_block = self.loc_key_to_block(predecessor.loc_key)
        if len(predecessor.assignblks) != len(asm_block.lines):
            processed = set()
            todo = {predecessor.loc_key}
            while cur_bloc.loc_key not in ircfg.successors(
                    predecessor.loc_key):
                loc_key = todo.pop()
                if loc_key in processed:
                    continue
                processed.add(loc_key)
                predecessor = ircfg.blocks[loc_key]
                todo.update(ircfg.successors(loc_key))

        # get jump_table_control_variable from predecessor
        dg = DependencyGraph(ircfg,
                             implicit=True,
                             apply_simp=True,
                             follow_mem=True,
                             follow_call=False)
        jtcdg = JTCVariableDependencyGraph(predecessor.loc_key,
                                           ircfg,
                                           implicit=True,
                                           apply_simp=True,
                                           follow_mem=False,
                                           follow_call=False)

        dependency_result_iter = iter(
            jtcdg.get(irdst_block.loc_key, {ircfg.IRDst},
                      len(predecessor.assignblks), {predecessor.loc_key}))
        solution_predecessor = next(dependency_result_iter)
        # jump table control variable
        jtc_var = jtcdg.jtc_var
        if not jtc_var:
            logger.info(
                "couldn't determine single jump table control variable")
            return
        # get symbolic execution engine to be used in both predecessor and jmp table block
        symb_exec_both = MySymbolicExecutionEngine(pool_bin, jtc_var, ir_arch)
        try:
            # symbolically evaluate lines influencing IRDst of the predecessor leading to jtc_var
            for line_nb in sorted({
                    node.line_nb
                    for node in solution_predecessor.relevant_nodes
                    if node.loc_key == predecessor.loc_key
            }):
                assign_blk = predecessor.assignblks[line_nb]
                symb_exec_both.eval_updt_assignblk(assign_blk)
        except (KeyError, TypeError):
            logger.error("Couldn't symbolically eval predecessor of 0x%x" %
                         loc_db.get_location_offset(cur_bloc.loc_key))
            # stantinko contains illegal unreachable dereferences prior jmp tables, such as
            # xor     eax, eax; movsx   eax, byte ptr [eax]
            return
        # get symbolic execution engine supporting binary memory dereference
        symb_exec_minimal = MySymbolicExecutionEngine(
            pool_bin, ir_arch, symb_exec_both.symbols.copy())
        predecessor_irdst_equation = symb_exec_both.symbols[ircfg.IRDst]

        # get equation whose solutions solve the indirect jump
        irdst_block = ircfg.blocks[cur_bloc.loc_key]
        if len(irdst_block.assignblks) != len(cur_bloc.lines):
            processed = set()
            todo = {irdst_block.loc_key}
            while not irdst_block.dst.is_mem():
                symb_exec_both.eval_updt_irblock(irdst_block)
                loc_key = todo.pop()
                if loc_key in processed:
                    continue
                processed.add(loc_key)
                irdst_block = ircfg.blocks[loc_key]
                todo.update(ircfg.successors(loc_key))

        irdst_equation = symb_exec_both.eval_updt_irblock(irdst_block)
        sizes = set()
        # prevent mem processing via raw arrays by using var ID instead
        # we also want to set a maximum boundary so slices don't cause the sat solver generate a huge number of results
        visitor = ExprVisitorCallbackTopToBottom(
            lambda x: self._eliminate_jtc_var_slice_cb(x, sizes, jtc_var))
        irdst_equation = visitor.visit(irdst_equation)
        predecessor_irdst_equation = visitor.visit(predecessor_irdst_equation)
        size_boundary = jtc_var.size
        sizes = sorted(filter(lambda x: x > 1, sizes))
        if sizes:
            size_boundary = sizes[0]
        jtc_var_id = ExprId("jtc_var", jtc_var.size)
        irdst_equation = irdst_equation.replace_expr({jtc_var: jtc_var_id})
        predecessor_irdst_equation = predecessor_irdst_equation.replace_expr(
            {jtc_var: jtc_var_id})
        # track possible CS base address dependency, ignore control variable from predecessor
        eliminated_jtc_var_equation = irdst_equation.replace_expr(
            {jtc_var_id: ExprInt(0, jtc_var_id.size)})
        evaluated_ejtc_var_equation = symb_exec_both.eval_expr(
            eliminated_jtc_var_equation)
        if not evaluated_ejtc_var_equation.is_int():
            # we need to determine code base
            dependencies = dg._follow_apply_cb(evaluated_ejtc_var_equation)
            expr_deps = {
                fexpr.element
                for fexpr in dependencies if fexpr.follow
            }
            dg_base = DependencyGraph(ircfg,
                                      implicit=False,
                                      apply_simp=True,
                                      follow_mem=True,
                                      follow_call=False)
            dependency_result_iter = iter(
                dg_base.get(cur_bloc.loc_key, expr_deps, len(cur_bloc.lines),
                            {self.heads()[0]}))
            solution = next(dependency_result_iter)
            code_base_dict = {
                expr: solution.emul(ir_arch)[expr]
                for expr in expr_deps
            }
            irdst_equation = irdst_equation.replace_expr(code_base_dict)
            predecessor_irdst_equation = predecessor_irdst_equation.replace_expr(
                code_base_dict)

        # we need backward slice of the jump table destination dependencies to retain the other independent assignments
        # during cmp chain assembling
        dependency_result = dg.get(cur_bloc.loc_key, {ircfg.IRDst},
                                   len(cur_bloc.lines), {cur_bloc.loc_key})
        dependent_line_nbs = {}
        for solution in dependency_result:
            dependent_line_nbs.setdefault(solution.loc_key, set()).update(
                {dn.line_nb
                 for dn in solution.relevant_nodes})
        cur_bloc_new_lines = []
        for loc_key, lines in dependent_line_nbs.items():
            for line_nb, assignblk in enumerate(
                    ircfg.blocks[loc_key].assignblks):
                if line_nb not in lines:
                    symb_exec_minimal.eval_assignblk(assignblk)
                    cur_bloc_new_lines.append(assignblk.instr)
        comparison_reg_id = None
        comparison_reg_value = None
        if jtc_var not in symb_exec_minimal.symbols.symbols_id:
            comparison_reg_id = jtc_var
            comparison_reg_value = jtc_var
        else:
            for symbol, comparison_reg_value in symb_exec_minimal.symbols.symbols_id.items(
            ):
                if jtc_var in comparison_reg_value and (
                        symbol.is_mem() or
                    (symbol.is_id() and symbol.name not in [
                        "RIP", "EIP", "zf", "nf", "pf", "of", "cf", "af", "df",
                        ircfg.IRDst.name
                    ])):
                    replaced_jtcv = comparison_reg_value.replace_expr(
                        {jtc_var: ExprInt(0, jtc_var.size)})
                    if isinstance(symb_exec_minimal.eval_expr(replaced_jtcv),
                                  ExprInt):
                        comparison_reg_id = symbol
                        break
        if not comparison_reg_id or not comparison_reg_value:
            logger.debug(
                "Couldn't find any candidate for comparison register at 0x%x" %
                loc_db.get_location_offset(cur_bloc.loc_key))
            return

        from miasm.ir.translators import Translator
        import z3
        translator = Translator.to_language("z3")
        solver = z3.Solver()

        logger.debug("predecessor_irdst_equation: %s" %
                     str(predecessor_irdst_equation))
        logger.debug(("dst_address: 0x%x" % dst_address))
        logger.debug(("jump_table_control_variable: %s" % str(jtc_var)))
        solver.add(
            translator.from_expr(predecessor_irdst_equation) == dst_address)
        translated_jtc_var = translator.from_expr(jtc_var_id)
        solver.add(translated_jtc_var >= 0)
        solver.add(translated_jtc_var < 2**(size_boundary - 1) - 1)

        if solver.check() != z3.sat:
            logger.debug(
                "Couldn't find at least one jump table control variable")
            return

        dbg_destinations = set()
        next_loc_key = new_block_loc_key = loc_db.add_location()

        logger.debug("comparison_reg_id: %s" % str(comparison_reg_id))
        dst_ranges = {}
        counter = 0
        while counter < 500:
            val = solver.model()[translated_jtc_var].as_long()
            final_irdst_equation = irdst_equation.replace_expr(
                {jtc_var_id: ExprInt(val, jtc_var_id.size)})
            final_dst = int(symb_exec_both.eval_expr(final_irdst_equation))
            cmp_reg_val = comparison_reg_value.replace_expr(
                {jtc_var: ExprInt(val, jtc_var.size)})
            cmp_reg_val = int(symb_exec_minimal.eval_expr(cmp_reg_val))

            dst_ranges[final_dst] = dst_ranges.get(final_dst,
                                                   interval()).union([
                                                       (cmp_reg_val,
                                                        cmp_reg_val)
                                                   ])
            dbg_destinations.add(final_dst)
            offsets_to_dis.add(final_dst)

            solver.add(translated_jtc_var != translator.from_expr(
                ExprInt(val, jtc_var_id.size)))
            if solver.check() != z3.sat:
                break
            counter += 1

        if counter == 500:
            raise RuntimeError("Interrupted; there might be a broken slice")

        for dst, interv in dst_ranges.items():
            cond_target_loc_key = loc_db.get_or_create_offset_location(dst)
            for lower, upper in interv:
                lower = ExprInt(lower, self.mode)
                upper = ExprInt(upper, self.mode)
                new_asm_block = AsmBlock(new_block_loc_key)
                new_block_loc_key = loc_db.add_location()
                if lower == upper:
                    new_asm_block.lines = create_cmp_j_instructions(
                        self.mode, comparison_reg_id, lower,
                        ExprLoc(cond_target_loc_key, self.mode), "JZ")
                    new_asm_block.add_cst(cond_target_loc_key, "c_to")
                    new_asm_block.add_cst(new_block_loc_key, "c_next")
                else:
                    upper_check_loc_key = loc_db.add_location()
                    # lower boundary check
                    new_asm_block.lines = create_cmp_j_instructions(
                        self.mode, comparison_reg_id, lower,
                        ExprLoc(new_block_loc_key, self.mode), "JB")
                    new_asm_block.add_cst(new_block_loc_key, "c_to")
                    new_asm_block.add_cst(upper_check_loc_key, "c_next")
                    # upper boundary check
                    upper_check_block = AsmBlock(upper_check_loc_key)
                    upper_check_block.lines = create_cmp_j_instructions(
                        self.mode, comparison_reg_id, upper,
                        ExprLoc(cond_target_loc_key, self.mode), "JBE")
                    upper_check_block.add_cst(cond_target_loc_key, "c_to")
                    upper_check_block.add_cst(new_block_loc_key, "c_next")
                    self.add_block(upper_check_block)
                self.add_block(new_asm_block)
        # trigger last jump unconditionally
        new_asm_block.bto = {AsmConstraintTo(cond_target_loc_key)}
        new_asm_block.lines = [
            create_jump_instruction(self.mode,
                                    ExprLoc(cond_target_loc_key, self.mode))
        ]

        cur_bloc.lines = cur_bloc_new_lines
        cur_bloc.add_cst(next_loc_key, "c_next")
        if not cur_bloc.lines:
            cur_bloc.lines = [create_nop(self.mode)]
        self.jmp_table_loc_keys.add(cur_bloc.loc_key)
        logger.debug("destinations: %s" %
                     pformat([hex(i or 0) for i in dbg_destinations]))
        logger.debug("blocks: %d" % counter)
Esempio n. 16
0
 def codeRange(self):
     for section in self.parser.sections:
         if '.text' in section.Name.decode():
             return interval([(
                 section.VirtualAddress + self.imageBase,
                 section.VirtualAddress + self.imageBase + section.Misc_VirtualSize)])
Esempio n. 17
0
 def clear_jitted_blocks(self):
     "Reset all jitted blocks"
     self.offset_to_jitted_func.clear()
     self.loc_key_to_block.clear()
     self.blocks_mem_interval = interval()
Esempio n. 18
0
            [
                "MessageBoxA"
            ]
        )
    ]
    pe.DirImport.add_dlldesc(new_dll)
    s_myimp = pe.SHList.add_section(name="myimp", rawsize=len(pe.DirImport))
    pe.DirImport.set_rva(s_myimp.addr)
    pe.Opthdr.AddressOfEntryPoint = s_text.addr

    addr_main = pe.rva2virt(s_text.addr)
    virt = pe.virt
    output = pe
    dst_interval = interval(
        [
            (pe.rva2virt(s_text.addr), pe.rva2virt(s_text.addr + s_text.size))
        ]
    )
else:
    st = StrPatchwork()

    addr_main = 0
    virt = st
    output = st


# Get and parse the source code
with open(args.source) as fstream:
    source = fstream.read()