forked from alessandrodd/apk_api_key_extractor
-
Notifications
You must be signed in to change notification settings - Fork 3
/
main.py
executable file
·137 lines (117 loc) · 5.4 KB
/
main.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
#!/usr/bin/env python3
import argparse
import logging
import logging.config
import os
import shutil
import sys
import time
import json
from console_dump import ConsoleDump
from mongodb_dump import MongoDBDump
from jsonlines_dump import JsonlinesDump
import config
LOG_CONFIG_PATH = "log_config.json"
__location__ = os.path.realpath(os.path.join(os.getcwd(), os.path.dirname(__file__)))
# Configure logging
with open(os.path.join(__location__, LOG_CONFIG_PATH), "r", encoding="utf-8") as fd:
log_config = json.load(fd)
logging.config.dictConfig(log_config["logging"])
import apk_analyzer
def clean_resources(apk_path, lock, decoded_apk_output_path, apks_analyzed_dir, remove_apk=False):
"""
Clean the resources allocated to analyze a string
:param apk_path: path of the apk that has been
:param lock: a lock that is locking the aforementioned apk
:param decoded_apk_output_path: where the decoded apk where placed
:param apks_analyzed_dir: where the apk should be moved after analysis; None if it should not be moved
:param remove_apk: True if the apk should be deleted; ignored if apks_analyzed_dir is not None
"""
apk = os.path.basename(apk_path)
try:
if os.path.exists(decoded_apk_output_path):
shutil.rmtree(decoded_apk_output_path)
else:
logging.error("Unable to find decoded folder for {0}".format(apk_path))
if apks_analyzed_dir:
if not os.path.exists(apks_analyzed_dir):
os.mkdir(apks_analyzed_dir)
# either way, move the apk out of apk dir
shutil.move(apk_path, os.path.join(apks_analyzed_dir, apk))
elif remove_apk:
os.remove(apk_path)
finally:
if lock:
# unlock and clean temp files; cleaning should not be necessary
# noinspection PyProtectedMember
lockfile = lock._lockfile
if lock.is_locked:
lock.unlock()
if os.path.exists(lockfile):
os.remove(lockfile)
def analyze_apk(apk_path, apks_decoded_dir, apks_analyzed_dir, apktool_path, lock=None):
apk = os.path.basename(apk_path)
decoded_output_path = os.path.join(apks_decoded_dir, apk)
try:
apikeys, all_strings, package, version_code, version_name = apk_analyzer.analyze_apk(apk_path,
decoded_output_path,
apktool_path)
if apikeys:
dump = None
if config.dump_location == "console":
dump = ConsoleDump()
elif config.dump_location == "jsonlines":
dump = JsonlinesDump()
elif config.dump_location == "mongodb":
dump = MongoDBDump()
else:
print("Unrecognized dump location: {0}".format(config.dump_location))
exit(1)
dump.dump_apikeys(apikeys, package, version_code, version_name)
if config.dump_all_strings:
dump.dump_strings(all_strings)
except apk_analyzer.ApkAnalysisError as e:
logging.error(str(e))
clean_resources(apk_path, lock, decoded_output_path, apks_analyzed_dir, not config.save_analyzed_apks)
def monitor_apks_folder(apks_dir, apks_decoded_dir, apks_analyzed_dir, apktool_path):
logging.info("Monitoring {0} for apks...".format(apks_dir))
try:
while True:
apk_path, lock = apk_analyzer.get_next_apk(apks_dir)
if lock is not None:
logging.info("Detected {0}".format(apk_path))
analyze_apk(apk_path, apks_decoded_dir, apks_analyzed_dir, apktool_path, lock)
logging.info("{0} analyzed".format(apk_path))
else:
time.sleep(1)
except KeyboardInterrupt:
print('\nInterrupted!')
def main():
parser = argparse.ArgumentParser(
description='A python program that finds API-KEYS and secrets hidden inside strings', add_help=True
)
parser.add_argument('--debug', action="store_true", dest='boolean_debug',
default=False, help='Print debug information')
parser.add_argument('--analyze-apk', action='store', dest='apk_path',
help='Analyze a single apk to find hidden API Keys')
parser.add_argument('--monitor-apks-folder', action="store_true", dest='boolean_monitor',
default=False, help='Monitors the configured apks folder for new apks. '
'When a new apk is detected, the file is locked and analysis starts.')
results = parser.parse_args()
# functions that don't need gibberish detector
if results.boolean_debug:
logging.basicConfig(level=logging.DEBUG)
elif results.apk_path:
analyze_apk(results.apk_path, os.path.abspath(config.apks_decoded_dir),
None, os.path.abspath(config.apktool))
return
elif results.boolean_monitor:
apks_analyzed_dir = None
if config.save_analyzed_apks:
apks_analyzed_dir = os.path.abspath(config.apks_analyzed_dir)
monitor_apks_folder(os.path.abspath(config.apks_dir), os.path.abspath(config.apks_decoded_dir),
apks_analyzed_dir, os.path.abspath(config.apktool))
return
parser.print_help()
if __name__ == '__main__':
main()