Skip to content

Instantly share code, notes, and snippets.

@JosephRedfern
Created April 11, 2018 17:06
Show Gist options
  • Save JosephRedfern/0a83e6081331e92f069df87aef8b47dc to your computer and use it in GitHub Desktop.
Save JosephRedfern/0a83e6081331e92f069df87aef8b47dc to your computer and use it in GitHub Desktop.
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