-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathr2DAD.py
executable file
·188 lines (145 loc) · 6.35 KB
/
r2DAD.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
from androguard import misc, session
from androguard.decompiler import decompiler
from androguard.core.bytecodes import dvm
from androguard.core.analysis.analysis import Analysis
from pathlib import Path
import r2pipe
import sys
import argparse
import os
# Save and open session to/from Radare2 project directory
def r2ProjectName(projectName, sessionName, fileName, sess):
project = Path(os.environ['HOME'] + "/.local/share/radare2/projects/" + projectName)
sessionFile = str(project) +"/" + sessionName
sessionFile = Path(sessionFile)
if project.is_dir():
print("Project exists! -- " + str(project) + "\n")
if sessionFile.is_file():
print("Loading session file at " + str(sessionFile) + ", please wait... \n")
sess = session.Load(str(sessionFile))
return sess
else:
print("No session file found, creating one! Please wait...")
apk, d, dx = misc.AnalyzeAPK(fileName.decode('utf-8'), session=sess)
session.Save(sess, str(sessionFile))
print("Session file created at : " + str(sessionFile) + "\n")
return sess
else:
print("Radare2 Project does not exist, please save a Radare2 project first")
exit()
# Decompile user provded class
def decompileClass(className, sess):
print("Class name is: " + className)
print("Decompiling whole class...")
className = className.replace("_", "/")
dalv = next(sess.get_objects_dex())[1]
dx = next(sess.get_objects_dex())[2]
dad = decompiler.DecompilerDAD(dalv, dx)
classes = dalv.get_classes()
for c in classes:
if className in str(c):
dad.display_all(c)
# Decompile user provided method
def decompileMethod(className, methodName, sess):
print("Decompiling whole method...")
className = className.replace("_", "/")
dalv = next(sess.get_objects_dex())[1]
dx = next(sess.get_objects_dex())[2]
dad = decompiler.DecompilerDAD(dalv, dx)
classes = dalv.get_classes_names()
for c in classes:
if className in c:
for m in dalv.get_methods_class(c):
if methodName in str(m):
dad.display_source(m)
# Try to detect current method and class
def autoDecompile(dalv,dx,dad,classNames,currentClass, apkMethod):
apkMethod = apkMethod + "("
for c in classNames:
if currentClass in c:
for m in dalv.get_methods_class(c):
if apkMethod in str(m):
dad.display_source(m)
def main(projectName, className, methodName):
if methodName and (not className):
print('Must provide class name "-c" in order to decompile specific method "-m"')
exit()
#Increase recursion limit to save session file
sys.setrecursionlimit(100000)
r2 = r2pipe.open()
fileName = r2.cmd("i~file[1]")
fileName = fileName.split("/")[2]
if fileName.split("."):
sessionName = fileName.split(".")[0]
sessionName = sessionName+".session"
sessionFile = Path(sessionName)
currentClassMethod = r2.cmd("afi.")
if "_" in currentClassMethod:
currentClassMethod = str(currentClassMethod).replace("_", "/")
currentClass = str(currentClassMethod).split(".")[1]
print("Current class: " + currentClass)
currentMethod = str(currentClassMethod).split(".")[3]
apkMethod = currentMethod.split("/")[0]
if apkMethod == "method":
currentMethod = str(currentClassMethod).split(".")[4]
apkMethod = currentMethod.split("(")[0]
print(" Current Method: " + apkMethod + "\n")
sess = misc.get_default_session()
#Check if project name is passed
if projectName != None:
projectSession = r2ProjectName(projectName, sessionName, fileName, sess)
if className and methodName:
decompileMethod(className, methodName, projectSession)
exit()
if className:
decompileClass(className, projectSession)
exit()
dalv = next(projectSession.get_objects_dex())[1]
dx = next(projectSession.get_objects_dex())[2]
print("Decompiling method " + apkMethod + " in the class" + currentClass)
dad = decompiler.DecompilerDAD(dalv, dx)
classNames = dalv.get_classes_names()
autoDecompile(dalv, dx, dad, classNames, currentClass, apkMethod)
exit()
# Check if session file exists
if sessionFile.is_file():
print("Loading session file, please wait... \n")
sess = session.Load(sessionName)
if className and methodName:
decompileMethod(className, methodName, sess)
exit()
if className:
decompileClass(className, sess)
exit()
dalv = next(sess.get_objects_dex())[1]
dx = next(sess.get_objects_dex())[2]
dad = decompiler.DecompilerDAD(dalv, dx)
classNames = dalv.get_classes_names()
autoDecompile(dalv,dx,dad,classNames, currentClass, apkMethod)
# Create sesssion file
else:
print("No session file found, creating one! Please wait...")
fileName = fileName.replace("\\n\\x00","")
fileName = fileName.split("\'")[0]
apk, d, dx = misc.AnalyzeAPK(fileName, session=sess)
session.Save(sess, sessionName)
print("Session file created: " + sessionName)
print(" Will load session file for future calls... \n")
if className and methodName:
decompileMethod(className, methodName, sess)
exit()
if className:
decompileClass(className, sess)
exit()
dalv = next(sess.get_objects_dex())[1]
dx = next(sess.get_objects_dex())[2]
dad = decompiler.DecompilerDAD(dalv, dx)
classNames = dalv.get_classes_names()
autoDecompile(dalv,dx,dad,classNames,currentClass, apkMethod)
if __name__ == '__main__':
parser = argparse.ArgumentParser(description="r2DAD Decompiler")
parser.add_argument('-p', dest="project_name", help="Save session with Radare2 Project (Project must already exist!)")
parser.add_argument('-c', dest="class_name", help="Decompile specific class")
parser.add_argument('-m', dest="method_name", help="Decompile specific method (must be used with -c)")
args = parser.parse_args()
main(args.project_name, args.class_name, args.method_name)