Esempio n. 1
0
 def findDep(self, item):
     arg = item.args[self.lastClickIndex]
     address = item.address + item.instr.l
     func = item.func
     if func.ircfg is None:
         func.ira = BinaryAnalysis.iraType(func.cfg.loc_db)
         func.ircfg = func.ira.new_ircfg_from_asmcfg(func.cfg)
         func.defUse = DiGraphDefUse(ReachingDefinitions(func.ircfg))
     indexReg = eval('BinaryAnalysis.machine.mn.regs.regs' + str(arg.size).zfill(2) + '_expr').index(arg)
     arg = eval('BinaryAnalysis.machine.mn.regs.regs' + str(BinaryAnalysis.disasmEngine.attrib).zfill(2) + '_expr')[
         indexReg]
     elements = set()
     elements.add(arg)
     depgraph = DependencyGraph(func.ircfg, implicit=False, apply_simp=True, follow_call=False, follow_mem=True)
     currentLockey = next(iter(func.ircfg.getby_offset(address)))
     assignblkIndex = 0
     currentBlock = func.ircfg.get_block(currentLockey)
     for assignblkIndex, assignblk in enumerate(currentBlock):
         if assignblk.instr.offset == address:
             break
     outputLog = ''
     for solNum, sol in enumerate(depgraph.get(currentBlock.loc_key, elements, assignblkIndex, set())):
         results = sol.emul(func.ira, ctx={})
         outputLog += 'Solution %d:\n' % solNum
         for k, v in viewitems(results):
             outputLog += str(k) + ' = ' + str(v) + '\n'
         path = ' -> '.join(BinaryAnalysis.locDB.pretty_str(h) for h in sol.history[::-1])
         outputLog += path + '\n\n'
     self.log.emit(outputLog)
Esempio n. 2
0
def get_funcs_arg0(ctx, ira, ircfg, lbl_head):
    """Compute DependencyGraph on the func @lbl_head"""
    g_dep = DependencyGraph(ircfg, follow_call=False)
    element = ira.arch.regs.RSI

    for loc_key, index in find_call(ircfg):
        irb = ircfg.get_block(loc_key)
        instr = irb[index].instr
        print('Analysing references from:', hex(instr.offset), instr)
        g_list = g_dep.get(irb.loc_key, set([element]), index, set([lbl_head]))
        for dep in g_list:
            emul_result = dep.emul(ira, ctx)
            value = emul_result[element]
            yield value
Esempio n. 3
0
def get_funcs_arg0(ctx, ira, ircfg, lbl_head):
    """Compute DependencyGraph on the func @lbl_head"""
    g_dep = DependencyGraph(ircfg, follow_call=False)
    element = ira.arch.regs.RSI

    for loc_key, index in find_call(ircfg):
        irb = ircfg.get_block(loc_key)
        instr = irb[index].instr
        print('Analysing references from:', hex(instr.offset), instr)
        g_list = g_dep.get(irb.loc_key, set([element]), index, set([lbl_head]))
        for dep in g_list:
            emul_result = dep.emul(ira, ctx)
            value = emul_result[element]
            yield value
Esempio n. 4
0
    def _insert_flat_block(self, source_flat_block, symb_exec,
                           flat_block_to_loc_key):
        """
        Copies source_flat_block and sets its successors according to flat_block_to_loc_key
        :param flat_block_to_loc_key: dictionary mapping flat_blocks to respective loc_keys
        :param symb_exec: instance of current symbolic execution engine
        :param source_flat_block: flat_block to be inserted
        :return: dictionary mapping old successor loc_keys to the new ones
        """
        # we're not using redirect_successors after copying to avoid executing the same loops multiple times
        source_block = self.asmcfg.loc_key_to_block(
            source_flat_block.block_loc_key)
        tobe_processed = {}
        new_flat_blocks = set()
        new_block_loc_key = flat_block_to_loc_key[source_flat_block]
        if self.out_asmcfg.loc_key_to_block(new_block_loc_key) is not None:
            raise Exception("Target loc_key is already associated to a block")
        new_block = AsmBlock(new_block_loc_key)

        # copy instructions
        for ln in source_block.lines:
            tmp_ln = instruction_x86(ln.name, ln.mode,
                                     [i.copy() for i in ln.args],
                                     ln.additional_info)
            tmp_ln.b = ln.b
            tmp_ln.l = ln.l
            tmp_ln.offset = ln.offset
            new_block.addline(tmp_ln)

        constraints = source_block.bto
        # try to simplify the destination if it's a primary flattening block
        if not self.flat_loops[source_block.loc_key].is_default:
            logger.debug("current block is a part of primary loc_keys")
            simplified_target = symb_exec.eval_expr(self.ircfg.IRDst)
            if isinstance(simplified_target, ExprInt):
                simplified_target = self.asmcfg.loc_db.get_offset_location(
                    int(simplified_target))
            elif isinstance(simplified_target, ExprLoc):
                simplified_target = simplified_target.loc_key
            else:
                # there's probably a(n) (series of) unknown instruction(s) causing an implicit conditional assignment
                # such as CMOV or SBB->AND->ADD, prepend comparison + cond jump if it happens to be common, or add it to
                # ExtendedAsmCFG.extended_discovery and split flow on the final instruction

                # it's also possible that it's not related to any cff loop at all
                addr = self.asmcfg.loc_db.get_location_offset(
                    source_flat_block.block_loc_key)
                addr = hex(addr) if addr else addr
                logger.warning(
                    "Couldn't simplify loc_key %s at %s, continuing" %
                    (str(source_flat_block.block_loc_key), addr))
                logger.warning("the simplified target is %s of instance %s" %
                               (simplified_target, type(simplified_target)))
                simplified_target = None
            if simplified_target:
                constraints = {AsmConstraintTo(simplified_target)}
                mode = self.asmcfg.mode

                # remove redundant comparison
                dp = DependencyGraph(self.ircfg, True)
                block_loc_key = source_block.loc_key
                res = next(
                    dp.get(block_loc_key, {self.ircfg.IRDst}, None,
                           {block_loc_key}))
                for depnode in res.relevant_nodes:
                    ind = depnode.line_nb
                    ind -= (len(self.ircfg.blocks[block_loc_key]) -
                            len(new_block.lines))
                    if new_block.lines[ind].name == "CMP":
                        new_block.lines.pop(ind)

                new_block.lines[-1] = create_jump_instruction(
                    mode, ExprLoc(simplified_target, mode))

        # copy constraints
        new_bto = set()
        for constraint in constraints:
            if not self.asmcfg.loc_key_to_block(constraint.loc_key):
                logger.debug("Skipping bad constraint %s" % constraint.loc_key)
                continue
            flat_block = self.flat_loops.get_block(constraint.loc_key,
                                                   symb_exec,
                                                   source_flat_block)
            if flat_block not in flat_block_to_loc_key:
                new_flat_blocks.add(flat_block)
                new_loc_key = self.out_asmcfg.loc_db.add_location()
                tobe_processed[constraint.loc_key] = (new_loc_key, flat_block)
                flat_block_to_loc_key[flat_block] = new_loc_key
            else:
                new_loc_key = flat_block_to_loc_key[flat_block]
            new_bto.add(AsmConstraint(new_loc_key, constraint.c_t))
        new_block.bto = new_bto
        new_block.alignment = source_block.alignment

        # change jmp targets
        if new_block.lines:
            for ind, arg in enumerate(list(new_block.lines[-1].args)):
                if isinstance(arg, ExprLoc):
                    if not self.asmcfg.loc_key_to_block(arg.loc_key):
                        logger.debug("Skipping bad constraint %s" %
                                     arg.loc_key)
                        continue
                    new_target, flat_block = tobe_processed.get(
                        arg.loc_key, (None, None))
                    if not new_target:
                        flat_block = self.flat_loops.get_block(
                            arg.loc_key, symb_exec, source_flat_block)
                        new_target = flat_block_to_loc_key.get(flat_block)
                    # None in case of irrelevant calls
                    logger.debug("new target: %s" % new_target)
                    if new_target:
                        new_block.lines[-1].args[ind] = ExprLoc(
                            new_target, arg.size)

        self.out_asmcfg.add_block(new_block)
        return new_flat_blocks
Esempio n. 5
0
        # StdCall example
        for i in range(4):
            e_mem = ExprMem(
                ExprId("ESP_init", 32) + ExprInt(4 * (i + 1), 32), 32)
            init_ctx[e_mem] = ExprId("arg%d" % i, 32)

# Disassemble the targeted function
asmcfg = mdis.dis_multiblock(int(args.func_addr, 0))

# Generate IR
ircfg = ir_arch.new_ircfg_from_asmcfg(asmcfg)

# Get the instance
dg = DependencyGraph(ircfg,
                     implicit=args.implicit,
                     apply_simp=not args.do_not_simplify,
                     follow_mem=not args.unfollow_mem,
                     follow_call=not args.unfollow_call)

# Build information
target_addr = int(args.target_addr, 0)
current_loc_key = next(iter(ircfg.getby_offset(target_addr)))
assignblk_index = 0
current_block = ircfg.get_block(current_loc_key)
for assignblk_index, assignblk in enumerate(current_block):
    if assignblk.instr.offset == target_addr:
        break

# Enumerate solutions
json_solutions = []
for sol_nb, sol in enumerate(
Esempio n. 6
0
                                (G16_IRA, G16_INPUT),
                                (G17_IRA, G17_INPUT),
                                ]):

    # Extract test elements
    print("[+] Test", test_nb + 1)
    ircfg, (depnodes, heads) = test

    open("graph_%02d.dot" % (test_nb + 1), "w").write(ircfg.dot())
    open("graph_%02d.dot" % (test_nb + 1), "w").write(bloc2graph(ircfg))

    # Different options
    suffix_key_list = ["", "_nosimp", "_nomem", "_nocall",
                       "_implicit"]
    # Test classes
    for g_ind, g_dep in enumerate([DependencyGraph(ircfg),
                                   DependencyGraph(ircfg, apply_simp=False),
                                   DependencyGraph(ircfg, follow_mem=False),
                                   DependencyGraph(
                                       ircfg, follow_mem=False,
                                       follow_call=False
                                   ),
                                   # DependencyGraph(ircfg, implicit=True),
                                   ]):
        # if g_ind == 4:
        # TODO: Implicit specifications
        #    continue
        print(" - Class %s - %s" % (g_dep.__class__.__name__,
                                    suffix_key_list[g_ind]))
        # Select the correct result key
        mode_suffix = suffix_key_list[g_ind]
Esempio n. 7
0
    if arch == "x86_32":
        # StdCall example
        for i in range(4):
            e_mem = ExprMem(ExprId("ESP_init", 32) + ExprInt(4 * (i + 1), 32), 32)
            init_ctx[e_mem] = ExprId("arg%d" % i, 32)

# Disassemble the targeted function
asmcfg = mdis.dis_multiblock(int(args.func_addr, 0))

# Generate IR
ircfg = ir_arch.new_ircfg_from_asmcfg(asmcfg)

# Get the instance
dg = DependencyGraph(
    ircfg, implicit=args.implicit,
    apply_simp=not args.do_not_simplify,
    follow_mem=not args.unfollow_mem,
    follow_call=not args.unfollow_call
)

# Build information
target_addr = int(args.target_addr, 0)
current_loc_key = next(iter(ircfg.getby_offset(target_addr)))
assignblk_index = 0
current_block = ircfg.get_block(current_loc_key)
for assignblk_index, assignblk in enumerate(current_block):
    if assignblk.instr.offset == target_addr:
        break

# Enumerate solutions
json_solutions = []
for sol_nb, sol in enumerate(dg.get(current_block.loc_key, elements, assignblk_index, set())):
Esempio n. 8
0
    def _mark_branch_conditions(self, ctx=None):
        """
        For any cjmp in CFG tries to find all solutions for []IP symbol
        :return:
        """
        ir_loc: LocKey
        ir_block: IRBlock

        for ir_loc, ir_block in self._ir_cfg.blocks.items():
            # check for detect current location that is head or tail of natural loop

            loc_addr = self._ir_cfg.loc_db.get_location_offset(ir_loc)

            is_head, _ = self._is_loop_head(ir_loc)
            is_tail, _ = self._is_loop_tail(ir_loc)

            if not ir_block.dst.is_cond() or is_head or is_tail:
                continue

            dg = DependencyGraph(self._ir_cfg)

            dst_solutions = set()

            solutions_log = []

            for sol in dg.get(ir_loc, [self.ip],
                              ir_block.assignblks[-1].instr.offset, set()):
                try:
                    solutions = sol.emul(self._ir_arch, ctx=ctx)
                except NotImplementedError as ex:
                    log(f"Unsupported expression in location - {ir_loc}",
                        code='!')

                    solutions_log.append((ir_loc, ir_block, None))

                    dst_solutions = set()
                    break

                ip_expr = solutions.get(self.ip)

                solutions_log.append((ir_loc, ir_block, ip_expr))

                if not ip_expr.is_int() and not ip_expr.is_loc(
                ) and not is_static_expr(ip_expr):
                    dst_solutions = set()

                    known_dst = self._flow_patches_map.get(loc_addr, None)
                    if known_dst:
                        del self._flow_patches_map[loc_addr]

                    break

                if not ip_expr.is_int() and not ip_expr.is_loc():
                    log(f"Static ip expressions unsupported now [{ip_expr}]")

                    # invlidate dst_solutions
                    dst_solutions = set()

                    known_dst = self._flow_patches_map.get(loc_addr, None)
                    if known_dst:
                        del self._flow_patches_map[loc_addr]

                    break

                dst_solutions.update([ip_expr])

            if self._verbose_log:
                vl_pad = 24
                for ir_loc, ir_block, ip_expr in solutions_log:
                    print(f"{'-' * vl_pad}")
                    print(f"{ir_loc} - {hex(loc_addr)if loc_addr else 'None'}")
                    for assign_block in ir_block.assignblks:
                        for dst, src in assign_block.iteritems():
                            print(f"{dst} = {src}")
                    print(f"{'-' * vl_pad}")
                    print(f"Solution: {ip_expr}")

            if len(dst_solutions) != 1:
                continue

            static_dst = dst_solutions.pop()
            static_addr = simple_unwrap_expr(static_dst, self._ir_cfg.loc_db)

            if static_addr == -1:
                log(f"Oops ... {static_dst}. Fail resolve dst by a simple approach",
                    code='!')
                continue

            known_dst = self._flow_patches_map.get(loc_addr, None)
            if known_dst is None:
                self._flow_patches_map[loc_addr] = static_addr
            elif self._flow_patches_map[loc_addr] != static_addr:
                # We found in another path different static solution, not opaque jmp
                del self._flow_patches_map[loc_addr]

        if self._verbose_log:
            for l, d in self._flow_patches_map.items():
                print(f"{hex(l)} -> {hex(d)}")
Esempio n. 9
0
 def depgraph(self):
     value = self.cMethod.value
     return DependencyGraph(self.ircfg,
                            implicit=value & 4,
                            follow_mem=value & 1,
                            follow_call=value & 2)