Search in sources :

Example 1 with BasicBlock

use of com.google.security.zynamics.binnavi.API.disassembly.BasicBlock in project binnavi by google.

the class PathFinder method createPath.

/**
 * Creates a view that shows all possible paths between two blocks of a module.
 *
 * @param module The module for which the view is created.
 * @param startBlock The basic block where the path begins (must be null if startFunction is not
 *        null).
 * @param targetBlock The basic block where the path ends (must be null if targetFunction is not
 *        null).
 * @param startFunction The function where the path starts (must be null if startBlock is not
 *        null).
 * @param targetFunction The function where the path ends (must be null if targetBlock is not
 *        null).
 *
 * @return The view that contains all possible paths between the start block and the target block.
 *
 * @throws CouldntLoadDataException
 * @throws PartialLoadException
 * @throws IllegalArgumentException
 */
public static View createPath(final Module module, final BasicBlock startBlock, final BasicBlock targetBlock, final Function startFunction, final Function targetFunction) throws CouldntLoadDataException, PartialLoadException {
    Preconditions.checkNotNull(module, "Error: Module argument can't be null");
    Preconditions.checkArgument(module.isLoaded(), "Error: Module is not loaded");
    if ((startBlock == null) && (startFunction == null)) {
        throw new IllegalArgumentException("Error: No valid start given");
    }
    if ((targetBlock == null) && (targetFunction == null)) {
        throw new IllegalArgumentException("Error: No valid target given");
    }
    if ((startFunction != null) && !startFunction.isLoaded()) {
        throw new IllegalArgumentException("Error: Start function is not loaded");
    }
    if ((targetFunction != null) && !targetFunction.isLoaded()) {
        throw new IllegalArgumentException("Error: Target function is not loaded");
    }
    // The algorithm works like this:
    // 
    // 1. Find all functions that lie between the start function and the target function.
    // 2. Insert all of these functions into the new view.
    // 3. Connect the individual functions at function calls and split code nodes if necessary.
    // 4. Determine what nodes are actually on the path by taking the successors of the start
    // node and set-unioning those with the predecessors of the target node.
    // 5. Delete all the nodes which are not on the path.
    // At first we determine the function where the path starts and the function where the path
    // ends.
    final Function realStartFunction = startFunction != null ? startFunction : startBlock.getParentFunction();
    final Function realTargetFunction = targetFunction != null ? targetFunction : targetBlock.getParentFunction();
    if (realStartFunction.getGraph().nodeCount() == 0) {
        throw new IllegalArgumentException("Error: Functions with zero nodes can not be used for pathfinding");
    }
    // Determine the real start and end blocks of the path with the help of the function flow graphs
    final BasicBlock realStartBlock = startBlock != null ? startBlock : findEntryNode(realStartFunction);
    final BasicBlock realTargetBlock = targetBlock != null ? targetBlock : findEntryNode(realTargetFunction);
    // Find out what functions are called on the way between the first block and the second block.
    final LinkedHashSet<FunctionBlock> passedFunctions = findPassedFunctions(module.getCallgraph(), realStartFunction, realTargetFunction);
    // Create the view that represents the calculated path
    final String endAddress = realTargetBlock != null ? realTargetBlock.getAddress().toHexString() : realTargetFunction.getAddress().toHexString();
    final View view = module.createView("New Pathfinder View", String.format("%s -> %s", realStartBlock.getAddress().toHexString(), endAddress));
    view.load();
    // Maps basic blocks of functions to their corresponding node in the new view.
    final Map<BasicBlock, ViewNode> nodeMap = new HashMap<BasicBlock, ViewNode>();
    // Keeps track of the entry nodes for each function,
    final Map<Function, ViewNode> entryNodes = new HashMap<Function, ViewNode>();
    // Keeps track of the exit nodes for each function,
    final ArrayListMultimap<Function, ViewNode> exitNodes = ArrayListMultimap.create();
    // Keeps track of the function a view node belongs to.
    // TODO (timkornau): This should actually be accessible from the plug in API.
    final Map<ViewNode, Function> functionMap = new HashMap<ViewNode, Function>();
    // Create a code node for all basic blocks of the passed functions.
    createInitialBlocks(view, passedFunctions, nodeMap, functionMap);
    // Create view edges for all edges in the passed functions.
    createInitialEdges(view, passedFunctions, nodeMap);
    // Find the entry and exit nodes for all passed functions.
    findEntryExitNodes(passedFunctions, nodeMap, functionMap, entryNodes, exitNodes);
    ViewNode startNode = nodeMap.get(realStartBlock);
    ViewNode targetNode = realTargetBlock == null ? entryNodes.get(realTargetFunction) : nodeMap.get(realTargetBlock);
    startNode.setColor(Color.GREEN);
    targetNode.setColor(Color.YELLOW);
    // Connect the nodes of the different functions on function calls.
    final NodePair splitResult = connectFunctions(view, startNode, targetNode, passedFunctions, entryNodes, exitNodes, functionMap);
    startNode = splitResult.getFirst();
    targetNode = splitResult.getSecond();
    // all paths end here.
    for (final ViewEdge edge : targetNode.getOutgoingEdges()) {
        view.deleteEdge(edge);
    }
    // Delete all nodes that are not on the path.
    deleteNodesNotOnPath(view, startNode, targetNode);
    if (startNode.getOutgoingEdges().isEmpty()) {
        // no path exists between the two nodes
        return null;
    }
    try {
        view.save();
    } catch (final CouldntSaveDataException exception) {
        CUtilityFunctions.logException(exception);
    }
    return view;
}
Also used : HashMap(java.util.HashMap) CouldntSaveDataException(com.google.security.zynamics.binnavi.API.disassembly.CouldntSaveDataException) BasicBlock(com.google.security.zynamics.binnavi.API.disassembly.BasicBlock) View(com.google.security.zynamics.binnavi.API.disassembly.View) Function(com.google.security.zynamics.binnavi.API.disassembly.Function) ViewEdge(com.google.security.zynamics.binnavi.API.disassembly.ViewEdge) ViewNode(com.google.security.zynamics.binnavi.API.disassembly.ViewNode) FunctionBlock(com.google.security.zynamics.binnavi.API.disassembly.FunctionBlock)

Example 2 with BasicBlock

use of com.google.security.zynamics.binnavi.API.disassembly.BasicBlock in project binnavi by google.

the class PathfinderPlugin method showPathfindingDialog.

/**
 * Shows the pathfinding dialog that is used to select the start block and the end block of the
 * pathfinding operation.
 *
 * @param module The target module of the pathfinding operation.
 * @throws CouldntLoadDataException Thrown if one of the functions couldn't be loaded.
 */
private void showPathfindingDialog(final Module module) throws CouldntLoadDataException {
    Preconditions.checkArgument(module.isLoaded(), "Internal Error: Target module is not loaded");
    final PathfindingDialog dlg = new PathfindingDialog(pluginInterface.getMainWindow().getFrame(), module);
    GuiHelper.centerChildToParent(pluginInterface.getMainWindow().getFrame(), dlg, true);
    dlg.setVisible(true);
    if (dlg.wasCancelled()) {
        return;
    }
    final BasicBlock sourceBlock = dlg.getStartBlock();
    final BasicBlock targetBlock = dlg.getEndBlock();
    final Function firstFunction = dlg.getStartFunction();
    final Function secondFunction = dlg.getEndFunction();
    // for every time when a user has not selected a function but a basic block this breaks.
    // As it does throw a null pointer exception.
    firstFunction.load();
    secondFunction.load();
    final CreationThread creationThread = new CreationThread(module, sourceBlock, targetBlock, firstFunction, secondFunction);
    ProgressDialog.show(pluginInterface.getMainWindow().getFrame(), "Creating path ...", creationThread);
    if ((!(creationThread.threwException())) && (creationThread.getCreatedView() == null)) {
        MessageBox.showInformation(pluginInterface.getMainWindow().getFrame(), "There is no path between the two selected blocks");
    } else {
        new Thread() {

            @Override
            public void run() {
                PluginInterface.instance().showInNewWindow(creationThread.getCreatedView());
            }
        }.start();
    }
}
Also used : Function(com.google.security.zynamics.binnavi.API.disassembly.Function) BasicBlock(com.google.security.zynamics.binnavi.API.disassembly.BasicBlock) IProgressThread(com.google.security.zynamics.binnavi.API.helpers.IProgressThread)

Example 3 with BasicBlock

use of com.google.security.zynamics.binnavi.API.disassembly.BasicBlock in project binnavi by google.

the class InstructionFinders method findInstruction.

/**
 * Searches for an instruction in a function.
 *
 * @param function The function to search through.
 * @param searchInstruction The instruction to search for.
 *
 * @return The API instruction object that wraps the search instruction.
 */
public static Instruction findInstruction(final Function function, final IInstruction searchInstruction) {
    Preconditions.checkNotNull(function, "IE02034: Function argument can not be null");
    Preconditions.checkNotNull(searchInstruction, "IE02052: Instruction argument can not be null");
    for (final BasicBlock block : function.getGraph().getNodes()) {
        for (final Instruction instruction : block.getInstructions()) {
            if (instruction.getNative() == searchInstruction) {
                return instruction;
            }
        }
    }
    throw new IllegalStateException("IE01274: Could not determine what instruction could not be translated");
}
Also used : BasicBlock(com.google.security.zynamics.binnavi.API.disassembly.BasicBlock) Instruction(com.google.security.zynamics.binnavi.API.disassembly.Instruction) IInstruction(com.google.security.zynamics.zylib.disassembly.IInstruction)

Example 4 with BasicBlock

use of com.google.security.zynamics.binnavi.API.disassembly.BasicBlock in project binnavi by google.

the class PathFinderTest method testRegularFunction.

@Test
public void testRegularFunction() throws CouldntLoadDataException, PartialLoadException {
    // Tests pathfinding between two simple functions
    // 0x1004565
    // 0x1003CD7
    final Function startFunction = findFunction(m_notepad, 0x1004565);
    final BasicBlock startBlock = findBlock(startFunction, 0x1004629);
    final Function endFunction = findFunction(m_notepad, 0x1003C92);
    final BasicBlock endBlock = findBlock(endFunction, 0x1003CD7);
    final View view = PathFinder.createPath(m_notepad, startBlock, endBlock, null, null);
    assertEquals(7, view.getGraph().nodeCount());
    assertEquals(8, view.getGraph().edgeCount());
}
Also used : Function(com.google.security.zynamics.binnavi.API.disassembly.Function) BasicBlock(com.google.security.zynamics.binnavi.API.disassembly.BasicBlock) View(com.google.security.zynamics.binnavi.API.disassembly.View) Test(org.junit.Test)

Example 5 with BasicBlock

use of com.google.security.zynamics.binnavi.API.disassembly.BasicBlock in project binnavi by google.

the class PathFinderTest method testInsideFunctionPartial.

@Test
public void testInsideFunctionPartial() throws CouldntLoadDataException, PartialLoadException {
    // Tests path finding somewhere inside a function
    final Function startFunction = findFunction(m_notepad, 0x01002452);
    final BasicBlock startBlock = findBlock(startFunction, 0x10024C2);
    final BasicBlock endBlock = findBlock(startFunction, 0x10026FB);
    final View view = PathFinder.createPath(m_notepad, startBlock, endBlock, null, null);
    assertEquals(9, view.getGraph().nodeCount());
    assertEquals(11, view.getGraph().edgeCount());
    final List<ViewEdge> edges = view.getGraph().getEdges();
    final List<ViewNode> nodes = view.getGraph().getNodes();
    assertEquals(EdgeType.JumpConditionalFalse, findEdge(edges, 0x10024C2, 0x1002523).getType());
    assertEquals(EdgeType.JumpConditionalTrue, findEdge(edges, 0x10024C2, 0x1002539).getType());
    assertEquals(EdgeType.JumpUnconditional, findEdge(edges, 0x100253F, 0x10026F9).getType());
    assertEquals(Color.GREEN, findNode(nodes, 0x10024C2).getColor());
    assertEquals(Color.YELLOW, findNode(nodes, 0x10026FB).getColor());
}
Also used : Function(com.google.security.zynamics.binnavi.API.disassembly.Function) BasicBlock(com.google.security.zynamics.binnavi.API.disassembly.BasicBlock) ViewEdge(com.google.security.zynamics.binnavi.API.disassembly.ViewEdge) ViewNode(com.google.security.zynamics.binnavi.API.disassembly.ViewNode) View(com.google.security.zynamics.binnavi.API.disassembly.View) Test(org.junit.Test)

Aggregations

BasicBlock (com.google.security.zynamics.binnavi.API.disassembly.BasicBlock)14 Function (com.google.security.zynamics.binnavi.API.disassembly.Function)13 View (com.google.security.zynamics.binnavi.API.disassembly.View)10 Test (org.junit.Test)9 FunctionBlock (com.google.security.zynamics.binnavi.API.disassembly.FunctionBlock)3 ViewNode (com.google.security.zynamics.binnavi.API.disassembly.ViewNode)3 ViewEdge (com.google.security.zynamics.binnavi.API.disassembly.ViewEdge)2 HashMap (java.util.HashMap)2 CodeNode (com.google.security.zynamics.binnavi.API.disassembly.CodeNode)1 CouldntSaveDataException (com.google.security.zynamics.binnavi.API.disassembly.CouldntSaveDataException)1 FunctionNode (com.google.security.zynamics.binnavi.API.disassembly.FunctionNode)1 Instruction (com.google.security.zynamics.binnavi.API.disassembly.Instruction)1 IProgressThread (com.google.security.zynamics.binnavi.API.helpers.IProgressThread)1 IInstruction (com.google.security.zynamics.zylib.disassembly.IInstruction)1 Map (java.util.Map)1