/
autopatcher.py
117 lines (94 loc) · 3.8 KB
/
autopatcher.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
import androguard
from androguard.core.bytecodes import apk
from androguard.core.bytecodes.dvm import DalvikVMFormat
import argparse
import subprocess
import xml.etree.ElementTree as etree
from subprocess import PIPE as SPIPE
parser = argparse.ArgumentParser(description='Perform static patching & analysis of an Android apk')
parser.add_argument('file', type=str, nargs=1, metavar='filename', help='the file to operate on')
args = parser.parse_args()
input_file = args.file[0]
# setup
apk_file = input_file + ".apk"
debuggable_attribute = "{http://schemas.android.com/apk/res/android}debuggable"
apktool_decode = ["apktool", "d", apk_file ]
apktool_build = ["apktool", "b", input_file, "-o" + input_file + "-debug.apk"]
jarsigner_sign = ["jarsigner", "-verbose", "-sigalg", "SHA1withRSA",
"-digestalg", "SHA1", "-keystore", "autopatcher.jks", "-storepass", "password",
input_file + "-debug.apk", "autopatcher-keystore" ]
attack_surface = [ 'activity', 'service', 'receiver', 'provider' ]
# TODO verify properly signed apk
# Shouldn't I be able to do this with Androguard?
# Step one : make APK debuggable, sign it
subprocess.run(apktool_decode, stdout=SPIPE, stderr=SPIPE)
manifest_file = etree.parse(input_file + '/AndroidManifest.xml')
for child in manifest_file.getroot():
if child.tag == "application":
child.attrib[debuggable_attribute] = 'true'
manifest_file.write(input_file + '/AndroidManifest.xml', encoding="unicode")
subprocess.run(apktool_build, stdout=SPIPE, stderr=SPIPE)
# this doesn't align the zip because we're not releasing it.
subprocess.run(jarsigner_sign, stdout=SPIPE, stderr=SPIPE)
# Step two: do static analysis using androguard
apkf = apk.APK(apk_file)
activities = apkf.get_activities()
receivers = apkf.get_receivers()
services = apkf.get_services()
providers = apkf.get_providers()
exported_activities = []
exported_receivers = []
dynamic_exported_receivers = []
exported_services = []
exported_providers = []
for activity in activities:
if apkf.get_element('activity', 'exported', name=activity) == 'true':
exported_activities.append(activity)
else:
filters = apkf.get_intent_filters("activity", activity)
if len(filters) > 0:
exported_activities.append(activity)
for receiver in receivers:
if apkf.get_element('receiver', 'exported', name=receiver) == 'true':
exported_receivers.append(receiver)
else:
filters = apkf.get_intent_filters("receiver", receiver)
if len(filters) > 0:
exported_receivers.append(receiver)
dexf = DalvikVMFormat(apkf.get_dex())
for item in dexf.get_classes_def_item().get_obj():
if "BroadcastReceiver" in str(item):
dynamic_exported_receivers.append(item)
for service in services:
if apkf.get_element('service', 'exported', name=service) == 'true':
exported_services.append(service)
else:
filters = apkf.get_intent_filters("service", service)
if len(filters) > 0:
exported_services.append(service)
if int(apkf.get_target_sdk_version()) < 17:
exported_providers = providers
else:
for provider in providers:
if apkf.get_element('provider', 'exported', name=provider) == 'true':
exported_providers.append(provider)
else:
filters = apkf.get_intent_filters('provider', provider)
if len(filters) > 0:
exported_providers.append(provider)
print(apkf.get_app_name())
print("\nActivities:")
for activity in exported_activities:
print(activity)
print("\nReceivers (static):")
for receiver in exported_receivers:
print(receiver)
print("\nReceivers (dynamic):")
for receiver in dynamic_exported_receivers:
print(receiver)
print("\nServices:")
for service in exported_services:
print(service)
print("\nProviders:")
for provider in exported_providers:
print(provider)