forked from honeynet/droidbot
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathstart.py
230 lines (217 loc) · 12.3 KB
/
start.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
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
# helper file of droidbot
# it parses command arguments and send the options to droidbot
import os
import argparse
import time
from droidbot import input_manager
from droidbot import input_policy
from droidbot import env_manager
from droidbot import DroidBot
from droidbot.adapter import frida_trace
from droidbot.droidmaster import DroidMaster
def parse_args():
"""
parse command line input
generate options including host name, port number
"""
parser = argparse.ArgumentParser(description="Start DroidBot to test an Android app.",
formatter_class=argparse.RawTextHelpFormatter)
parser.add_argument("-d", action="store", dest="device_serial", required=False,
help="The serial number of target device (use `adb devices` to find)")
parser.add_argument("-a", action="store", dest="apk_path", required=True,
help="The file path to target APK")
parser.add_argument("-o", action="store", dest="output_dir",
help="directory of output")
# parser.add_argument("-env", action="store", dest="env_policy",
# help="policy to set up environment. Supported policies:\n"
# "none\tno environment will be set. App will run in default environment of device; \n"
# "dummy\tadd some fake contacts, SMS log, call log; \n"
# "static\tset environment based on static analysis result; \n"
# "<file>\tget environment policy from a json file.\n")
parser.add_argument("-policy", action="store", dest="input_policy", default=input_manager.DEFAULT_POLICY,
help='Policy to use for test input generation. '
'Default: %s.\nSupported policies:\n' % input_manager.DEFAULT_POLICY +
' \"%s\" -- No event will be sent, user should interact manually with device; \n'
' \"%s\" -- Use "adb shell monkey" to send events; \n'
' \"%s\" -- Explore UI using a naive depth-first strategy;\n'
' \"%s\" -- Explore UI using a greedy depth-first strategy;\n'
' \"%s\" -- Explore UI using a naive breadth-first strategy;\n'
' \"%s\" -- Explore UI using a greedy breadth-first strategy;\n'
%
(
input_policy.POLICY_NONE,
input_policy.POLICY_MONKEY,
input_policy.POLICY_NAIVE_DFS,
input_policy.POLICY_GREEDY_DFS,
input_policy.POLICY_NAIVE_BFS,
input_policy.POLICY_GREEDY_BFS,
))
# for distributed DroidBot
parser.add_argument("-distributed", action="store", dest="distributed", choices=["master", "worker"],
help="Start DroidBot in distributed mode.")
parser.add_argument("-master", action="store", dest="master",
help="DroidMaster's RPC address")
parser.add_argument("-qemu_hda", action="store", dest="qemu_hda",
help="The QEMU's hda image")
parser.add_argument("-qemu_no_graphic", action="store_true", dest="qemu_no_graphic",
help="Run QEMU with -nograpihc parameter")
parser.add_argument("-script", action="store", dest="script_path",
help="Use a script to customize input for certain states.")
parser.add_argument("-count", action="store", dest="count", default=input_manager.DEFAULT_EVENT_COUNT, type=int,
help="Number of events to generate in total. Default: %d" % input_manager.DEFAULT_EVENT_COUNT)
parser.add_argument("-interval", action="store", dest="interval", default=input_manager.DEFAULT_EVENT_INTERVAL,
type=int,
help="Interval in seconds between each two events. Default: %d" % input_manager.DEFAULT_EVENT_INTERVAL)
parser.add_argument("-timeout", action="store", dest="timeout", default=input_manager.DEFAULT_TIMEOUT, type=int,
help="Timeout in seconds, -1 means unlimited. Default: %d" % input_manager.DEFAULT_TIMEOUT)
parser.add_argument("-cv", action="store_true", dest="cv_mode",
help="Use OpenCV (instead of UIAutomator) to identify UI components. CV mode requires opencv-python installed.")
parser.add_argument("-debug", action="store_true", dest="debug_mode",
help="Run in debug mode (dump debug messages).")
parser.add_argument("-random", action="store_true", dest="random_input",
help="Add randomness to input events.")
parser.add_argument("-keep_app", action="store_true", dest="keep_app",
help="Keep the app on the device after testing.")
parser.add_argument("-keep_env", action="store_true", dest="keep_env",
help="Keep the test environment (eg. minicap and accessibility service) after testing.")
parser.add_argument("-use_method_profiling", action="store", dest="profiling_method",
help="Record method trace for each event. can be \"full\" or a sampling rate.")
parser.add_argument("-grant_perm", action="store_true", dest="grant_perm",
help="Grant all permissions while installing. Useful for Android 6.0+.")
parser.add_argument("-is_emulator", action="store_true", dest="is_emulator",
help="Declare the target device to be an emulator, which would be treated specially by DroidBot.")
parser.add_argument("-accessibility_auto", action="store_true", dest="enable_accessibility_hard",
help="Enable the accessibility service automatically even though it might require device restart\n(can be useful for Android API level < 23).")
parser.add_argument("-humanoid", action="store", dest="humanoid",
help="Connect to a Humanoid service (addr:port) for more human-like behaviors.")
parser.add_argument("-ignore_ad", action="store_true", dest="ignore_ad",
help="Ignore Ad views by checking resource_id.")
parser.add_argument("-replay_output", action="store", dest="replay_output",
help="The droidbot output directory being replayed.")
# for the addition of frida-trace
parser.add_argument("-frida_trace_args", action="store", dest="frida_trace_args",
help="File containing the arguments for frida-trace. These are the functions, methods and so on \nthat frida-trace shall take into account.\nSee frida_trace_args/ for examples")
parser.add_argument("-frida_trace_out", action="store", dest="frida_trace_out", default='frida_out',
help="Path to directory where frida-trace results will be saved")
# to save snapshots
parser.add_argument('-save_snapshot', action="store_true", dest="save_snapshot",
help="Save a snapshot before installing an application")
parser.add_argument('-telnet_token_path', action="store", dest="telnet_token_path",
help="Path to the telnet token in order to establish a telnet connection to the device")
options = parser.parse_args()
# print options
return options
def main():
"""
the main function
it starts a droidbot according to the arguments given in cmd line
"""
opts = parse_args()
if not os.path.exists(opts.apk_path):
print("Path to APK(s) does not exist.")
return
if not opts.output_dir and opts.cv_mode:
print("To run in CV mode, you need to specify an output dir (using -o option).")
if opts.distributed:
if opts.distributed == "master":
start_mode = "master"
else:
start_mode = "worker"
else:
start_mode = "normal"
if start_mode == "master":
droidmaster = DroidMaster(
app_path=opts.apk_path,
is_emulator=opts.is_emulator,
output_dir=opts.output_dir,
# env_policy=opts.env_policy,
env_policy=env_manager.POLICY_NONE,
policy_name=opts.input_policy,
random_input=opts.random_input,
script_path=opts.script_path,
event_interval=opts.interval,
timeout=opts.timeout,
event_count=opts.count,
cv_mode=opts.cv_mode,
debug_mode=opts.debug_mode,
keep_app=opts.keep_app,
keep_env=opts.keep_env,
profiling_method=opts.profiling_method,
grant_perm=opts.grant_perm,
enable_accessibility_hard=opts.enable_accessibility_hard,
qemu_hda=opts.qemu_hda,
qemu_no_graphic=opts.qemu_no_graphic,
humanoid=opts.humanoid,
ignore_ad=opts.ignore_ad,
replay_output=opts.replay_output)
droidmaster.start()
else:
if not os.path.isdir(opts.apk_path):
droidbot = DroidBot(
app_path=opts.apk_path,
device_serial=opts.device_serial,
is_emulator=opts.is_emulator,
output_dir=opts.output_dir,
# env_policy=opts.env_policy,
env_policy=env_manager.POLICY_NONE,
policy_name=opts.input_policy,
random_input=opts.random_input,
script_path=opts.script_path,
event_interval=opts.interval,
timeout=opts.timeout,
event_count=opts.count,
cv_mode=opts.cv_mode,
debug_mode=opts.debug_mode,
keep_app=opts.keep_app,
keep_env=opts.keep_env,
profiling_method=opts.profiling_method,
grant_perm=opts.grant_perm,
enable_accessibility_hard=opts.enable_accessibility_hard,
master=opts.master,
humanoid=opts.humanoid,
ignore_ad=opts.ignore_ad,
replay_output=opts.replay_output,
frida_trace_args=opts.frida_trace_args,
frida_trace_out=opts.frida_trace_out,
telnet_auth_token_path=opts.telnet_token_path,
save_snapshot=opts.save_snapshot)
droidbot.start()
elif os.path.isdir(opts.apk_path):
# We are going to treat every application within that folder:
directory = os.fsdecode(opts.apk_path)
for file in os.listdir(directory):
file_name = os.fsdecode(file)
file_path = os.path.abspath(directory + file_name)
if file_name.endswith('.apk'):
droidbot = DroidBot(
app_path=file_path,
device_serial=opts.device_serial,
is_emulator=opts.is_emulator,
output_dir=opts.output_dir,
# env_policy=opts.env_policy,
env_policy=env_manager.POLICY_NONE,
policy_name=opts.input_policy,
random_input=opts.random_input,
script_path=opts.script_path,
event_interval=opts.interval,
timeout=opts.timeout,
event_count=opts.count,
cv_mode=opts.cv_mode,
debug_mode=opts.debug_mode,
keep_app=opts.keep_app,
keep_env=opts.keep_env,
profiling_method=opts.profiling_method,
grant_perm=opts.grant_perm,
enable_accessibility_hard=opts.enable_accessibility_hard,
master=opts.master,
humanoid=opts.humanoid,
ignore_ad=opts.ignore_ad,
frida_trace_args=opts.frida_trace_args,
frida_trace_out=opts.frida_trace_out,
telnet_auth_token_path=opts.telnet_token_path,
save_snapshot=opts.save_snapshot)
droidbot.start()
time.sleep(5)
return
if __name__ == "__main__":
main()