Пример #1
0
class neo4ida_t(idaapi.plugin_t):
    flags = 0
    comment = "Neo4j graph export and query interface"
    help = "Neo4j graph export and query interface"
    wanted_name = "Neo4IDA"
    wanted_hotkey = ""

    def init(self):
        self.conf_file = os.path.expanduser("~") + os.path.sep + "neo4ida.json"
        config = self.get_config()
        if not config:
            config = self.create_default_config()
        self.connect()
        action = UiAction(id="neo4ida:upload",
                          name="Upload",
                          tooltip="Upload to neo4j",
                          menuPath="Edit/neo4ida/",
                          callback=self.upload,
                          icon="")
        if not action.registerAction():
            return 1
        action = UiAction(id="neo4ida:dropdb",
                          name="Drop Database",
                          tooltip="Delete all entries in database instance.",
                          menuPath="Edit/neo4ida/",
                          callback=self.drop_db,
                          icon="")
        if not action.registerAction():
            return 1
        action = UiAction(id="neo4ida:config",
                          name="Configure",
                          tooltip="Configure neo4j connection details.",
                          menuPath="Edit/neo4ida/",
                          callback=self.config_form,
                          icon="")
        if not action.registerAction():
            return 1
        action = UiAction(id="neo4ida:query",
                          name="Cypher Query",
                          tooltip="Execute a Cypher query.",
                          menuPath="Edit/neo4ida/",
                          callback=self.query_form,
                          icon="")
        if not action.registerAction():
            return 1
        action = UiAction(id="neo4ida:browser",
                          name="Neo4j Browser",
                          tooltip="Open Neo4j browser.",
                          menuPath="Edit/neo4ida/",
                          callback=self.open_browser,
                          icon="")
        if not action.registerAction():
            return 1
        action = UiAction(id="neo4ida:diff",
                          name="Binary Diff",
                          tooltip="Open binary diffing interface.",
                          menuPath="Edit/neo4ida/",
                          callback=self.binary_diff,
                          icon="")
        if not action.registerAction():
            return 1
        return idaapi.PLUGIN_KEEP

    def connect(self):
        conf = self.get_config()
        authenticate(conf['host'] + ":" + conf['port'], conf['username'],
                     conf["password"])
        try:
            self.neo = Graph("http://" + conf['host'] + ":" + conf["port"] +
                             "/db/data")
        except:
            print "Failed to connect!"

    def term(self):
        return None

    def binary_diff(self, ctf):
        print "Open binary diffing interface"

    def drop_db(self, ctx):
        self.neo.cypher.execute("START n=node(*) detach delete n;")
        print "All database nodes and relationships deleted."

    def open_browser(self, ctx):
        self.neo.open_browser()

    def config_form(self, ctx):
        ConnectionManagementForm(self)

    def query_form(self, ctf):
        CypherQueryForm(self)

    def upload(self, ctx):
        start = time.time()
        func_count = 0
        bb_count = 0
        call_count = 0
        target = idaapi.get_root_filename()
        hash = idc.GetInputMD5()
        tx = self.neo.cypher.begin()
        insert_binary = "MERGE (n:Binary {name:{N},hash:{H}}) RETURN n"
        insert_func = "MERGE (n:Function {name:{N},start:{S},flags:{F}}) RETURN n"
        insert_bb = "MERGE (n:BasicBlock {start:{S}, end:{E}}) RETURN n"
        create_relationship = "MATCH (u:Function {name:{N}}), (r:Function {start:{S}}) CREATE (u)-[:CALLS]->(r)"
        create_contains = "MATCH (u:BasicBlock {start:{S}}), (f:Function {name:{N}}) CREATE (f)-[:CONTAINS]->(u)"
        create_inside = "MATCH (u:Function {start:{S}}), (b:Binary {hash:{H}}) CREATE (f)-[:INSIDE]->(b)"
        self.neo.cypher.execute(insert_binary, {"N": target, "H": hash})
        self.neo.cypher.execute("CREATE INDEX ON :Function(start)")
        #self.neo.cypher.execute("CREATE INDEX ON :Function(name)")
        self.neo.cypher.execute("CREATE INDEX ON :BasicBlock(start)")
        for f in Functions():
            tx.append(create_inside, {"S": f, "H": hash})
            callee_name = GetFunctionName(f)
            flags = get_flags(f)
            type = GetType(f)
            if type:
                return_type = type.split()[0]
                print type
                end_return = type.find(' ')
                start_args = type.find('(')
                print type[end_return + 1:start_args]
                print type[start_args + 1:].split(',')
            else:
                print GuessType(f)
            tx.append(insert_func, {"N": callee_name, "S": f, "F": flags})
            func_count += 1
            fc = idaapi.FlowChart(idaapi.get_func(f))
            for block in fc:
                tx.append(insert_bb, {"S": block.startEA, "E": block.endEA})
                tx.append(create_contains, {"S": block.startEA, "N": f})
                bb_count += 1
        tx.process()
        tx.commit()
        tx = self.neo.cypher.begin()
        for f in Functions():
            for xref in CodeRefsTo(f, 0):
                caller_name = GetFunctionName(xref)
                if caller_name != '':
                    tx.append(create_relationship, {"N": caller_name, "S": f})
                    call_count += 1
        tx.process()
        tx.commit()
        print "Upload ran in: " + str(time.time() - start)
        print "Uploaded " + str(func_count) + " functions, " + str(
            call_count) + " function calls and " + str(
                bb_count) + " basic blocks."

    def run(self):
        pass

    def update_config(self, new_config):
        print "updating config to be: "
        print json.dumps(new_config)
        os.remove(self.conf_file)
        with open(self.conf_file, "w+") as f:
            f.write(json.dumps(new_config))

    def create_default_config(self):
        default_conf = {
            "host": "localhost",
            "port": "7474",
            "username": "******",
            "password": "******"
        }
        with open(self.conf_file, "w+") as f:
            f.write(json.dumps(default_conf))
        return default_conf

    def get_config(self):
        try:
            with open(self.conf_file, "r") as f:
                return json.loads(f.read())
        except:
            return None

    def find_path(self, startFunc, endFunc):
        all_paths = ""
        print "Finding all paths from " + startFunc + " to " + endFunc
        self.neo.cypher.execute(all_paths, {})
Пример #2
0
def show_graph():
    graph = Graph(password=pw)
    graph.run('MATCH (n:Android) return n')
    graph.open_browser()
Пример #3
0
class neo4ida_t(idaapi.plugin_t):
	flags = 0
	comment = "Neo4j graph export and query interface"
	help = "Neo4j graph export and query interface"
	wanted_name = "Neo4IDA"
	wanted_hotkey = ""

	def init(self):
		self.conf_file = os.path.expanduser("~") + os.path.sep + "neo4ida.json"
		config = self.get_config()
		if not config:
			config = self.create_default_config()
		self.connect()
		action = UiAction(
			id="neo4ida:upload",
			name="Upload",
			tooltip="Upload to neo4j",
			menuPath="Edit/neo4ida/",
			callback=self.upload,
			icon=""
		)
		if not action.registerAction():
			return 1
		action = UiAction(
			id="neo4ida:dropdb",
			name="Drop Database",
			tooltip="Delete all entries in database instance.",
			menuPath="Edit/neo4ida/",
			callback=self.drop_db,
			icon=""
		)
		if not action.registerAction():
			return 1
		action = UiAction(
			id="neo4ida:config",
			name="Configure",
			tooltip="Configure neo4j connection details.",
			menuPath="Edit/neo4ida/",
			callback=self.config_form,
			icon=""
		)
		if not action.registerAction():
			return 1
		action = UiAction(
			id="neo4ida:query",
			name="Cypher Query",
			tooltip="Execute a Cypher query.",
			menuPath="Edit/neo4ida/",
			callback=self.query_form,
			icon=""
		)
		if not action.registerAction():
			return 1
		action = UiAction(
			id="neo4ida:browser",
			name="Neo4j Browser",
			tooltip="Open Neo4j browser.",
			menuPath="Edit/neo4ida/",
			callback=self.open_browser,
			icon=""
		)
		if not action.registerAction():
			return 1
		action = UiAction(
			id="neo4ida:diff",
			name="Binary Diff",
			tooltip="Open binary diffing interface.",
			menuPath="Edit/neo4ida/",
			callback=self.binary_diff,
			icon=""
		)
		if not action.registerAction():
			return 1
		return idaapi.PLUGIN_KEEP

		
	def connect(self):
		conf = self.get_config()
		authenticate(conf['host'] + ":" + conf['port'],conf['username'],conf["password"])
		try:
			self.neo = Graph("http://" + conf['host'] + ":" + conf["port"] + "/db/data")
		except:
			print "Failed to connect!"
	
	def term(self):
		return None

	def binary_diff(self,ctf):
		print "Open binary diffing interface"

	def drop_db(self,ctx):
		self.neo.cypher.execute("START n=node(*) detach delete n;")
		print "All database nodes and relationships deleted."
	
	def open_browser(self,ctx):
		self.neo.open_browser()
	
	def config_form(self,ctx):
		ConnectionManagementForm(self)
	
	def query_form(self,ctf):
		CypherQueryForm(self)
	
	def upload(self,ctx):
		start = time.time()
		func_count = 0
		bb_count = 0
		call_count = 0
		target = idaapi.get_root_filename()
		hash = idc.GetInputMD5()
		tx = self.neo.cypher.begin()
		insert_binary = "MERGE (n:Binary {name:{N},hash:{H}}) RETURN n"
		insert_func = "MERGE (n:Function {name:{N},start:{S},flags:{F}}) RETURN n"
		insert_bb = "MERGE (n:BasicBlock {start:{S}, end:{E}}) RETURN n"
		create_relationship = "MATCH (u:Function {name:{N}}), (r:Function {start:{S}}) CREATE (u)-[:CALLS]->(r)"
		create_contains = "MATCH (u:BasicBlock {start:{S}}), (f:Function {name:{N}}) CREATE (f)-[:CONTAINS]->(u)"
		create_inside = "MATCH (u:Function {start:{S}}), (b:Binary {hash:{H}}) CREATE (f)-[:INSIDE]->(b)"
		self.neo.cypher.execute(insert_binary, {"N":target, "H":hash})
		self.neo.cypher.execute("CREATE INDEX ON :Function(start)")
		#self.neo.cypher.execute("CREATE INDEX ON :Function(name)")
		self.neo.cypher.execute("CREATE INDEX ON :BasicBlock(start)")
		for f in Functions():
			tx.append(create_inside, {"S":f, "H":hash})
			callee_name = GetFunctionName(f)
			flags = get_flags(f)
			type = GetType(f)
			if type:
				return_type = type.split()[0]
				print type
				end_return = type.find(' ')
				start_args = type.find('(')
				print type[end_return +1:start_args]
				print type[start_args+1:].split(',')
			else:
				print GuessType(f)
			tx.append(insert_func, {"N": callee_name, "S":f, "F":flags})
			func_count += 1
			fc = idaapi.FlowChart(idaapi.get_func(f))
			for block in fc:
				tx.append(insert_bb, {"S":block.startEA,"E":block.endEA})
				tx.append(create_contains,{"S":block.startEA,"N":f})
				bb_count += 1
		tx.process()
		tx.commit()
		tx = self.neo.cypher.begin()
		for f in Functions():
			for xref in CodeRefsTo(f,0):
				caller_name = GetFunctionName(xref)
				if caller_name != '':
					tx.append(create_relationship,{"N":caller_name,"S":f})
					call_count += 1
		tx.process()
		tx.commit()
		print "Upload ran in: " + str(time.time() - start)
		print "Uploaded " + str(func_count) + " functions, " + str(call_count) +" function calls and " + str(bb_count) + " basic blocks."
	
	def run(self):
		pass
	
	def update_config(self,new_config):
		print "updating config to be: "
		print json.dumps(new_config)
		os.remove(self.conf_file)
		with open(self.conf_file,"w+") as f:
			f.write(json.dumps(new_config))
	
	def create_default_config(self):
		default_conf = {
			"host": "localhost",
			"port": "7474",
			"username":"******",
			"password":"******"
		}
		with open(self.conf_file,"w+") as f:
			f.write(json.dumps(default_conf))
		return default_conf
	
	def get_config(self):
		try:
			with open(self.conf_file,"r") as f:
				return json.loads(f.read())
		except:
			return None

	def find_path(self,startFunc, endFunc):
		all_paths = ""
		print "Finding all paths from " + startFunc + " to " + endFunc
		self.neo.cypher.execute(all_paths,{})