Skip to content

Create a batch file that runs powershell scripts even if the excutionpolicy is restricted

2011/02/20

When the executionpolicy is set to restricted is not possible to run scripts. This is the most used configuration found in companies on the clients. If you need to run a script on such a PC for troubleshooting or support, then it is possible if you convert the script to a encoded string and then pass it to powershell on the commandline.

The following code generates a batchfile that includes the script and starts powershell. You have to run it on a different machine and give it the path to the scriptfile and the name for the output batchfile.

The script you want to run is encoded. Then converted to a bunch of string that can be written to a temporary file by the echo command of the OS. That temporary file is used as an input when invoking powershell on the cmdline. The “double invocation of powershell” is needed to rebuild the original script.

if your inputscript is stored in a file named runme.ps1 and stored in the same directory as the create-batchrunner and your cmd file should be abc.cmd, you would use

.\create-batchrunner.ps1 runme.ps1 abc.cmd

the runme.ps1 is

"hello world" | write-host
$dummy = read-host "enter to continue"

the output batch wich can be run on the restricted clients is

@echo off
echo loading
echo IgBoAGUAbABsAG8AIAB3AG8AcgBsAGQAIgAgAHwAIAB3AHIAaQB0AGUALQBoAG8AcwB0AA0ACgAkAGQAdQBtAG0AeQAgA> %temp%\2ms.mtg
echo D0AIAByAGUAYQBkAC0AaABvAHMAdAAgACIAZQBuAHQAZQByACAAdABvACAAYwBvAG4AdABpAG4AdQBlACIADQAKAA==>> %temp%\2ms.mtg
 PowerShell -noprofile -Command "PowerShell -noprofile -encodedCommand ( (get-Content %temp%\2ms.mtg) -join '' )"

here is the script to create this

param ($ScriptToEncode, $OutBatchFileName, $LineLen = 93, $TmpFileName="2ms.mtg")
if ( -not (test-path $ScriptToEncode) ) {
"input script was not found" | write-host
return
}
if (test-path $OutBatchFileName) {
rm $OutBatchFileName
"removed existing output $OutBatchFileName" | write-host
}
$EncodedScriptText =  ([Convert]::ToBase64String([System.Text.Encoding]::Unicode.GetBytes((Get-Content $ScriptToEncode |%{$_}|out-string))))$redirect = "> %temp%\"+$TmpFileName
"@echo off" | out-file "$OutBatchFileName" -Encoding "ASCII"
"echo loading " | out-file "$OutBatchFileName" -append  -Encoding "ASCII"
$first = $true
while( $EncodedScriptText.length -gt $lineLen) {
"echo " + $EncodedScriptText.substring(0,$lineLen) + $redirect  | out-file "$OutBatchFileName" -append -Encoding "ASCII"
if($first){
$first = $false
$redirect = ">" + $redirect
}
$EncodedScriptText = $EncodedScriptText.substring($lineLen)
}
"echo " + $EncodedScriptText + $redirect  | out-file "$OutBatchFileName" -append -Encoding "ASCII"
$batchstart = @"
PowerShell -noprofile -Command "PowerShell -noprofile -encodedCommand ( (get-Content %temp%\$TmpFileName) -join '' )"
"@
$batchstart |  out-file "$OutBatchFileName" -append -Encoding "ASCII"

This was inspired by a link on the powerscripting podcast episode 130 that inked to Tome’s Land of IT . The base technique is described in the powershell help if you call it from the “dos” commandline with -? . Look at the last example.

Advertisements

From → powershell

One Comment
  1. myself permalink

    Just found in my mails:

    Get-Content ‘C:\temp\scriptsource.ps1’ | powershell.exe -noprofile –

    can excute the script stored in the file even if the executionpolicy is restricted. The magic is done by the undocumented / secret parameter –
    The dash at the end, does it. At least in version 2.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: