Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Short smali analyser to generate call hierarchy and inspect methods...
import glob
from collections import defaultdict
classes = defaultdict(lambda: defaultdict(list))
class Klass:
def __init__(self, name, project):
self.name = name
self.project = project
self.methods = {}
def get_or_create_method(self, method_name):
if method_name not in self.methods:
self.methods[method_name] = Method(name=method_name, klass=self)
return self.methods[method_name]
class Method:
def __init__(self, name, klass=None):
self.name = name
self.calls = []
self.called_by = []
self.klass = klass
def add_calls(self, method):
self.calls.append(method)
def add_called_by(self, method):
self.called_by.append(method)
def __str__(self):
return """Name: {}
Class: {}
Calls:{}
Called By:{}""".format(self.name, self.klass.name, "\n -".join([" "] + ["{}->{}".format(c.klass.name, c.name) for c in self.calls]),"\n -".join([" "] + ["{}->{}".format(c.klass.name, c.name) for c in self.called_by]))
class Project:
def __init__(self):
self.classes = {}
def get_or_create_class(self, class_name):
if class_name not in self.classes:
self.classes[class_name] = Klass(name=class_name, project=self)
return self.classes[class_name]
def find_method(self, name):
for klass in self.classes.values():
for method in klass.methods.values():
if method.name == name:
print(method)
proj = Project()
for cf in glob.glob("**/*.smali", recursive=True):
with open(cf, 'r') as class_file:
klass = None
method = None
for line in class_file:
line = line.strip()
if line.startswith(".class"):
class_name = line.split()[-1]
klass = proj.get_or_create_class(class_name)
elif line.startswith(".super"):
klass.super = line.split()[-1]
elif line.startswith(".method"):
method_name = line.split()[-1]
method = klass.get_or_create_method(method_name)
elif line.startswith(".end method"):
method_name = None
elif line.startswith("invoke-"):
called_class_name = line.split()[-1].split("->")[0]
called_method_name = line.split()[-1].split("->")[-1]
called_class = proj.get_or_create_class(called_class_name)
called_method = called_class.get_or_create_method(called_method_name)
method.add_calls(called_method)
called_method.add_called_by(method)
proj.find_method("a(Lcom/arxnet/otetvgo/models/mem/node/Vod;ZZ)V")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment