Run a script as an admin user - ps2exe??

Do any of you have experience using PS2EXE ([url]https://ps2exe.codeplex.com/[/url]) script? It takes a script as input and outputs an exe file of the script. I am trying to use this process to create a script to self elevate without having the password easily obtained in the script.

I have a script that I can pass a file path to, and it will run another powershell script as an admin user. This script that runs as the admin user copies some files to various places on the machine and across the network. I need to be able to copy files to essentially anywhere on the machine or on the other machine that is on the same subnet.

Currently, my script, Enable-Elevated takes a parameter, FilePath. This file path is the path to the powershell script that needs to run as an admin. The script itself works fine - no problem other than the username and password being embedded in the script itself. So, ideally I would like to take my Enable-Elevated script and turn it into an exe so the password is not as easily in the clear.

My problem is - when I exe the script, it isn’t working. It doesn’t seem to recognize the paramter, and I just don’t understand. Like I mentioned, the script runs fine. The problem occurs when I convert it to an exe and call it with the parameter.

Any help or ideas would be greatly appreciated.

Thanks

Here is my Enable-Elevated script:


Param
(
    # Param1 help description
    [Parameter(Mandatory=$false, 
                ValueFromPipeline=$false,
                ValueFromPipelineByPropertyName=$false, 
                ValueFromRemainingArguments=$false, 
                Position=0,
                ParameterSetName='Parameter Set 1')]
    [ValidateNotNull()]
    [ValidateNotNullOrEmpty()]
    [ValidatePattern("([^\s]+(\.(?i)(ps1))$)")]
    [string]$FilePath,

    # Param2 help description
    [Parameter(Mandatory=$false, 
                ValueFromPipeline=$false,
                ValueFromPipelineByPropertyName=$false, 
                ValueFromRemainingArguments=$false, 
                ParameterSetName='Parameter Set 1')]
    [ValidateSet("Normal", "Minimized", "Hidden")]
    [string]$WindowStyle = "Hidden", 

    # Param3 help description
    [switch] $Help


)

$logFile = "c:\posapps\elevate\" + $(Get-Date -DisplayHint Date -Format "yyyyMMdd") + "_elevated.log"


 "$(Get-Date -DisplayHint Time -Format T)::  Elevate Process Started" | Add-Content $logFile
 
# output usage
if($help -or [String]::IsNullOrEmpty($FilePath)) 
{
    Write-Host "Usage:"
    Write-Host ""
    Write-Host "    elevate.exe -FilePath '' [-WindowStyle] 'Normal' | 'Minimized' | 'Hidden'"
    Write-Host ""       
    Write-Host ""       
    Write-Host "        FilePath = Path to the signed powershell script to run"       
    Write-Host "     WindowStyle = Passes this to the powershell exe.  Options are Normal | Minimized | Hidden"       
    write-host ""

    "$(Get-Date -DisplayHint Time -Format T)::  Elevate Process Exiting" | Add-Content $logFile
    Exit
}




$command = "c:\windows\system32\windowspowershell\v1.0\powershell.exe"
# example c:\posapps\powershell\ApplyPricing.ps1"
#TODO - run powershell with an execution policy of allsigned
$arguments = "-File $FilePath"

"$(Get-Date -DisplayHint Time -Format T)::  File Path: $filepath" | Add-Content $logFile
"$(Get-Date -DisplayHint Time -Format T)::  Window Style: $WindowStyle" | Add-Content $logFile

$user = "DOMAIN\adminaccount"
$pass = ConvertTo-SecureString -String "AdminPassword" -AsPlainText -Force
$creds = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $user, $pass
 
Try{

    if(Test-Path -Path $FilePath)
    {
        # append the script path to the arguments
        $arguments += $FilePath
    
        # start the process
        Start-Process -FilePath $command -ArgumentList $arguments -WindowStyle $WindowStyle -Credential $creds
        
    }

}
Catch [System.Exception]
{

    $message = "$_ #([environment]::NewLine) Command: $command $([environment]::NewLine) Arguments: $arguments" 
    $(Get-Date -DisplayHint Time -Format T):: ERROR: $message | Add-Content $logFile


}

# log the script ending


"$(Get-Date -DisplayHint Time -Format T)::  Elevate Process Exiting" | Add-Content $logFile

Exit


According to ps2exe’s documentation, you need to pass the -end parameter to the executable before any arguments that you want to be passed to the embedded script.

However, I’d just like to point out that you haven’t really gained anything in terms of security. The original script still exists in easily decoded text, for anyone who cares to look. For example, using DotPeek on my compiled exe and looking at the Main function turns up this line:

string @string = Encoding.UTF8.GetString(Convert.FromBase64String("JHBhc3N3b3JkID0gJ1N1cGVyIHNlY3JldCEn"));

# Running this code at a PowerShell console:

[Text.Encoding]::UTF8.GetString([convert]::FromBase64String('JHBhc3N3b3JkID0gJ1N1cGVyIHNlY3JldCEn'))

# Returns my original script:

$password = 'Super secret!'

There is absolutely no way to have a self-elevating script (assuming the elevation happens locally) where it is not possible for the user to extract the credentials used for elevation. They can be obfuscated, but a determined person will always be able to peel back the layers and get to the original password; it’s just a question of how much effort is involved.

If that’s not acceptable for you, the secure way to accomplish this is to set up a PowerShell remoting endpoint with the -RunAsCredential option set. That way, the elevated credentials are stored on a remote host and are never exposed to the local, unprivileged user. You can also define who has permissions to use the endpoint, and what commands are allowed to be run from inside of it. Jeffrey Snover has been working on a module named JEA (Just Enough Admin) to make setting up these endpoints easy; you can read about it here. He’s also given talks about this module at several events over the past year (PowerShell Summit, TechEd, etc.)

For some information about custom PSRemoting endpoints topic in general, Boe Prox did a great series on this topic back in April. Here’s a link to the last article in the series; it contains links to the first 4: http://blogs.technet.com/b/heyscriptingguy/archive/2014/04/04/build-a-tool-that-uses-constrained-powershell-endpoint.aspx

Thank you very much for this response. I will take a look at the reading and posts about the JEA and powershell endpoints. I hope they can fit what I am trying to accomplish.

As far as the documentation for ps2exe goes… where do you see that? I looked on the codex, and came up empty. I did a find in ISE on the script itself and see "-end " in there at one point, is this where?

Thanks again!
sb

The documentation I referred to is about 2/3 down on the page at https://ps2exe.codeplex.com/ . It starts with “The generated EXE can also be calls using command line options”, followed by a table with 4 parameters and their descriptions.