Windows scripting sucks or does it?

I am not a fan of the big MS.  It started a long time ago when my funds were limited and I simply couldn’t afford to keep up with the MS upgrade schedule.  Not all of their software back in the day, in my opinion, was all that great.  I went cold turkey on as many of the MS products that I could.

There is a lot of open source software that could fill in the empty spots for me and since then most of my work life was on Unix which led to joys of shell scripting (ksh,bash,csh)

I love Unix shell scripting because the shell is basically just the glue to tie together a lot of small command line utilities which makes it easy to create and add extra commands, and Unix has a lot of command line tools.  Windows, at that time, had a very weak batch scripting language and a limited number interesting command line commands.

PowerShell

(Eventually) Those folks at MS decided to create their own scripting language called powershell.  They decided to take a slightly different route than the Unix crowd. Powershell is an interpreter that contains the logic for doing tasks.  This “shell” appears to be more of a replacement for the typical cmd.exe shell that has existed since the beginning (well it used to be command.com) as well as all of the command line programs.

The commands that exist from the powershell are called cmdlets.  Unlike Unix these are not a simple executables that can be executed from the cmd shell but are commands that are part of the powershell interpreter.  This might give a small bit of extra performance but it also means a new version of powershell is needed to add some new functionality.

The one good thing about the powershell is that it was installed on my computer by default. In addition, The big MS did want to show their security credentials and they have added a security level that must be set before you are able to run any powershell scripts.  This security level is essentially determining to which extent you trust powershell scripts with the focus being on either local or from other sources.

This is actually a pretty smart as it is possible to do quite a few things using powershell once you can run the scripts.  It would be pretty serious to have such power unlocked by default for any user who happens to execute a powershell script that is an attachment to an email.

However, even accidentally running a powershell script is a bit harder as MS has associated the extension .ps1 to be assigned to notepad.  Thus if you click on a script from windows explorer you will simply open up the script in notpad.

In order to run powershell scripts you need to first select an executable permission. There are four different permissions that can be selected in order to set the various rights at different levels.

Level Description
Restricted Can not run powershell scripts
RemoteSigned Can run local scripts but remote scripts need to be signed.
Unrestricted Any script can be run.
AllSigned Very secure, requires all scripts to be signed.
Undefined Removes existing level

Changing the level is actually pretty easy but you do need to be an administrator to do so. Simply use the set-executionpolicy cmdlet to set the permission to one of the described levels.

Signed Scripts

I personally am a fan of the unix “permissions” as it is really quite simple and very easy to modify. However, I wouldn’t say that they are the final word in preventing unauthorized scripts from being run.

I guess the final word is trying to protect your scripts is to use Microsoft’s method of creating recognized certificates while using a certification authority infrastructure.  If you want you can learn more about this by visiting Microsoft and downloading their best practices document.  I didn’t feel up to the task of going through the entire 67 page document so instead I decided to set my execution policy level to RemoteSigned.

This then let me run my fabulous powershell script.

$list = dir
echo $list

Actually this small script does quite a bit.  It does a directory listing and assigns the output to a variable.  Much like the bash shell that variable can be a list and echoed to the output device.

 

Note: It is possible to run any other programs from this powershell if they are in your path.

Unix friendly

It is possible that the big MS wanted to create a shell that would also appeal to the Unix crowd. I think this is the case as the powershell has the alias command.  This gave them the ability to create a bunch of commands that appear to include the common Unix commands.

The alias command links the name to an internal cmdlet which performs some action. One example of this is the “clear” alias being linked to the cmdlet clear-content.  The alias’s that they choose appear to look like they were picked to make Unix guys feel comfortable.

PS C:\Windows\system32> alias

CommandType     Name                            Definition
-----------     ----                            ----------
Alias           %                               ForEach-Object
Alias           ?                               Where-Object
Alias           ac                              Add-Content
Alias           asnp                            Add-PSSnapIn
Alias           cat                             Get-Content
Alias           cd                              Set-Location
Alias           chdir                           Set-Location
Alias           clc                             Clear-Content
Alias           clear                           Clear-Host
Alias           clhy                            Clear-History
Alias           cli                             Clear-Item
Alias           clp                             Clear-ItemProperty
Alias           cls                             Clear-Host
Alias           clv                             Clear-Variable
Alias           compare                         Compare-Object
Alias           copy                            Copy-Item
Alias           cp                              Copy-Item
Alias           cpi                             Copy-Item
Alias           cpp                             Copy-ItemProperty
Alias           cvpa                            Convert-Path
Alias           dbp                             Disable-PSBreakpoint
Alias           del                             Remove-Item
Alias           diff                            Compare-Object
Alias           dir                             Get-ChildItem
Alias           ebp                             Enable-PSBreakpoint
Alias           echo                            Write-Output
Alias           epal                            Export-Alias
Alias           epcsv                           Export-Csv
Alias           epsn                            Export-PSSession
Alias           erase                           Remove-Item
Alias           etsn                            Enter-PSSession
Alias           exsn                            Exit-PSSession
Alias           fc                              Format-Custom
Alias           fl                              Format-List
Alias           foreach                         ForEach-Object
Alias           ft                              Format-Table
Alias           fw                              Format-Wide
Alias           gal                             Get-Alias
Alias           gbp                             Get-PSBreakpoint
Alias           gc                              Get-Content
Alias           gci                             Get-ChildItem
Alias           gcm                             Get-Command
Alias           gcs                             Get-PSCallStack
Alias           gdr                             Get-PSDrive
Alias           ghy                             Get-History
Alias           gi                              Get-Item
Alias           gjb                             Get-Job
Alias           gl                              Get-Location
Alias           gm                              Get-Member
Alias           gmo                             Get-Module
Alias           gp                              Get-ItemProperty
Alias           gps                             Get-Process
Alias           group                           Group-Object
Alias           gsn                             Get-PSSession
Alias           gsnp                            Get-PSSnapIn
Alias           gsv                             Get-Service
Alias           gu                              Get-Unique
Alias           gv                              Get-Variable
Alias           gwmi                            Get-WmiObject
Alias           h                               Get-History
Alias           history                         Get-History
Alias           icm                             Invoke-Command
Alias           iex                             Invoke-Expression
Alias           ihy                             Invoke-History
Alias           ii                              Invoke-Item
Alias           ipal                            Import-Alias
Alias           ipcsv                           Import-Csv
Alias           ipmo                            Import-Module
Alias           ipsn                            Import-PSSession
Alias           ise                             powershell_ise.exe
Alias           iwmi                            Invoke-WMIMethod
Alias           kill                            Stop-Process
Alias           lp                              Out-Printer
Alias           ls                              Get-ChildItem
Alias           man                             help
Alias           md                              mkdir
Alias           measure                         Measure-Object
Alias           mi                              Move-Item
Alias           mount                           New-PSDrive
Alias           move                            Move-Item
Alias           mp                              Move-ItemProperty
Alias           mv                              Move-Item
Alias           nal                             New-Alias
Alias           ndr                             New-PSDrive
Alias           ni                              New-Item
Alias           nmo                             New-Module
Alias           nsn                             New-PSSession
Alias           nv                              New-Variable
Alias           ogv                             Out-GridView
Alias           oh                              Out-Host
Alias           popd                            Pop-Location
Alias           ps                              Get-Process
Alias           pushd                           Push-Location
Alias           pwd                             Get-Location
Alias           r                               Invoke-History
Alias           rbp                             Remove-PSBreakpoint
Alias           rcjb                            Receive-Job
Alias           rd                              Remove-Item
Alias           rdr                             Remove-PSDrive
Alias           ren                             Rename-Item
Alias           ri                              Remove-Item
Alias           rjb                             Remove-Job
Alias           rm                              Remove-Item
Alias           rmdir                           Remove-Item
Alias           rmo                             Remove-Module
Alias           rni                             Rename-Item
Alias           rnp                             Rename-ItemProperty
Alias           rp                              Remove-ItemProperty
Alias           rsn                             Remove-PSSession
Alias           rsnp                            Remove-PSSnapin
Alias           rv                              Remove-Variable
Alias           rvpa                            Resolve-Path
Alias           rwmi                            Remove-WMIObject
Alias           sajb                            Start-Job
Alias           sal                             Set-Alias
Alias           saps                            Start-Process
Alias           sasv                            Start-Service
Alias           sbp                             Set-PSBreakpoint
Alias           sc                              Set-Content
Alias           select                          Select-Object
Alias           set                             Set-Variable
Alias           si                              Set-Item
Alias           sl                              Set-Location
Alias           sleep                           Start-Sleep
Alias           sort                            Sort-Object
Alias           sp                              Set-ItemProperty
Alias           spjb                            Stop-Job
Alias           spps                            Stop-Process
Alias           spsv                            Stop-Service
Alias           start                           Start-Process
Alias           sv                              Set-Variable
Alias           swmi                            Set-WMIInstance
Alias           tee                             Tee-Object
Alias           type                            Get-Content
Alias           where                           Where-Object
Alias           wjb                             Wait-Job
Alias           write                           Write-Output

PS C:\Windows\system32>

This is NOT exactly like Unix. The “ls” alias does do a directory listing but unsurprisingly it does not accept the same options.

Microsofts cmdlets

PowerShell actually implements all the logic in the form of cmdlets.  You could find a book that described PowerShell programming along with (hopefully) a big reference section. That is one possible approach but the good news is that PowerShell has built in help.

The cmdlet get-help will return the information about any of the supported cmdlets.

Microsoft also has a very complete webpage that describes the different cmdlets. This information is grouped together by function.

https://technet.microsoft.com/en-us/library/dd772285.aspx

One final note about security

Well, I am glad that I didn’t spend a whole lot of time on setting up an elaborate system to deal with signed certificates.  It turns out that there are actually a number of different ways that you can run powershell scripts and some of them get around the existing security settings.

I didn’t actually come up with these methods myself, but instead happened upon the following webpage that elaborated a lot of ways to get around the execution policy.

15 Ways to Bypass the PowerShell Execution Policy

Of all the methods of bypassing the security I liked the method of piping the script through the interpreter and telling it to ignore the execution permissions by not using anyone’s profile.

Does windows scripting suck?  It is a bit too early to answer this question as the only script I have provided is equivalent to the dir command.  I will cover a bit more about powershell scripting in part II.

This entry was posted in programming and tagged , . Bookmark the permalink.