Search in sources :

Example 1 with ICodeContainer

use of com.google.security.zynamics.zylib.disassembly.ICodeContainer 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 2 with ICodeContainer

use of com.google.security.zynamics.zylib.disassembly.ICodeContainer in project binnavi by google.

the class ReilTranslator method insertNativeEdges.

/**
 * Inserts missing edges that could not be deduced automatically from the REIL instructions and
 * their operands.
 *
 * @param nativeEdges List of native edges of the input graph.
 * @param nodes List of translated REIL nodes.
 * @param edges List of translated REIL edges. This list is extended by the function.
 * @param firstMap Maps between native instructions and their first REIL instructions.
 * @param lastMap Maps between native instructions and their last REIL instructions.
 */
private static void insertNativeEdges(final List<? extends ICodeEdge<?>> nativeEdges, final List<ReilBlock> nodes, final List<ReilEdge> edges, final Map<IInstruction, ReilInstruction> firstMap, final Map<IInstruction, ReilInstruction> lastMap) {
    for (final ICodeEdge<?> nativeEdge : nativeEdges) {
        final Object source = nativeEdge.getSource();
        final Object target = nativeEdge.getTarget();
        if ((source instanceof ICodeContainer) && (target instanceof ICodeContainer)) {
            final ICodeContainer<?> sourceCodeNode = (ICodeContainer<?>) source;
            final ICodeContainer<?> targetCodeNode = (ICodeContainer<?>) target;
            final IInstruction sourceInstruction = getLastInstruction(sourceCodeNode);
            final IInstruction targetInstruction = getFirstInstruction(targetCodeNode);
            final ReilInstruction sourceReilInstruction = lastMap.get(sourceInstruction);
            final ReilInstruction targetReilInstruction = firstMap.get(targetInstruction);
            insertNativeEdge(nodes, edges, nativeEdge, sourceReilInstruction, targetReilInstruction);
        }
    }
}
Also used : ReilInstruction(com.google.security.zynamics.reil.ReilInstruction) ICodeContainer(com.google.security.zynamics.zylib.disassembly.ICodeContainer) IInstruction(com.google.security.zynamics.zylib.disassembly.IInstruction)

Aggregations

ReilInstruction (com.google.security.zynamics.reil.ReilInstruction)2 ICodeContainer (com.google.security.zynamics.zylib.disassembly.ICodeContainer)2 IInstruction (com.google.security.zynamics.zylib.disassembly.IInstruction)2 ReilBlock (com.google.security.zynamics.reil.ReilBlock)1 ReilEdge (com.google.security.zynamics.reil.ReilEdge)1 ReilFunction (com.google.security.zynamics.reil.ReilFunction)1 ReilGraph (com.google.security.zynamics.reil.ReilGraph)1 IAddress (com.google.security.zynamics.zylib.disassembly.IAddress)1 ArrayList (java.util.ArrayList)1 HashMap (java.util.HashMap)1 LinkedHashMap (java.util.LinkedHashMap)1 List (java.util.List)1