Using SecureString to protect Malware

Malware and SecureString? Why not.


Whilst writing a PowerShell Packer, I had a quick look into ConvertTo-SecureString and quickly remembered it is a feature in Invoke-Obfuscation. Looking into this as a method of obfuscation then led me to PowerShell Obfuscation using SecureString.
This seems to be a trend now, but what I wanted was to use it in an Environmental Keying scenario.
But first, what is it...

About SecureString

SecureString, as far as I can tell, is an AES encrypted string which aims to help users mask credentials. To see how secure SecureString is, Microsoft have a How Secure is SecureString explanation.
Lets have a look at an example:
WMI Connection Example
In the above, Get-WmiObject is used to query a remote computer. It then failed, and a new credential was created and used; this allowed access.

Small Proof-of-Concept

As an example, here is how data would be encrypted:
  1. 1.
    Get a key: For now, an array of 0 -> 31 will do.
$key = (0..31)
  1. 2.
    Encrypt the data with ConvertTo-SecureString
ConvertFrom-SecureString -Key $key (ConvertTo-SecureString "Get-Date" -AsPlainText -Force)
This will produce something like:
And here is a screenshot of that all executing:
To then decrypt it, the following command can be used:
(New-Object System.Net.NetworkCredential("", (ConvertTo-SecureString -key $key $encrypted))).Password
Which looks like this:
Converting Get-Date to SecureString
Quite simple.

Using SecureString for Keying

Now lets take a quick look at how this can be used with keying... Honestly, its quite simple. Assume the payload to run is Get-Date, and the keying string is:
In this case, it would be:
To join the string:
To convert this to a byte array:
This now has one issue, it is not of length 32. Which, again, is easy to fix with PadRight():
Wrapping this up:
$key = [system.Text.Encoding]::UTF8.GetBytes(((-join($env:USERDNSDOMAIN,'\',$env:USERNAME)).PadRight(32,0).ToLower()))
ConvertFrom-SecureString -Key $key (ConvertTo-SecureString "Get-Date" -AsPlainText -Force)
In my case, it produces:
Here is an example of it all running:
Decrypting Get-Date
Now that it works, lets automate it.

Automating it

I was unable to find a good way to do this natively in Linux, and I didn't want to do it on Windows because of Invoke-Obfuscation, and I tend to work from Linux 99% of the time anyway.
Here is the script I threw together which relies on PowerShell for Linux:
import subprocess
def get_encrypted_payload(payload: str, password: str) -> str:
base_command: str = f"$key = [system.Text.Encoding]::UTF8.GetBytes('{password}'.PadRight(32,0));ConvertFrom-SecureString -Key $key (ConvertTo-SecureString '{payload}' -AsPlainText -Force)"
output = (
subprocess.check_output(["pwsh", "-c", base_command]).decode().strip("\n")
return output
except Exception as e:
print(f"[!] Error: {str(e)}")
return None
def executor(encrypted: str) -> str:
password = "(([System.Text.encoding]::UTF8.GetBytes(((-join($env:USERDNSDOMAIN,'\\',$env:USERNAME)).PadRight(32,0).ToLower()))))"
return f"(New-Object System.Net.NetworkCredential('', (ConvertTo-SecureString -key ${password} '{encrypted}'))).Password|Invoke-Expression"
def main() -> None:
password: str = "johto.local\\lance"
payload: str = "Get-Date"
encrypted: str = get_encrypted_payload(payload, password)
if not encrypted:
cradle: str = executor(encrypted)
if __name__ == "__main__":
This script is a Python3.9+ utility which automates all of the previous steps discussed. Running the script will give:
(New-Object System.Net.NetworkCredential('', (ConvertTo-SecureString -key $(([System.Text.encoding]::UTF8.GetBytes(((-join($env:USERDNSDOMAIN,'\',$env:USERNAME)).PadRight(32,0).ToLower())))) '76492d1116743f0423413b16050a5345MgB8ADEAMABOADgAUQBBADQATQBDAEoAZABpAE4AdwA2AFoAdQBiAE8AVgBDAFEAPQA9AHwAYwBmAGMAMwA5AGMAZgA2AGYANwA5ADQAOAA4ADkAZABlADcAMAAxADMAYQBhADgAMQA3ADAAOQA2ADcAMgAyADEANAA3ADIANABkADUAMgA1ADEAMQBiAGIANwAyAGMAMQAwADEANQBjADMAOAA5ADYAOQAzADkAMAA4AGUAYwA='))).Password|Invoke-Expression
Running on the incorrect target:
Incorrect target
And on the correct host:
Correct target


This isn't new, nor is it particularly exciting. Its just something I ended up spending a few hours playing with. As PowerShell doesn't really have much usage offensively any more, it is also widely used in dotnet.
Go Up!