PowerShell scripts can contain sensitive information that you wouldn’t want to fall into the wrong hands. This video tutorial by Brien Posey explains how to encrypt individual lines of code within PowerShell scripts.
The following transcript has been lightly edited for length and clarity.
Brien Posey: PowerShell scripts can be really useful for automating tasks in your organization. But those same scripts can also be a little bit risky from a security standpoint, simply for the fact that the scripts themselves are stored in plain text and can sometimes contain sensitive information about your organization.
So, that being said, I want to show you a technique for encrypting individual lines of code within a PowerShell script. That way, if a script contains anything particularly sensitive, you can hide that sensitive item from view.
Let's take a look at how this works.
Manual Steps for PowerShell Encryption
I'm going to open up File Explorer. And you can see it. I've already created several files. The first file that I have here is something called HelloWorld.ps1. This is just a really simple script that displays the words “Hello World” on the screen. I'll go ahead and execute this. That's all this script does.
So, let me go ahead and switch back to File Explorer. And I'll open up my Hello World script. And you can see that the script consists of a single line of code. So, let's pretend for the purposes of this demo that this is a particularly sensitive line of code containing information about your organization's infrastructure. So, let's go ahead and encrypt this.
The first thing that I did was to make a copy of this, and I saved it as a .txt file. And you can see that file right here. It's called HelloWorld.txt. And if I open this up, you can see that it's identical to the file that I just showed you, the only difference being that this is stored in .txt format. So let me go ahead and close that out.
And now I've created a PowerShell script called EncryptCode.ps1. You can see that script right here. I'll go ahead and open this up. And this is a fairly simple four-line script. The very first line of code creates a variable called $Code, which you can see right here. And that variable is set equal to Get-Content. And then we're reading in the .txt file that I showed you a moment ago, the HelloWorld.txt file.
$Code = Get-Content C:\Scripts\HelloWorld.txt
The next line of code converts the contents of that .txt file to a secure string. Now, I'll execute this entire script in just a moment, but let's go ahead and take a look at what this does line by line.
So, I'm going to go ahead and copy this first line of code. I'll paste this into PowerShell. And so, there's no visible output. But we've created a variable called $Code. Let's go ahead and take a look at the contents of that variable. So, you can see that $Code is set to Write-Host ‘Hello World’.
So let me switch back over to my script. The second line of code that I showed you earlier is designed to convert that to a secure string, and in doing so, it creates a variable called $CodeSecureString.
$CodeSecureString = ConvertTo-SecureString $Code -AsPlainText -Force
Let's go ahead and manually run that command, as well.
Once again, let's take a look at the contents of this variable. So, the variable is $CodeSecureString. And you can see that the variable simply contained System.Security.SecureString. So, the contents of that secure string are being hidden from us.
So, now let's take a look at our script once again. The third line creates a variable called $Encrypted. And we're setting that variable equal to ConvertFrom-SecureString -SecureString $CodeSecureString.
$Encrypted = ConvertFrom-SecureString -SecureString $CodeSecureString
What we're doing is we're taking that secure string that we just created and we're converting that from a secure string and restoring the contents in a variable called $Encrypted.
Let's go ahead and run that line of code. Let's take a look at the contents of the $Encrypted variable. And you can see that now what we have is an encrypted string.
The last thing that we have to do is to write that string out to a file. And the way that we would do that is by typing $Encrypted, then typing that to Out-File, then the file path, and then the name of the file that we want to create.
$Encrypted | Out-File -FilePath C:\Scripts\Encrypted.txt
Let's go ahead and do that now.
And so we should have a file called Encrypted.txt. And if I open it up, you can see that it contains the encrypted string.
Run Encryption as a PowerShell Script
Now, I ran all these steps manually, but we could run that as a script instead. So, let me go ahead and close this out. And I'm going to go ahead and delete that .txt file. And let's just run EncryptCode.ps1. And you can see that the Encrypted.txt file has been created once again. The contents of this file should be the same as what we had earlier.
While I've got the Encrypted.txt file open, I'm going to go ahead and copy the encrypted string. So, I’ve copied the encrypted string to the clipboard. Let me go ahead and close this out.
And so now the last thing that we have to do is put that encrypted string to use. Remember, the overall goal that we're trying to achieve is to hide a particularly sensitive line of code within a PowerShell script.
So, I've got another script here called RunCode.ps1, and we'll pretend that this is our PowerShell script that contains the line of code that we want to hide. Let me go ahead and open this up. And the very first line of code is $Instructions =, and you can see that that set to “”.
$Instructions = “”
What I want to do is paste the encrypted string between these quotation marks. So, we're creating a variable called $Instructions, and we're setting it equal to that encrypted string.
Now we've pasted the encrypted command into our PowerShell script, but PowerShell can’t use the command in its encrypted form, so we have to have a little bit of code to decrypt the command in order for that to be used.
So, what I've done is I've created a variable called $Decrypt, and I've set that equal to $Instructions. Remember, $Instructions is our encrypted command right here. And then I'm piping that to ConvertTo-SecureString. So, I'm taking that encrypted value and I'm turning it back into a secure string.
$Decrypt = $Instructions | ConvertTo-SecureString
Then our last line of code creates a variable called $Code, which you can see right here. And then setting that equal to [Runtime.InteropServices.Marshal]. Now, you'll notice that we have a double colon right here. Anytime that you see a double colon in PowerShell, what that means is that you're invoking a .NET method. So, that's exactly what we're doing right here. We're calling the .NET framework, and we're using some of the functionality from .NET in order to decrypt this string.
$Code = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($Decrypt))
And we're taking the decrypted contents and we're setting that equal to $Code. So, now $Code is going to contain our formerly encrypted command, but it's now been decrypted.
So, all we have to do now is run that line of code. We can do that by using the Invoke-Expression $Code command.
Let's take a look at what this looks like. I'm going to go ahead and save this. And one of the things about using Notepad for PowerShell is that it defaults to saving files in UTF-8 format, but you can end up having an error if you're trying to use PowerShell in UTF-8 format. You need to set this equal to ANSI. So, I’m going to save this in ANSI format.
And then all execute RunCode.ps1. And you can see that RunCode.ps1 produces the same results as our Hello World script, except that now the command that causes the words Hello World to be displayed on the screen is encrypted and completely obfuscated. So, anybody who takes a look at the contents of this particular PowerShell script isn't going to be able to see that particular command.
Now, obviously, Write-Host ‘Hello World’ isn't sensitive content by any stretch of the imagination, but you can only imagine what would happen if you had a line of code that stored a password, provided a path to a server that you didn't want the world to know about, or something like that. This is a great way of hiding code within your PowerShell script.
So, that's how you encrypt and decrypt a command in a PowerShell script.
About the authorBrien Posey is a bestselling technology author, speaker, and 21x Microsoft MVP. In addition to his ongoing work in IT, Posey has trained as a commercial astronaut candidate in preparation to fly on a mission to study polar mesospheric clouds from space.