Search in sources :

Example 1 with ReilBlock

use of com.google.security.zynamics.reil.ReilBlock 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 2 with ReilBlock

use of com.google.security.zynamics.reil.ReilBlock 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 3 with ReilBlock

use of com.google.security.zynamics.reil.ReilBlock 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 4 with ReilBlock

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

the class ReilTranslator method insertNativeEdge.

/**
   * Inserts a single missing edge that could not be deduced automatically from the REIL
   * instructions and their operands.
   * 
   * @param nodes List of translated REIL nodes.
   * @param edges List of translated REIL edges. This list is extended by the function.
   * @param nativeEdge The native to check for and add if necessary.
   * @param sourceReilInstruction Source REIL instruction of the edge.
   * @param targetReilInstruction Target REIL instruction of the edge.
   */
private static void insertNativeEdge(final List<ReilBlock> nodes, final List<ReilEdge> edges, final ICodeEdge<?> nativeEdge, final ReilInstruction sourceReilInstruction, final ReilInstruction targetReilInstruction) {
    for (final ReilBlock node : nodes) {
        if ((sourceReilInstruction == getLastInstruction(node)) && !hasEdge(nodes, node, targetReilInstruction)) {
            final EdgeType edgeType = ReilHelpers.isJump(sourceReilInstruction) ? nativeEdge.getType() : EdgeType.JUMP_UNCONDITIONAL;
            final ReilBlock targetNode = getNode(targetReilInstruction, nodes);
            final ReilEdge newEdge = new ReilEdge(node, targetNode, edgeType);
            ReilBlock.link(node, targetNode, newEdge);
            edges.add(newEdge);
        }
    }
}
Also used : ReilEdge(com.google.security.zynamics.reil.ReilEdge) ReilBlock(com.google.security.zynamics.reil.ReilBlock) EdgeType(com.google.security.zynamics.zylib.gui.zygraph.edges.EdgeType)

Example 5 with ReilBlock

use of com.google.security.zynamics.reil.ReilBlock 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)

Aggregations

ReilBlock (com.google.security.zynamics.reil.ReilBlock)23 ReilEdge (com.google.security.zynamics.reil.ReilEdge)16 ReilInstruction (com.google.security.zynamics.reil.ReilInstruction)16 ArrayList (java.util.ArrayList)12 ReilGraph (com.google.security.zynamics.reil.ReilGraph)10 Test (org.junit.Test)8 HashMap (java.util.HashMap)5 INaviInstruction (com.google.security.zynamics.binnavi.disassembly.INaviInstruction)4 EdgeType (com.google.security.zynamics.zylib.gui.zygraph.edges.EdgeType)4 HashSet (java.util.HashSet)4 ReilFunction (com.google.security.zynamics.reil.ReilFunction)3 InstructionGraph (com.google.security.zynamics.reil.algorithms.mono.InstructionGraph)3 OperandGraph (com.google.security.zynamics.reil.algorithms.mono.OperandGraph)3 IAddress (com.google.security.zynamics.zylib.disassembly.IAddress)3 Pair (com.google.security.zynamics.zylib.general.Pair)3 List (java.util.List)3 InstructionGraphNode (com.google.security.zynamics.reil.algorithms.mono.InstructionGraphNode)2 ValueTrackerElement (com.google.security.zynamics.reil.algorithms.mono.valuetracking.ValueTrackerElement)2 Triple (com.google.security.zynamics.zylib.general.Triple)2 CCodeNode (com.google.security.zynamics.binnavi.disassembly.CCodeNode)1