Exetools  

Go Back   Exetools > General > General Discussion

Notices

Reply
 
Thread Tools Display Modes
  #1  
Old 09-23-2020, 06:40
chants chants is offline
VIP
 
Join Date: Jul 2016
Posts: 576
Rept. Given: 7
Rept. Rcvd 35 Times in 21 Posts
Thanks Given: 501
Thanks Rcvd at 847 Times in 396 Posts
chants Reputation: 35
Using IDA Pro to generate Control Flow Graphs

Does anyone know a simple method to take IDA Pro to generate Control Flow Graphs (CFG) for each function in a very basic numbered edge format e.g. to graphviz or simply a list of successor nodes. The edges should be ordered by their occurrence or scanning/memory order. In other words, something like:
Code:
1 -> 2;
2 -> 3;
2 -> 4;
3 -> 5;
4 ->5;
Or even without the edges properly ordered as just a vertex successor list:
Code:
[2], [3, 4], [5], [5]
I know I could write a plugin to do this but it seems like such a basic task to generate CFGs that it would be nice not to reinvent the wheel if this is already possible.
Reply With Quote
  #2  
Old 09-23-2020, 10:22
TQN TQN is offline
VIP
 
Join Date: Apr 2003
Location: Vietnam
Posts: 282
Rept. Given: 122
Rept. Rcvd 10 Times in 8 Posts
Thanks Given: 50
Thanks Rcvd at 22 Times in 10 Posts
TQN Reputation: 10
You can see the code of Diaphora or FireEye SimplifyGraph.
Reply With Quote
The Following User Says Thank You to TQN For This Useful Post:
chants (09-23-2020)
  #3  
Old 09-23-2020, 13:03
chants chants is offline
VIP
 
Join Date: Jul 2016
Posts: 576
Rept. Given: 7
Rept. Rcvd 35 Times in 21 Posts
Thanks Given: 501
Thanks Rcvd at 847 Times in 396 Posts
chants Reputation: 35
Yes perfect just what I was looking for. Am realizing I need a "legitimate" IDA Freeware 7.0 way to do this also . So for that there are no plugins, no IDAPython but the IDC scripting language should be enough to generate GDL files if enumerating all the functions and saving the files separately as can be done by the GUI. Also a method in IDC to save the call graph. The function CFGs and call graph and then GDL can be converted to a more basic format with a simple Python script or any number of graph tools. Otherwise I would need to buy a license. Although after doing that proof of legitimacy my preferred route is still to use the plugin you linked
Reply With Quote
  #4  
Old 09-24-2020, 00:31
chants chants is offline
VIP
 
Join Date: Jul 2016
Posts: 576
Rept. Given: 7
Rept. Rcvd 35 Times in 21 Posts
Thanks Given: 501
Thanks Rcvd at 847 Times in 396 Posts
chants Reputation: 35
Anyone interested in doing this with IDA Free 7.0, I wrote the IDC script to do the job - will generate GDLs which are an easy to manipulate text graph format. Even many IDC commands are missing but fortunately I came up with a reasonable solution here:

Code:
static get_path_name(filepath)
{
	auto i = strlen(filepath) - 1;
	while (i != 0 && filepath[i] != "\\" && filepath[i] != "/") {
		i--;
	}
	return i == 0 ? filepath : filepath[:i];
}
static remove_bad_chars(name)
{
	auto filtered = "";
	auto i = strlen(name);
	auto c = 0;
	while (c < i) {
		if (strstr("/<>:\"\\|?*", name[c]) == -1) {
			filtered = filtered + name[c];
		}
		c++;
	}
	return filtered;
}
static gen_graphs()
{
	auto p = get_path_name(get_idb_path());
	auto r = get_root_filename();
	//CHART_GEN_GDL = 0x4000
	//FUNCATTR_END = 8
	call_system("mkdir \"" + p + "/" + r + "\"");
	gen_simple_call_chart(p + "/" + r + "/" + "calls", "", 0x4000);
	auto a;
	a = get_next_func(0);
	while (a != -1) {
		gen_flow_graph(p + "/" + r + "/func_" + remove_bad_chars(get_func_name(a)), "", a, get_func_attr(get_next_func(a), 8), 0x4000);
		a = get_next_func(a);
	}
}
Parsing it in Python is pretty easy using some regex tricks:
Code:
  def get_real_cfgs():
    import glob
    import os
    import re
    libNames = ["kernel32.dll"]
    allEdges = []
    for libName in libNames:
      for filePath in glob.glob(os.getenv("USERPROFILE") + "/Documents/" + libName + "/*.gdl"):
        edges = []
        with open(filePath) as fp:
          line = fp.readline()
          while line:
            match = re.search("^edge: { sourcename: \"(\w+)\" targetname: \"(\w+)\" label: \"\w+\" color: \w+ }\n$", line)
            if match is None: match = match = re.search("^edge: { sourcename: \"(\w+)\" targetname: \"(\w+)\" }\n$", line)
            if not match is None:
              edges.append((int(match[1]), int(match[2])))
            line = fp.readline()
        if len(edges) != 0: allEdges.append(edges)
    return allEdges

Last edited by chants; 09-24-2020 at 01:15.
Reply With Quote
The Following 3 Users Say Thank You to chants For This Useful Post:
niculaita (09-24-2020), SinaDiR (10-01-2020), TQN (11-14-2020)
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



All times are GMT +8. The time now is 16:45.


Always Your Best Friend: Aaron, JMI, ahmadmansoor, ZeNiX
( 1998 - 2020 )