Tak
Tak

Reputation: 3616

Prevent PowerShell script from being read

I have the below PowerShell script (myscript.ps1) in which I ask for username and password. Depending on the username and password it copies a file to a certain destination.

$credentials = Get-Credential
if ($credentials.Username -eq "user1" -And $credentials.GetNetworkCredential().password -eq "pass1") 
{ Copy-Item "test1.pdf" "\test\test1.pdf"; } 
else 
{ Copy-Item "test2.pdf" "\test\test2.pdf"; }

Requirement: I want to make this file protected so no one can edit it and see the username and password.

PS2EXE

I found a solution found here which converts the PowerShell script to an .exe file. When I originally run the script using PowerShell a dialog box appears allowing me to enter the username and password:

Get-Credential dialog box

After the .exe is generated and when I run it the credentials dialog box no longer appears. Instead, the console appears saying "Credential:"

PS2EXE console

I don't know why? I want the credentials form to still appear when running the exe. Any thoughts please?

Upvotes: 0

Views: 4129

Answers (2)

MisterSeajay
MisterSeajay

Reputation: 4659

Q: Why does the EXE prompt with "Credential"?

This isn't an answer to the real question, and is based on guessing/supposition about PS2EXE, but I hope it is useful to clear up some confusion.

Having looked briefly at the PS2EXE page linked above, it seems that this utility encodes the script in Base64 and bundles it with a lightweight (?) custom PowerShell host. When run, I suppose the EXE starts the host, decodes the script and runs it.

The problem is that the Get-Credential cmdlet is running within a PS host that probably can't interact with the desktop. That is, it can't put up the GUI prompt for credentials. It therefore needs to prompt for the Credential property on the command line, explaining why you see that behaviour.

Workaround with Read-Host?

Instead of trying to use Get-Credential to prompt for username and password, you could embrace what PS2EXE seems to be doing and just use Read-Host:

$UserName = Read-Host "Enter username"
$Password = Read-Host "Enter password" -AsSecureString

$Credentials = New-Object System.Management.Automation.PSCredential $UserName,$Password

if ($credentials.Username -eq "user1" -And $credentials.GetNetworkCredential().password -eq "pass1") 
{ ... }

Using -AsSecureString will hide the password on the screen. The $Password variable will be of type System.Security.SecureString, which can be used to create a PSCredential object as shown.

You'd need to test this, but it seems that you're able to read from the shell but not from a GUI prompt.

And just to be clear: none of this is anywhere near best-practice security. If you need authentication/authorization for these activities, step back and look at the problem again.

Workaround with two scripts?

It seems that PS2EXE doesn't support -AsSecureString in the same way that normal PowerShell does, i.e. it doesn't hide the characters. A possible workaround for this would be to collect the username and password from the user in one script and then pass them to a PS2EXE-converted script for processing.

Launch-MyScript.ps1:

$Credentials = Get-Credential
& MyScript.exe $Credentials.Username $Credentials.Password

MyScript.exe (coverted with PS2EXE):

param($Username,$Password)

$Credentials = New-Object System.Management.Automation.PSCredential $Username,$Password

if ($Credentials.Username -eq "user1" -and
  $Credentials.GetNetworkCredential().password -eq "pass1")
{
  ...
}

The user runs Launch-MyScript.ps1 and completes the password prompt. Then the EXE is run automatically with the username and password passed in as arguments. Note that, as shown above, the password is a Secure String. Test this; I'm not using PS2EXE so it's a theoretical solution at the moment.

If you can't pass $Password along the pipeline as a Secure String object, you can convert it to text with ConvertFrom-SecureString in the first script, then conver it back with ConvertTo-SecureString in the second one.

Upvotes: 3

mgiedyk
mgiedyk

Reputation: 1

According to this article http://windowsitpro.com/powershell/protect-your-powershell-scripts you should first set ur execution policy to AllSigned by Set-ExecutionPolicy AllSigned, then create a certificate using makecert cmdlet.

Then u can sign single script using Set-AuthenticodeSignature cmdlet or use .pfx File to Sign a Script which appears even safer.

Hope it helps a bit.

Upvotes: 0

Related Questions