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));
}
}
}
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);
}
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));
}
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;
}
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;
}
Aggregations