3

According to Radare2 documentation, this is the command to find paths:

agt [addr]            find paths from current offset to given address

But when I try the command, after running aaaaa analysis, I get the following error:

[0x00430044]> agt 0x0042aa98 > agtoutput.dot
Unable to find source or destination basic block

I can confirm that the two addresses are functions and I can graph each function individually. Also, 0x00430044 does lead to 0x0042aa98. I can see that from the gdb trace. I looked at the radare2 canal.c code and found that it's looking through the RAnalFunction->bbs for the provided addresses. I tried ensuring that bbs was populated with those addressings by running abb $s

abb [length]         analyze N bytes and extract basic blocks 

and feeding the output back into r2. I ran abb $s from various locations to see if it would add the basic blocks to the bbs list. The various locations were 0x0, 0x00430044, and 0x0042aa98. But nothing worked, I always get the "Unable to find source or destination basic block" error message. I could be way off and going down rabbit holes, but the "find paths" feature would be so useful, and I'd really like to get it working? Any help on using the agt feature as documented would be appreciated.

6
  • 1
    Did you try using official support options?
    – Igor Skochinsky
    Sep 3, 2017 at 17:07
  • 1
    When you say official support options, do you mean aaa, instead of aaaaa? I just tried after your comment and I go the same result. Also just rebuilt from the latest radare2 git. I had previously been using a build that was about a month old.
    – Z. Cass
    Sep 3, 2017 at 22:26
  • 1
    What are official support options
    – Z. Cass
    Sep 3, 2017 at 23:18
  • 1
    I get the impression that this feature is not fully implemented. I looked through the code (canal.c) and found a "bug" which would make the agt call never work. I fixed the bug locally, so I got past the initial error, but the "r_core_anal_graph_to" function then basically returns no results. So sad :-(, this would be a great feature. Not sure why this option is in the help menu since it doesn't seem to work at all. Unless, I'm missing something.
    – Z. Cass
    Sep 4, 2017 at 1:17
  • 1
    If you know it's a bug then open an issue in r2 repo or even better if you have the fix then send them a pull-request. I'm assuming you're running r2 from git. Sep 4, 2017 at 5:46

2 Answers 2

3

Seems like the feature is not implemented yet. As you can see in this function:

...
if (root && dest) {
    if (dest == root) {
        eprintf ("Source and destination are the same\n");
        return NULL;
    }
    eprintf ("ROOT BB 0x%08"PFMT64x"\n", root->addr);
    eprintf ("DEST BB 0x%08"PFMT64x"\n", dest->addr);
    list = r_list_new ();
    printf ("=>  0x%08"PFMT64x"\n", root->jump);
} else {
    eprintf ("Unable to find source or destination basic block\n");
}
return list;
...

Feel free to open an issue in the official repository, or better -- to try implementing it by yourself for the good of all of us.

Last thing, don't use aaaaa, it doesn't even exists and any analysis command after aaa is experimental and can cause you with bugs. You don't have to analyze so deeply anyway.

For more information about analysis in radare2 please see this answer.

3

When I realized that this feature was not implement, I made a workaround to get what I want. I output the full program call graph then made a very simple python script that uses networkx to find paths between nodes. This is not ideal but gets the job done.

In radare2, I output the full program call graph to a .dot file:

agC > agCfullProgramCallGraph.dot

Then I have a python script that takes that graph and finds the paths for the connected nodes I'm interested in.

#!/usr/bin/env python
"""
Given a .dot graph, a source node, target node, this script prints out new graphs with all the paths between

"""       
import networkx as nx
from pygraphviz import *
class DotGraphvizUtil(object):

    def find_paths(self, dot_file_path, source, target):
        agraph = AGraph(dot_file_path)
        graphviz_graph = nx.nx_agraph.from_agraph(agraph)

        paths = nx.all_simple_paths(graphviz_graph, source=source, target=target)

        i = 0

        for path in paths:
            subgraph = nx.subgraph(graphviz_graph,path)
            print(path)
            nx.nx_agraph.write_dot(subgraph,"srcTargetGraph{}.dot".format(i))
            i =+ 1

        if i == 0:
            print("No paths found from {} {}".format(source, target))    

if __name__ == '__main__':
    dot_file = "agCfullProgramCallGraph.dot"
    dotGraph = DotGraphvizUtil()
    dotGraph.find_paths(dot_file_path=dot_file, source='0x004669bc', target='0x00466828')

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.