Asset Management, Identity, Vulnerability Management

Introduction to Microsoft PowerShell– Basics of Running Cmdlets

PowerShell Cmdlets

You will notice that for the PowerShell commands I use the word Cmdlet, that is how Microsoft calls and spells the word. In a PowerShell shell you can execute regular windows commands in addition to the cmdlets and most work without any problem some may experience problems depending on the parameters used since PowerShell uses space as a delimiter so do keep this in mind when you are running local exe files.

PowerShell cmdlets are in the form of a <verb>-<noun>, you will see common verbs like set, get, clear, write and stop to name a few and each belong to a group of actions, you can get an updated list of verbs at the TechNet site http://social.technet.microsoft.com/wiki/contents/articles/4537.powershell-approved-verbs-en-us.aspx do keep this list handy because if you create any module, cmdlet or function you should follow the naming so as to not confuse users and not get warnings from PowerShell when loading modules or cmdlets. To get a list of cmdlets on PS we use the Get-Command cmdlet:

image 

  When ran with no options we get a list of all cmdlet, functions and Aliases we have available. Just like on a Unix shell you will notice you have functions and aliases at your disposal to call. Aliases are mainly for saving time when entering commands and to make others more familiar when ran in a shell like the ls or the cat commands:

PS C:UsersCarlos Perez> ls


    Directory: C:UsersCarlos Perez


Mode                LastWriteTime     Length Name
----                -------------     ------ ----
d-r--         2/16/2012   3:03 PM            Contacts
d-r--         3/26/2012  11:23 PM            Desktop
d-r--         2/16/2012   3:03 PM            Documents
d-r--          3/8/2012   3:52 PM            Downloads
d-r--         2/16/2012   3:03 PM            Favorites
d-r--         2/16/2012   3:03 PM            Links
d-r--         2/16/2012   3:03 PM            Music
d-r--         2/16/2012   3:03 PM            Pictures
d-r--         2/16/2012   3:03 PM            Saved Games
d-r--         2/16/2012   3:03 PM            Searches
d-r--         2/16/2012   3:03 PM            Videos
-a---         3/28/2012   8:16 PM         28 hello.txt


PS C:UsersCarlos Perez> cat .hello.txt
hello world
PS C:UsersCarlos Perez> rm .hello.txt
PS C:UsersCarlos Perez> ls


    Directory: C:UsersCarlos Perez


Mode                LastWriteTime     Length Name
----                -------------     ------ ----
d-r--         2/16/2012   3:03 PM            Contacts
d-r--         3/26/2012  11:23 PM            Desktop
d-r--         2/16/2012   3:03 PM            Documents
d-r--          3/8/2012   3:52 PM            Downloads
d-r--         2/16/2012   3:03 PM            Favorites
d-r--         2/16/2012   3:03 PM            Links
d-r--         2/16/2012   3:03 PM            Music
d-r--         2/16/2012   3:03 PM            Pictures
d-r--         2/16/2012   3:03 PM            Saved Games
d-r--         2/16/2012   3:03 PM            Searches
d-r--         2/16/2012   3:03 PM            Videos

As we can see the aliases makes the shell behave similar to a Unix/Linux shell, but do keep in mind it is only similar, the parameters are not the same. 

One can use the tab key to auto complete PSDrive Paths (More on this on another blog post), File Paths,  Functions, Cmdlets, Function Options, Cmdlets Parameters, Variables and regular Windows Commands. So one can so Get-<tab> and keep hitting tab to cycle through the cmdlets available with the verb Get, the same can be done to find a cmdlet parameter like Get-Service –<tab>

The Get-Command also allow us to filter using wildcards:

PS C:UsersCarlos Perez> Get-Command -Name *service* -CommandType cmdlet

CommandType     Name                                                Definition
-----------     ----                                                ----------
Cmdlet          Get-Service                                         Get-Service [[-Name] <String[]>] [-ComputerName ...
Cmdlet          New-Service                                         New-Service [-Name] <String> [-BinaryPathName] <...
Cmdlet          New-WebServiceProxy                                 New-WebServiceProxy [-Uri] <Uri> [[-Class] <Stri...
Cmdlet          Restart-Service                                     Restart-Service [-Name] <String[]> [-Force] [-Pa...
Cmdlet          Resume-Service                                      Resume-Service [-Name] <String[]> [-PassThru] [-...
Cmdlet          Set-Service                                         Set-Service [-Name] <String> [-ComputerName <Str...
Cmdlet          Start-Service                                       Start-Service [-Name] <String[]> [-PassThru] [-I...
Cmdlet          Stop-Service                                        Stop-Service [-Name] <String[]> [-Force] [-PassT...
Cmdlet          Suspend-Service                                     Suspend-Service [-Name] <String[]> [-PassThru] [...

On Windows 8 in PowerShell v3 we have the the Show-Command cmdlet that will bring a GUI Interface for exploring the cmdlet and it options allowing us to copy the command we build or run the command:

image

When we want to get specific help on any cmdlet we can use the get-help cmdlet or it’s alias help:

image

This will provide us with a base help for the cmdlet where we can see:

  • Name
  • Synopsis
  • Syntax
  • Description
  • Related Links
  • Remarks

We can use the –detail option to get more details on the options, their types and position in the command arguments if we pass each value without an option, we can also use the –examples to get example on how to use the cmdlet and a brief description of what the command is doing and we can get a with –full the entire content of the help message. You can consider help/Get-Help as the man command in Unix/Linux. When you look at the Syntax section the options you can quickly determine what values you can provide to them. When we see the message we will see that each option we can pass is between [ ], some options do not require values those are just –<Parametername> other will take a value, for those that take a value PS will let you know the value type if it is a string, integer, object ..etc between <>, some can take a list of values and you will notice those will be in the format of <type[]>  and those that have a predefined list of options that can be given to a parameter will be in the format of < option1 | option2 | option3>.

If the computer you are running PowerShell on has internet connectivity you can give the parameter–online to the Get-Help cmdlet to open a browser window with the latest help information for it.

Let take a look at the Get-Service cmdlet:  

image

As we can see we in syntax we can call the cmdlet in 3 different ways, one where we start by providing the name or names of the service, another where we provide Display Names and a third where we pass service controller objects (Remember PowerShell cmdlets output objects). Let look at the first one:

Get-Service [[-Name] <string[]>] [-ComputerName <string[]>] [-DependentServices] [-Exclude <string[]>] [-Include <string[]>] [-RequiredServices] [<CommonParameters>]

As we can see the –Name parameter takes a list of strings. Lets get the state of several services:

PS C:UsersCarlos Perez> Get-Service -Name BITS, VSS

Status   Name               DisplayName
------   ----               -----------
Running  BITS               Background Intelligent Transfer Ser...
Stopped  VSS                Volume Shadow Copy

Now we ask for a full help for the command we will see for the name option that it accepts wildcard characters for the parameter of -Name and for the parameter of –DisplayName  so we can search for any service with the word WMI in its Display Name:

PS C:UsersCarlos Perez> Get-Service -DisplayName *WMI*

Status   Name               DisplayName
------   ----               -----------
Stopped  wmiApSrv           WMI Performance Adapter

The Wildcard Characters that can be used are shown in the table bellow:

Wildcard Character Description Example

*

Matches zero or more characters, starting at the specified position

a*

?

Matches any character at the specified position

?n

[ ]

Matches a range of characters

[a-l]name

[ ]

Matches the specified characters

[bc]name

 

In PowerShell one can use parameter abbreviation, similar to what one can do with commands on Cisco IOS we only need to enter enough of the parameter name that is is unique against the other. In the Get-Process cmdlet the only parameter that starts with the letter N is Name so we can shorten it to only this letter:

PS C:UsersCarlos Perez> Get-Process -N *vm*

Handles  NPM(K)    PM(K)      WS(K) VM(M)   CPU(s)     Id ProcessName
-------  ------    -----      ----- -----   ------     -- -----------
    270      20     8956       7708    87            1392 vmtoolsd
    289      23    15252      14388   145   113.97   2544 vmtoolsd
     68       9     3444       3148    68     0.55   2532 VMwareTray

As we play with parameters and comandlets one of the things we can do is to maintain a transcript. We can do this with the Start-Transcript cmdlet, this will save all of our commands and output to a file and when we issue the cmdlet Stop-Transcript it will stop recording our action, we can even append to an existing file by giving it the –Append parameter. One thing to note is that you can not use it on ISE.


PS C:Windowssystem32> Start-Transcript C:windowsTemptesttranscript.txt
Transcript started, output file is C:windowsTemptesttranscript.txt
PS C:Windowssystem32> Get-Service | select -first 1

Status   Name               DisplayName
------   ----               -----------
Stopped  AeLookupSvc        Application Experience


PS C:Windowssystem32> Get-process | select -first 1

Handles  NPM(K)    PM(K)      WS(K) VM(M)   CPU(s)     Id ProcessName
-------  ------    -----      ----- -----   ------     -- -----------
     23       4     2128       1460    38     0.09    408 cmd

LogName: PS C:Windowssystem32> Stop-Transcript
Transcript stopped, output file is C:windowsTemptesttranscript.txt

Now as mentioned before PowerShell cmdlets return objects and we can pipe this objects to other cmdlets. We can illustrate by saving an object in to a variable and looking at what we have available. In PowerShell variables start with with $ In this example we will look at the object for the BITS service:

PS C:Windowssystem32> $srv = Get-Service -Name BITS
PS C:Windowssystem32> $srv

Status   Name               DisplayName
------   ----               -----------
Running  BITS               Background Intelligent Transfer Ser...

If we want to know it’s type we can use the .Net method of gettype()

PS C:Windowssystem32> $srv.GetType().fullname
System.ServiceProcess.ServiceController

If we want to look at the methods (actions that can be taken) and Properties (Information) of an object we can use the Get-Members cmdlet.

PS C:Windowssystem32> Get-Member -InputObject $srv


   TypeName: System.ServiceProcess.ServiceController

Name                      MemberType    Definition
----                      ----------    ----------
Name                      AliasProperty Name = ServiceName
RequiredServices          AliasProperty RequiredServices = ServicesDependedOn
Disposed                  Event         System.EventHandler Disposed(System.Object, System.EventArgs)
Close                     Method        System.Void Close()
Continue                  Method        System.Void Continue()
CreateObjRef              Method        System.Runtime.Remoting.ObjRef CreateObjRef(type requestedType)
Dispose                   Method        System.Void Dispose()
Equals                    Method        bool Equals(System.Object obj)
ExecuteCommand            Method        System.Void ExecuteCommand(int command)
GetHashCode               Method        int GetHashCode()
GetLifetimeService        Method        System.Object GetLifetimeService()
GetType                   Method        type GetType()
InitializeLifetimeService Method        System.Object InitializeLifetimeService()
Pause                     Method        System.Void Pause()
Refresh                   Method        System.Void Refresh()
Start                     Method        System.Void Start(), System.Void Start(string[] args)
Stop                      Method        System.Void Stop()
ToString                  Method        string ToString()
WaitForStatus             Method        System.Void WaitForStatus(System.ServiceProcess.ServiceControllerStatus desi...
CanPauseAndContinue       Property      System.Boolean CanPauseAndContinue {get;}
CanShutdown               Property      System.Boolean CanShutdown {get;}
CanStop                   Property      System.Boolean CanStop {get;}
Container                 Property      System.ComponentModel.IContainer Container {get;}
DependentServices         Property      System.ServiceProcess.ServiceController[] DependentServices {get;}
DisplayName               Property      System.String DisplayName {get;set;}
MachineName               Property      System.String MachineName {get;set;}
ServiceHandle             Property      System.Runtime.InteropServices.SafeHandle ServiceHandle {get;}
ServiceName               Property      System.String ServiceName {get;set;}
ServicesDependedOn        Property      System.ServiceProcess.ServiceController[] ServicesDependedOn {get;}
ServiceType               Property      System.ServiceProcess.ServiceType ServiceType {get;}
Site                      Property      System.ComponentModel.ISite Site {get;set;}
Status                    Property      System.ServiceProcess.ServiceControllerStatus Status {get;}

 

We can also pipe the contents of the variable to the the cmdlet like so $srv | Get-Members as we can see we can get information like status, type, dependencies and we can take actions like pause , start and stop. we can also use tab completion to cycle thru the methods and properties of an object when it is in a variable.

Lets stop the service and get it’s status before and after:

PS C:Windowssystem32> (Get-Service -Name BITS).status
Stopped
PS C:Windowssystem32> (Get-Service -Name BITS).start()
PS C:Windowssystem32> (Get-Service -Name BITS).status
Running

You will notice that methods are always called with ( )  in the end since a methods takes parameters, properties we can call directly and they are the state of when the object was created that is why we execute the command and work with the object directly by running the command between parenthesis. 

Also properties and the results from methods can have methods and more properties beneath them, we can chain this to get the value or results we want.

PS C:Windowssystem32> $srv.Status.GetType()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     ServiceControllerStatus                  System.Enum

Another way would be to use the refresh method:

PS C:Windowssystem32> $srv.Status
Running
PS C:Windowssystem32> $srv.Stop()
PS C:Windowssystem32> $srv.Refresh()
PS C:Windowssystem32> $srv.Status
Stopped

As you can see one of the main advantages of PowerShell is the is the advantage to manipulate the data as objects and not as text. In the next post I will cover more on how to work with several objects, how to modify the objects and piping.

As always I hope you find this post informative and useful.

Carlos Perez

Carlos is currently the Principal Consultant, Team Lead for Research at TrustedSec and well-known for his research on both Metasploit and Windows Powershell. His blog www.darkoperator.com carries the tag line: “Shell Is Only The Beginning”.

Get daily email updates

SC Media's daily must-read of the most current and pressing daily news

By clicking the Subscribe button below, you agree to SC Media Terms and Conditions and Privacy Policy.