View Single Post
  #4  
Old 09-24-2020, 00:31
chants chants is offline
VIP
 
Join Date: Jul 2016
Posts: 738
Rept. Given: 37
Rept. Rcvd 48 Times in 30 Posts
Thanks Given: 671
Thanks Rcvd at 1,064 Times in 482 Posts
chants Reputation: 48
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)