-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathjanus.py
141 lines (123 loc) · 5.31 KB
/
janus.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
#!/usr/bin/python3
import sys
import os
import argparse
import struct
import datetime
import subprocess
import importlib
from hashlib import sha1
from zlib import adler32
from androguard.core.bytecodes.apk import APK
from androguard.util import get_certificate_name_string
class suppress_output:
def __init__(self,suppress_stdout=False,suppress_stderr=False):
self.suppress_stdout = suppress_stdout
self.suppress_stderr = suppress_stderr
self._stdout = None
self._stderr = None
def __enter__(self):
devnull = open(os.devnull, "w")
if self.suppress_stdout:
self._stdout = sys.stdout
sys.stdout = devnull
if self.suppress_stderr:
self._stderr = sys.stderr
sys.stderr = devnull
def __exit__(self, *args):
if self.suppress_stdout:
sys.stdout = self._stdout
if self.suppress_stderr:
sys.stderr = self._stderr
COLOR_DICT = {
'red': "\033[91m",
'green': "\033[92m",
'yellow': "\033[93m",
'cyan': "\033[96m",
'default': "\033[0m"
}
def print_message(msg, color='default'):
console_color = COLOR_DICT.get(color.lower())
console_default = COLOR_DICT.get('default')
if color == 'red':
print(console_color + "[X]" + console_default + " " + msg)
elif color == 'green':
print(console_color + "[+]" + console_default + " " + msg)
elif color == 'yellow':
print(console_color + "[!]" + console_default + " " + msg)
elif color == 'cyan':
print(console_color + msg + console_default)
else:
print(msg)
def check_required_tools_and_install():
andro = importlib.util.find_spec("androguard")
requirements = ["adb"]
ninstalled = 0
null = open("/dev/null", "w")
for tool in requirements:
try:
subprocess.Popen(tool, stdout=null, stderr=null)
null.close()
print_message('{0} is installed'.format(tool.upper()), 'cyan')
except OSError:
ninstalled = 1
print_message('{0} is not installed'.format(tool.upper()), 'red')
if ninstalled:
print_message("\nPlease install missing tools and re-run the exploit", 'cyan')
quit()
sdk, android = "27", "8.0.0"
def is_apk_vulnerable(apk):
with suppress_output(suppress_stdout=True,suppress_stderr=True): a = APK(app)
global sdk, android
if a.is_signed():
print_message('APK is signed', 'green')
if a.is_signed_v1():
print_message('v1 signature enabled - APK is potentially vulnerable for devices less than API level {0} (Android {1})'.format(sdk, android), 'yellow')
if a.is_signed_v2() or a.is_signed_v3():
sdk, android = "24", "7.0.0"
print_message('v2 and/or v3 signature enabled', 'green')
if a.get_min_sdk_version() < sdk:
print_message('APK ({0}) is set to run on devices less than API level {1} (Android {2})'.format(a.get_min_sdk_version(), sdk, android), 'yellow')
print_message('APK is vulnerable', 'red')
print_message("Please connect a device through adb to verify patch", 'cyan')
device_connected = input(COLOR_DICT.get('cyan') + "Once device is connected. Press 'y' (or any to exit): " + COLOR_DICT.get('default'))
if device_connected != "y":
quit()
else:
print_message('APK is Not Vulnerable - min SDK supported ({0}) is Not vulnerable'.format(a.get_min_sdk_version()), 'green')
quit()
else:
print_message('APK is Not signed', 'yellow')
quit()
parser = argparse.ArgumentParser()
print_message("Exploits the Janus Vulnerability\n", 'cyan')
parser.add_argument("apk_in", metavar="original-apk", type=str, help="original source apk to be checked")
args = parser.parse_args()
check_required_tools_and_install()
app = args.apk_in
is_apk_vulnerable(app)
device = os.popen("adb devices").read().split('\n', 1)[1].split("device")[0].strip()
if len(device) <= 1:
print_message('No device Connected', 'yellow')
quit()
else:
print_message('Device connected', 'cyan')
result = subprocess.Popen(['adb', 'shell', 'getprop', 'ro.build.version.sdk'], stdout=subprocess.PIPE)
api = str(result.communicate())
api = api.split("\n")[0].split('\\')[0].split("(b'")[1]
if api < sdk:
result = subprocess.Popen(['adb', 'shell', 'getprop', 'ro.build.version.release'], stdout=subprocess.PIPE)
release = str(result.communicate())
release = release.split("\n")[0].split('\\')[0].split("(b'")[1]
print_message('Android device {0} is connected (API Level {1})'.format(release, api), 'green')
result = subprocess.Popen(['adb', 'shell', 'getprop', 'ro.build.version.security_patch'], stdout=subprocess.PIPE)
patch = str(result.communicate())
patch = patch.split("\n")[0].split('\\')[0].split("(b'")[1]
patched = "2017-12-01"
if patched > patch:
print_message('Android security Patch level {0} is vulnerable'.format(patch), 'red')
null.close()
else: print_message('Android device is patched with 2017-12-05 which is not vulnerable', 'green')
else:
print_message('Device is Not vulnerable to Janus', 'green')
quit()