forked from june5079/soFrida
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdexparse.py
More file actions
111 lines (105 loc) · 4.16 KB
/
Copy pathdexparse.py
File metadata and controls
111 lines (105 loc) · 4.16 KB
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
import os
import xml.etree.ElementTree as ET
import struct
import dex.dexparser as dexparser
import json
import subprocess
import re
import sys
import tempfile
import traceback
from zipfile import ZipFile
class DexParse:
def __init__(self, apk_path):
self.apk_path = apk_path
self.tmp_dir = tempfile.TemporaryDirectory()
self.unzip()
self.dex_parse()
def unzip(self):
isdex = re.compile("classes([0-9]*).dex")
with ZipFile(self.apk_path) as apk:
for f in apk.namelist():
if isdex.match(f) != None:
apk.extract(f, path=self.tmp_dir.name)
def pretty(self, tt):
JNI = {"Z":"boolean", "B":"byte","C":"char","D":"double","F":"float","I":"int","J":"long","V":"void", "S":"short"}
if tt[0] == "L":
return tt[1:-1].replace("/",".")
elif tt[0] == "[":
return tt.replace("/",".")
else:
if tt in JNI:
return JNI[tt]
else:
if tt[:2] == "\x01L":
return tt[2:-1].replace("/",".")
def dex_parse(self):
c_list = dict()
for dex_file in os.listdir(self.tmp_dir.name):
print(self.tmp_dir.name+"/"+dex_file)
d = dexparser.Dexparser(self.tmp_dir.name+"/"+dex_file)
s_list = d.string_list()
t_list = d.typeid_list()
m = d.mmapdata()
p_list = d.protoids_list()
n_p_list = []
for shorty_idx, return_type_idx, parameters_off in p_list:
if parameters_off == 0:
param_size = 0
else:
param_size = struct.unpack("<L", m[parameters_off:parameters_off+4])[0]
params = []
for i in range(param_size):
param_type_id = struct.unpack("<H", m[parameters_off+4+i*2:parameters_off+4+i*2+2])[0]
params.append(s_list[t_list[param_type_id]])
n_p_list.append([s_list[t_list[return_type_idx]], params])
m_list = d.method_list()
for class_idx, proto_idx, name_idx in m_list:
cls = self.pretty(str(s_list[t_list[class_idx]],"utf-8"))
try:
method = str(s_list[name_idx],"utf-8")
if method != "clone" and method != "<clinit>":
if method == "<init>":
method = "$init"
proto = n_p_list[proto_idx]
ret = self.pretty(str(proto[0], "utf-8"))
params = []
for param in proto[1]:
params.append(self.pretty(str(param, "utf-8")))
proto = [ret, params]
if cls in c_list:
if method in c_list[cls]:
c_list[cls][method].append(proto)
else:
c_list[cls][method] = [proto]
else:
c_list[cls] = {method:[proto]}
except UnicodeDecodeError:
traceback.print_exc()
pass
except Exception:
traceback.print_exc()
break
self.names = c_list
def get_classes(self):
return self.names.keys()
def get_methods(self, class_name):
if class_name in self.names:
return self.names[class_name].keys()
return None
def get_overloads(self, class_name, method_name):
if class_name in self.names:
if method_name in self.names[class_name]:
return self.names[class_name][method_name]
return None
if __name__ == "__main__":
dp = DexParse("../apk/com.happylabs.hps.apk")
#dp.dex_parse()
for cls, methods in dp.dex_parse().items():
#print(cls)
for method, over in methods.items():
#print(method)
for proto in over:
ret = proto[0]
params = proto[1]
#print(ret+" ["+", ".join(params)+"]")