-
Notifications
You must be signed in to change notification settings - Fork 2
/
instruction_generator.py
111 lines (90 loc) · 3.46 KB
/
instruction_generator.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
import os
import os.path as osp
import multiprocessing as mp
manager = mp.Manager
ClassDictionary = manager().dict()
class Method(object):
def __init__(self):
self.name = ''
self.ClassName = ''
self.instructions = []
def add_instruction(self, raw_strig: str):
self.instructions.append(raw_strig.strip())
class SmaliClass(object):
def __init__(self):
self.name = ''
self.methods = []
self.api_names = []
def add_method(self, method: Method):
self.methods.append(method)
def add_api_name(self, api_name: str):
self.api_names.append(api_name)
def FunctionGenerator(SmaliFile):
MethodFlag = False
for line in open(SmaliFile, 'r').readlines():
if line.startswith('.class'):
ClassName = line.strip().split(' ')[-1][1:-1]
if ClassName in ClassDictionary:
ClassDictionary[ClassName] += 1
break
else:
ClassDictionary[ClassName] = 1
if line.startswith('.method'):
MethodFlag = True
method = Method()
method.name = line.split(' ')[-1][:-1]
method.ClassName = ClassName
continue
if line.startswith('.end method'):
MethodFlag = False
yield method
if MethodFlag and len(line.strip()) > 0 and not line.strip().startswith('.'):
method.add_instruction(line)
def SmaliInstructionGenerator(SmaliRootDir, flag='method'):
'''
SmaliRootDir: is the disassembled directory from dex files in an APK.
flag: can only be 'method' or 'class' indicating the generator to yield method or class.
'''
assert flag in {'method', 'class'}
SmaliFileList = []
for root, _, files in os.walk(SmaliRootDir, topdown=False):
SmaliFileList = SmaliFileList + [osp.join(root, x) for x in files if x.endswith('.smali')]
for SmaliFile in SmaliFileList:
if flag == 'class':
Class = SmaliClass()
for method in FunctionGenerator(SmaliFile):
if flag == 'method':
yield method
else:
Class.add_method(method)
if flag == 'class' and len(Class.methods):
Class.name = Class.methods[0].ClassName
yield Class
if __name__ == "__main__":
from numpy.core.fromnumeric import mean
import numpy as np
k1_3_cnt = 0
num_list = []
method_num_list = []
root_dir = './dataset/debug/raw_smalis'
app_list = os.listdir(root_dir)
for app_hash in app_list:
clas_cnt = 0
for cls in SmaliInstructionGenerator(osp.join(root_dir, app_hash), 'class'):
clas_cnt += 1
method_num_list.append(len(cls.methods))
num_list.append(clas_cnt)
if clas_cnt <= 2000 and clas_cnt >= 1000:
k1_3_cnt += 1
# print('class number: ', clas_cnt)
print("#"*10, 'Class number in each APK', "#"*10)
print("max number: ", max(num_list))
print("min number: ", min(num_list))
print("mean number: ", int(mean(num_list)))
print("median number: ", int(np.median(np.array(num_list))))
print('number in (1k, 3k): ', k1_3_cnt)
print("#"*10, 'Method number in each Class', "#"*10)
print("max number: ", max(method_num_list))
print("min number: ", min(method_num_list))
print("mean number: ", int(mean(method_num_list)))
print("median number: ", int(np.median(np.array(method_num_list))))