Search in sources :

Example 56 with ReilInstruction

use of com.google.security.zynamics.reil.ReilInstruction in project binnavi by google.

the class BasicBlockGenerator method addInstruction.

private void addInstruction(final ReilInstruction reilInstruction, final HashSet<IAddress> jumpTargets, final ReilInstruction lastInstruction) {
    if (jumpTargets.contains(reilInstruction.getAddress()) && (currentBlock.size() != 0)) {
        final ReilBlock reilBlock = new ReilBlock(currentBlock);
        // final IAddress blockAddress = reilBlock.getAddress();
        blocks.add(reilBlock);
        // if ((reilBlock.getAddress().toLong() & 0xFFFFFFFFFFFFFF00L) ==
        // (reilInstruction.getAddress().toLong() & 0xFFFFFFFFFFFFFF00L))
        {
            edgepairs.add(new Triple<ReilBlock, IAddress, EdgeType>(reilBlock, reilInstruction.getAddress(), EdgeType.JUMP_UNCONDITIONAL));
        }
        currentBlock = new ArrayList<ReilInstruction>();
    }
    currentBlock.add(reilInstruction);
    if (reilInstruction.getMnemonic().equals(ReilHelpers.OPCODE_JCC) && (ReilHelpers.isDelayedBranch(reilInstruction) || (reilInstruction != lastInstruction))) {
        // Every JCC instruction finishes a block. We skip the last instruction of a block
        // because those edges already exist in the native edge set.
        //
        // Delayed branches also finish a block, at least as far as edge creation goes.
        final ReilBlock reilBlock = new ReilBlock(currentBlock);
        blocks.add(reilBlock);
        currentBlock = new ArrayList<ReilInstruction>();
        final String jumpTarget = reilInstruction.getThirdOperand().getValue();
        if (ReilHelpers.isConditionalJump(reilInstruction)) {
            // If we have a conditional jump we have to add two edges.
            edgepairs.add(new Triple<ReilBlock, IAddress, EdgeType>(reilBlock, null, EdgeType.JUMP_CONDITIONAL_FALSE));
            if (Convert.isDecString(jumpTarget)) {
                edgepairs.add(new Triple<ReilBlock, IAddress, EdgeType>(reilBlock, toReilAddress(jumpTarget), EdgeType.JUMP_CONDITIONAL_TRUE));
            } else if (reilInstruction.getThirdOperand().getType() == OperandType.SUB_ADDRESS) {
                final String[] parts = jumpTarget.split("\\.");
                edgepairs.add(new Triple<ReilBlock, IAddress, EdgeType>(reilBlock, toReilAddress(parts), EdgeType.JUMP_CONDITIONAL_TRUE));
            }
        } else if (ReilHelpers.isFunctionCall(reilInstruction)) {
            edgepairs.add(new Triple<ReilBlock, IAddress, EdgeType>(reilBlock, null, EdgeType.JUMP_UNCONDITIONAL));
        } else if (Convert.isDecString(jumpTarget)) {
            edgepairs.add(new Triple<ReilBlock, IAddress, EdgeType>(reilBlock, toReilAddress(jumpTarget), EdgeType.JUMP_UNCONDITIONAL));
        } else if (reilInstruction.getThirdOperand().getType() == OperandType.SUB_ADDRESS) {
            final String[] parts = jumpTarget.split("\\.");
            edgepairs.add(new Triple<ReilBlock, IAddress, EdgeType>(reilBlock, toReilAddress(parts), EdgeType.JUMP_UNCONDITIONAL));
        }
    }
}
Also used : Triple(com.google.security.zynamics.zylib.general.Triple) ReilInstruction(com.google.security.zynamics.reil.ReilInstruction) ReilBlock(com.google.security.zynamics.reil.ReilBlock) EdgeType(com.google.security.zynamics.zylib.gui.zygraph.edges.EdgeType) IAddress(com.google.security.zynamics.zylib.disassembly.IAddress)

Example 57 with ReilInstruction

use of com.google.security.zynamics.reil.ReilInstruction in project binnavi by google.

the class ReilGraphGenerator method createGraphElements.

/**
   * Creates REIL basic blocks and edges from a list of REIL instructions.
   * 
   * @param instructionList A list of REIL instructions.
   * @param nativeJumpTargets Additional jump targets for the algorithm to consider.
   * 
   * @return A pair containing the blocks and edges created from the REIL instructions.
   */
public static Pair<List<ReilBlock>, List<ReilEdge>> createGraphElements(final Collection<List<ReilInstruction>> instructionList, final Collection<IAddress> nativeJumpTargets) {
    final BasicBlockGenerator generator = new BasicBlockGenerator(instructionList, nativeJumpTargets);
    final List<ReilBlock> blocks = generator.getBlocks();
    final ArrayList<Triple<ReilBlock, IAddress, EdgeType>> edgepairs = generator.getEdges();
    final List<ReilEdge> edges = new ArrayList<ReilEdge>();
    for (final Triple<ReilBlock, IAddress, EdgeType> p : edgepairs) {
        final ReilBlock source = p.first();
        final IAddress target = p.second();
        final EdgeType edgeType = p.third();
        if (target != null) {
            for (final ReilBlock block : blocks) {
                for (final ReilInstruction instruction : block.getInstructions()) {
                    if (target.equals(instruction.getAddress())) {
                        final ReilEdge edge = new ReilEdge(source, block, edgeType);
                        edges.add(edge);
                        ReilBlock.link(source, block, edge);
                    }
                }
            }
        } else {
            // Unknown target address
            final int index = blocks.indexOf(source);
            if (blocks.size() > (index + 1)) {
                final ReilEdge edge = new ReilEdge(source, blocks.get(index + 1), edgeType);
                edges.add(edge);
                ReilBlock.link(source, blocks.get(index + 1), edge);
            }
        }
    }
    return new Pair<List<ReilBlock>, List<ReilEdge>>(blocks, edges);
}
Also used : ReilInstruction(com.google.security.zynamics.reil.ReilInstruction) ReilEdge(com.google.security.zynamics.reil.ReilEdge) ReilBlock(com.google.security.zynamics.reil.ReilBlock) ArrayList(java.util.ArrayList) EdgeType(com.google.security.zynamics.zylib.gui.zygraph.edges.EdgeType) IAddress(com.google.security.zynamics.zylib.disassembly.IAddress) Triple(com.google.security.zynamics.zylib.general.Triple) Pair(com.google.security.zynamics.zylib.general.Pair)

Example 58 with ReilInstruction

use of com.google.security.zynamics.reil.ReilInstruction in project binnavi by google.

the class ReilTranslator method translate.

/**
   * Translates a disassembled function to REIL code.
   * 
   * @param environment The translation environment for the translation process
   * @param function The disassembled function
   * 
   * @return The function translated to REIL code
   * 
   * @throws InternalTranslationException Thrown if an internal error occurs
   */
public ReilFunction translate(final ITranslationEnvironment environment, final IBlockContainer<InstructionType> function, final List<ITranslationExtension<InstructionType>> extensions) throws InternalTranslationException {
    final LinkedHashMap<ICodeContainer<InstructionType>, List<ReilInstruction>> instructionMap = new LinkedHashMap<ICodeContainer<InstructionType>, List<ReilInstruction>>();
    final Map<IInstruction, ReilInstruction> firstMap = new HashMap<IInstruction, ReilInstruction>();
    final Map<IInstruction, ReilInstruction> lastMap = new HashMap<IInstruction, ReilInstruction>();
    final List<List<ReilInstruction>> delayedTrueBranches = new ArrayList<List<ReilInstruction>>();
    for (final ICodeContainer<InstructionType> block : function.getBasicBlocks()) {
        final Iterable<InstructionType> blockInstructions = block.getInstructions();
        final IInstruction lastBlockInstruction = Iterables.getLast(blockInstructions);
        final boolean endsWithInlining = isInlineSource(block);
        final ArrayList<ReilInstruction> instructions = new ArrayList<ReilInstruction>();
        instructionMap.put(block, instructions);
        for (final InstructionType instruction : blockInstructions) {
            environment.nextInstruction();
            final ITranslator<InstructionType> translator = m_translators.get(instruction.getArchitecture().toUpperCase());
            if (translator == null) {
                throw new InternalTranslationException("Could not translate instruction from unknown architecture " + instruction.getArchitecture());
            }
            try {
                final List<ReilInstruction> result = translator.translate(environment, instruction, extensions);
                instructions.addAll(result);
                if (endsWithInlining && (instruction == lastBlockInstruction)) {
                    // We skip the last JCC instruction of blocks that were split by inlining. In 99%
                    // of all cases this should be the inlined call; unless the user removed the
                    // call from the block.
                    final ReilInstruction lastInstruction = instructions.get(instructions.size() - 1);
                    if (lastInstruction.getMnemonic().equals(ReilHelpers.OPCODE_JCC) && lastInstruction.getMetaData().containsKey("isCall")) {
                        instructions.remove(instructions.size() - 1);
                        result.remove(result.size() - 1);
                    }
                }
                firstMap.put(instruction, getFirstInstruction(result));
                lastMap.put(instruction, getLastInstruction(result));
            } catch (final InternalTranslationException exception) {
                exception.setInstruction(instruction);
                throw exception;
            }
        }
        // In this step we have to consider delayed branches of the form
        //
        // BRANCH CONDITION, SOMEWHERE
        // EXECUTE ALWAYS
        //
        // We basically re-order the instructions to
        //
        // EVALUATE CONDITION -> TEMP
        // EXECUTE ALWAYS
        // BRANCH TEMP, SOMEWHERE
        final IInstruction secondLastInstruction = Iterables.size(block.getInstructions()) > 2 ? Iterables.get(block.getInstructions(), Iterables.size(block.getInstructions()) - 2, null) : null;
        if (secondLastInstruction != null) {
            final List<ReilInstruction> secondLastReil = getReilInstructions(secondLastInstruction, instructions);
            if (ReilHelpers.isDelayedBranch(secondLastReil.get(secondLastReil.size() - 1))) {
                final IInstruction lastInstruction = getLastInstruction(block);
                final List<ReilInstruction> lastReil = getReilInstructions(lastInstruction, instructions);
                if (secondLastReil.get(secondLastReil.size() - 1).getMnemonic().equals(ReilHelpers.OPCODE_JCC)) {
                    instructions.removeAll(lastReil);
                    instructions.addAll(instructions.size() - 1, lastReil);
                }
            } else if (ReilHelpers.isDelayedTrueBranch(secondLastReil.get(secondLastReil.size() - 1))) {
                final IInstruction lastInstruction = getLastInstruction(block);
                final List<ReilInstruction> lastReil = getReilInstructions(lastInstruction, instructions);
                delayedTrueBranches.add(lastReil);
            }
        }
    }
    // In this step we determine all jump targets of the input graph.
    // We need them later because not all original jump targets can be
    // found in the translated REIL graph. The reason for this is that
    // source instructions of edges in the input graph do not necessarily
    // have a reference to the address of the edge target. This happens
    // for example when removing the first instruction from a code node.
    // The edge still goes to the code node, but the jump instruction now
    // refers to the removed instruction.
    final Collection<IAddress> nativeJumpTargets = getBlockAddresses(function);
    final Pair<List<ReilBlock>, List<ReilEdge>> pair = ReilGraphGenerator.createGraphElements(instructionMap.values(), nativeJumpTargets);
    final List<ReilBlock> nodes = pair.first();
    final List<ReilEdge> edges = pair.second();
    // In a post-processing step all edges which could not be determined
    // from the REIL instructions alone are inserted into the graph.
    insertNativeEdges(function.getBasicBlockEdges(), nodes, edges, firstMap, lastMap);
    handleDelayedTrueBranches(nodes, edges, delayedTrueBranches);
    return new ReilFunction("REIL - " + function.getName(), new ReilGraph(nodes, edges));
}
Also used : HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) ArrayList(java.util.ArrayList) LinkedHashMap(java.util.LinkedHashMap) IInstruction(com.google.security.zynamics.zylib.disassembly.IInstruction) ICodeContainer(com.google.security.zynamics.zylib.disassembly.ICodeContainer) ArrayList(java.util.ArrayList) List(java.util.List) ReilGraph(com.google.security.zynamics.reil.ReilGraph) ReilInstruction(com.google.security.zynamics.reil.ReilInstruction) ReilEdge(com.google.security.zynamics.reil.ReilEdge) ReilBlock(com.google.security.zynamics.reil.ReilBlock) ReilFunction(com.google.security.zynamics.reil.ReilFunction) IAddress(com.google.security.zynamics.zylib.disassembly.IAddress)

Example 59 with ReilInstruction

use of com.google.security.zynamics.reil.ReilInstruction in project binnavi by google.

the class OperandGraph method createInitialMap.

private static Map<ReilBlock, Pair<List<OperandGraphNode>, List<OperandGraphEdge>>> createInitialMap(final ReilGraph graph) {
    final Map<ReilBlock, Pair<List<OperandGraphNode>, List<OperandGraphEdge>>> graphMap = new HashMap<ReilBlock, Pair<List<OperandGraphNode>, List<OperandGraphEdge>>>();
    for (final ReilBlock block : graph) {
        final List<OperandGraphNode> nodes = new ArrayList<OperandGraphNode>();
        final List<OperandGraphEdge> edges = new ArrayList<OperandGraphEdge>();
        graphMap.put(block, new Pair<List<OperandGraphNode>, List<OperandGraphEdge>>(nodes, edges));
        final Map<String, OperandGraphNode> defines = new HashMap<String, OperandGraphNode>();
        for (final ReilInstruction instruction : block) {
            final Integer mnemonic = instruction.getMnemonicCode();
            OperandGraphNode firstNode = null;
            OperandGraphNode secondNode = null;
            if (ReilHelpers.usesFirstOperand(mnemonic)) {
                firstNode = create(instruction, 0, nodes, edges, defines);
            }
            if (ReilHelpers.usesSecondOperand(mnemonic)) {
                secondNode = create(instruction, 1, nodes, edges, defines);
            }
            if (ReilHelpers.writesThirdOperand(mnemonic)) {
                final OperandGraphNode node = new OperandGraphNode(instruction, 2);
                nodes.add(node);
                defines.put(instruction.getThirdOperand().getValue(), node);
                if (firstNode != null) {
                    final OperandGraphEdge edge = new OperandGraphEdge(firstNode, node);
                    edges.add(edge);
                    OperandGraphNode.link(firstNode, node);
                }
                if (secondNode != null) {
                    final OperandGraphEdge edge = new OperandGraphEdge(secondNode, node);
                    edges.add(edge);
                    OperandGraphNode.link(secondNode, node);
                }
            }
        }
    }
    return graphMap;
}
Also used : ReilInstruction(com.google.security.zynamics.reil.ReilInstruction) HashMap(java.util.HashMap) ReilBlock(com.google.security.zynamics.reil.ReilBlock) ArrayList(java.util.ArrayList) ArrayList(java.util.ArrayList) List(java.util.List) Pair(com.google.security.zynamics.zylib.general.Pair)

Example 60 with ReilInstruction

use of com.google.security.zynamics.reil.ReilInstruction in project binnavi by google.

the class OperandGraph method findDefinition.

private static OperandGraphNode findDefinition(final OperandGraphNode search, final ReilBlock block, final Map<ReilBlock, Pair<List<OperandGraphNode>, List<OperandGraphEdge>>> graphMap, boolean found) {
    final String value = search.getValue();
    final List<ReilInstruction> instructions = Lists.newArrayList(block.getInstructions());
    for (int i = instructions.size() - 1; i >= 0; i--) {
        final ReilInstruction instruction = instructions.get(i);
        if (search.getInstruction() == instruction) {
            found = true;
        }
        if (!found) {
            continue;
        }
        //don't link self-dependency
        if (search.getInstruction() == instruction)
            continue;
        if (ReilHelpers.writesThirdOperand(instruction.getMnemonicCode()) && instruction.getThirdOperand().getValue().equals(value)) {
            final List<OperandGraphNode> nodes = graphMap.get(block).first();
            for (final OperandGraphNode node : nodes) {
                if ((node.getInstruction() == instruction) && (node.getIndex() == 2)) {
                    return node;
                }
            }
        }
    }
    return null;
}
Also used : ReilInstruction(com.google.security.zynamics.reil.ReilInstruction)

Aggregations

ReilInstruction (com.google.security.zynamics.reil.ReilInstruction)144 Test (org.junit.Test)102 TreeSet (java.util.TreeSet)73 ArrayList (java.util.ArrayList)35 IInstruction (com.google.security.zynamics.zylib.disassembly.IInstruction)18 OperandSize (com.google.security.zynamics.reil.OperandSize)16 ReilBlock (com.google.security.zynamics.reil.ReilBlock)16 MockInstruction (com.google.security.zynamics.zylib.disassembly.MockInstruction)16 MockOperandTree (com.google.security.zynamics.zylib.disassembly.MockOperandTree)16 MockOperandTreeNode (com.google.security.zynamics.zylib.disassembly.MockOperandTreeNode)16 ReilEdge (com.google.security.zynamics.reil.ReilEdge)12 HashMap (java.util.HashMap)12 TranslationResult (com.google.security.zynamics.reil.translators.TranslationResult)9 IAddress (com.google.security.zynamics.zylib.disassembly.IAddress)7 List (java.util.List)7 ReilGraph (com.google.security.zynamics.reil.ReilGraph)6 InternalTranslationException (com.google.security.zynamics.reil.translators.InternalTranslationException)6 BigInteger (java.math.BigInteger)6 INaviInstruction (com.google.security.zynamics.binnavi.disassembly.INaviInstruction)5 ValueTrackerElement (com.google.security.zynamics.reil.algorithms.mono.valuetracking.ValueTrackerElement)5