Meterpreter New Windows PowerShell Extension

I still remember 5 years ago when I decided to do my first PowerShell class at Derbycon and some of my buddies told me I was nuts for teaching what they called a "Toy Language" I have used  Windows PowerShell almost daily for work since 2007, started with my previous job setting up and securing Exchange 2007 servers, once PowerCLI from VMware come out it became my go to environment for automating and hardening ESX and ESXi environments.   Once we figured how to run encoded commands it became a must for post-exploitation since it gave me access to ADSI, COM, Win32 API, .NET API and all sorts of third party .NET library I could get my hands on. Some kind of PowerShell ability has been present in most major comercial products one way or another and now Metasploit is taking it a step further thanks to the great work of OJ Reeves also known as @TheColonial by adding a Metrerpeter extension for unmanaged Windows PowerShell Runspace.  This extension is based on the work from Lee Christensen and his UnmanagedPowerShell project.

Read More

My New Home Lab Setup

After I posted in Twitter that I was building a second ESXi server for my lab I got quite a large number of replies and direct messages on what I used as a lab. Based on the interest I decided to write a blog post on why I choose the gear I did and where do I see upgrading it in the near future.

Needs

I have to say we need to start with the needs first since this will dictate what hardware I will need, what hypervisor is best for the work I will do and will also have an impact on my budget.

I need a lab where I can run:

  • Operating Systems:
    • Windows XP/2003 to the latest version 8.1/2012 R2 - I have a MSDN Subscription this year that will help me cover the older versions of the OS and allow me to build permanent labs for complex setups since do to time and work I can not be rebuilding every couple of months. For the latest versions of Windows I use trial versions since Microsoft offers 180 days for server versions and 90 days for client version of the OS this allows me to test different types of persistence and weird configs and I just re-deploy from a template.
    • Linux - I run all kind of different versions of Linux where I test Bash, Python and Ruby scripts I write plus also test forensics and log management research.
    • Oracle Solaris - Currently have customers that run Solaris so I need to be able to run it to test all kinds of configurations, scripts and custom Metasploit modules.
    • FreeBSD - To isolate my labs I use PFSense and also I run several VMs with versions of JunOS that is based on FreeBSD.
    • OS X - Even do I can run OS X on my MacBook Pro I still prefer to have several copies of the server products and the recent client versions since I have been seeing it more and more in corporate environments and it has always been present in educational ones.
  • Nested Hypervisors (VMware, MS Hyper-V, KVM and Xen) - In my day job I do a lot of work on the security of different hypervisors and also I maintain some post-exploitation code to detect when running inside of a VM.
  • Support for Virtual Switches - Virtual Switching allows me to create separate networks with different policies so as to isolate traffic and also mimic a real network better. Some virtual switches allow for port mirroring and bandwith throttling so I can use IDS/IPS for testing, Capture traffic and also mimic WAN connections.
  • API for VM Management - The ability to automate deployment and configuration of VMs becomes important when one needs to tests conde or workflows against different operating systems under different configurations.
Read More

PowerShell Basics - Extending the Shell with Modules and Snapins

In PowerShell there are 2 main ways to extend the shell, this are:

  • Modules - A package that contains Windows PowerShell commands int he form of functions, cmdlerts and workflows, in addition it may contain variables, aliases and providers. Modules can be written in PowerShell and/or compiled as DLLs.

  • Snap-Ins - Are compiled cmdlets in to a DLL written in a .Net language are being deprecated and no longer recommended as the way to create and package new cmdlets.

There is a big miss conception with people starting with PowerShell install server products like Exchange or SharePoint, this programs place a shortcut to what they call a "Management Shell" which is not in reality a dedicated shell for it. it is nothing more than PowerShell with a loaded Module or PSSnapin. As you will see extending the shell is quite simple and flexible.

Working with Modules

Modules have primarily 2 locations on your system:

  • %windir%\system32\WindowsPowerShell\v1.0\Modules this is the location for system wide modules available to any user in the system.
  • %USERPROFILE%\Documents\WindowsPowerShell\Modules

Each module is stored in a folder where there is a psd1 file that is known as a Module Manifest, this manifest has the settings for the module and sets the restrictions for it in terms of .Net Framework version, version of PowerShell, files to load, version, copyright, author and many other settings. This file can load what is called a main module and sub-modules each can either be a psm1 or dll file, in addition they can also be scripts that gets processes. As it can be seen using modules provide great flexibility in terms of formats and structure.

We can also have modules in other locations that can be accessed by the PowerShell session we run in, the locations are defined in the environment variable $env:PSModulePath

C:\> $env:PSModulePath
C:\Users\Carlos\Documents\WindowsPowerShell\Modules;C:\Windows\system32\WindowsPowerShell\v1.0\Modules\

If we want to add another path for PowerShell to look at we just add that path to the current environment variable:

$env:psmodulepath = $env:psmodulepath + ";"

To list the modules that are available we use the Get-Module cmdlet withe the -listavailable parameter:

Get-Module -ListAvailable

This will list all modules that the session can see in the paths that are specified in the environment variable. On PowerShell v2 we would have to load each module we wanted by hand and only then would be be able to use the commands available, in the case of PowerShell v3 Microsoft now allows us access to the modules in those paths and the modules are loaded dynamically when a cmdlet, workflow, alias or function that form part of the module is invoked.

If you only want to see the modules that are currently loaded in to the session the -All parameter is used with Get-Module:

C:\> Get-Module -All

ModuleType NameExportedCommands
---------- --------------------
Script Discovery {Invoke-ARPScan, Invoke-PingScan, Invoke-PortScan, Invoke-ReverseDNSLookup...
Binary Microsoft.PowerShell.Activities
Binary Microsoft.PowerShell.Commands.Ma... {Add-Content, Clear-Content, Clear-ItemProperty, Join-Path...}
Binary Microsoft.PowerShell.Commands.Ut... {Get-FormatData, Export-FormatData, Format-List, Format-Custom...}
Manifest Microsoft.PowerShell.Management {Add-Computer, Add-Content, Checkpoint-Computer, Clear-Content...}
Manifest Microsoft.PowerShell.Utility{Add-Member, Add-Type, Clear-Variable, Compare-Object...}
Binary Microsoft.Powershell.Workflow.Se... {Import-PSWorkflow, New-PSWorkflowExecutionOption}
Script Parse {Import-DNSReconXML, Import-NessusReport}
Script posh-git{Add-SshKey, Enable-GitColors, Get-AliasPattern, Get-GitDirectory...}
Script posh-nessus {Copy-NessusPolicy, Get-NessusPolicyXML, Get-NessusReportHostsDetailed, Ge...
Script Posh-SecMod {Add-Zip, Compress-PostScript, Confirm-IsAdmin, Connect-SQLite3...}
Binary PoshSSH {New-SSHSession, New-SFTPSession}
Script Posh-SSH{New-SFTPSession, New-SSHSession, Get-SFTPCurrentDirectory, Get-SFTPDirect...
Script PostExploitation{Compress-PostScript, ConvertTo-PostBase64Command, New-PostDownloadExecute...
Script PSWorkflow{New-PSWorkflowSession, nwsn}
Manifest PSWorkflow{New-PSWorkflowExecutionOption, New-PSWorkflowSession, nwsn}
Script Registry{Get-RegKeys, Get-RegKeySecurityDescriptor, Get-RegValue, Get-RegValues...}

To import a module in to our session we just use the Import-Module cmdlet and give it the name of the module. I tend to recommend to people starting with PowerShell that when working on a shell session interactively to always add the -Verbose parameter,, this will list the cmdlets, functions and aliases that are being made available to you when you import the module. Lets take for example a module that I have been developing for automating tasks via SSH:

C:\> Import-Module -Name Posh-SSH -Verbose
VERBOSE: Loading module from path 'C:\Users\Carlos\Documents\WindowsPowerShell\Modules\Posh-SSH\Posh-SSH.psd1'.
VERBOSE: Importing cmdlet 'New-SFTPSession'.
VERBOSE: Importing cmdlet 'New-SSHSession'.
VERBOSE: Importing function 'Get-SFTPCurrentDirectory'.
VERBOSE: Importing function 'Get-SFTPDirectoryList'.
VERBOSE: Importing function 'Get-SFTPFile'.
VERBOSE: Importing function 'Get-SFTPSession'.
VERBOSE: Importing function 'Get-SSHPortForward'.
VERBOSE: Importing function 'Get-SSHSession'.
VERBOSE: Importing function 'Invoke-SSHCommand'.
VERBOSE: Importing function 'Move-SFTPFile'.
VERBOSE: Importing function 'New-SFTPDirectory'.
VERBOSE: Importing function 'New-SSHDynamicPortForward'.
VERBOSE: Importing function 'New-SSHPortForward'.
VERBOSE: Importing function 'Remove-SFTPDirectory'.
VERBOSE: Importing function 'Remove-SFTPFile'.
VERBOSE: Importing function 'Remove-SFTPSession'.
VERBOSE: Importing function 'Remove-SSHSession'.
VERBOSE: Importing function 'Set-SFTPDirectoryPath'.
VERBOSE: Importing function 'Set-SFTPFile'.
VERBOSE: Importing function 'Start-SSHPortForward'.
VERBOSE: Importing function 'Stop-SSHPortForward'.

As you can see it tells me the cmdlets and script functions it loaded in to the session. If you are in a session and want to know if a module is loaded the Get-Module cmndlet with the -Name option is use and we give it the module name we want to know about, if it returns the information about the module the module is loaded, if nothing is returned the module is not:

C:\> Get-Module -Name posh-ssh

ModuleType NameExportedCommands
---------- --------------------
Script Posh-SSH{New-SFTPSession, New-SSHSession, Get-SFTPCurrentDirectory, Get-SFTPDirect...

To remove the module from our session we use the Remove-Module cmdlet and give it the name of the module we want to remove:

C:\> Remove-Module -Name posh-ssh -Verbose
VERBOSE: Performing operation "Remove-Module" on Target "PoshSSH (Path:
'C:\Users\Carlos\Documents\WindowsPowerShell\Modules\Posh-SSH\PoshSSH.dll')".
VERBOSE: Performing operation "Remove-Module" on Target "Posh-SSH (Path:
'C:\Users\Carlos\Documents\WindowsPowerShell\Modules\Posh-SSH\Posh-SSH.psm1')".
VERBOSE: Removing the imported "Get-SFTPCurrentDirectory" function.
VERBOSE: Removing the imported "Get-SFTPDirectoryList" function.
VERBOSE: Removing the imported "Get-SFTPFile" function.
VERBOSE: Removing the imported "Get-SFTPSession" function.
VERBOSE: Removing the imported "Get-SSHPortForward" function.
VERBOSE: Removing the imported "Get-SSHSession" function.
VERBOSE: Removing the imported "Invoke-SSHCommand" function.
VERBOSE: Removing the imported "Move-SFTPFile" function.
VERBOSE: Removing the imported "New-SFTPDirectory" function.
VERBOSE: Removing the imported "New-SSHDynamicPortForward" function.
VERBOSE: Removing the imported "New-SSHPortForward" function.
VERBOSE: Removing the imported "Remove-SFTPDirectory" function.
VERBOSE: Removing the imported "Remove-SFTPFile" function.
VERBOSE: Removing the imported "Remove-SFTPSession" function.
VERBOSE: Removing the imported "Remove-SSHSession" function.
VERBOSE: Removing the imported "Set-SFTPDirectoryPath" function.
VERBOSE: Removing the imported "Set-SFTPFile" function.
VERBOSE: Removing the imported "Start-SSHPortForward" function.
VERBOSE: Removing the imported "Stop-SSHPortForward" function.
C:\> Get-Module -Name posh-ssh
C:\>

You can see in the example I used the Get-Module cmdlet to confirm the module is not present. We can also load modules by calling directly the DLL or the PSM1 file, lets call another module I'm still developing for controlling Metasploit:

C:\> Import-Module C:\Users\Carlos\Desktop\Posh-Metasploit.psm1 -Verbose
VERBOSE: Loading module from path 'C:\Users\Carlos\Desktop\Posh-Metasploit.psm1'.
VERBOSE: Exporting function 'New-MSFSession'.
VERBOSE: Exporting function 'Get-MSFSession'.
VERBOSE: Exporting function 'Invoke-MSFExploit'.
VERBOSE: Exporting function 'Invoke-MSFAuxiliary'.
VERBOSE: Exporting function 'Get-MSFModuleInfo'.
VERBOSE: Exporting function 'Get-MSFJobs'.
VERBOSE: Exporting function 'Get-MSFSessions'.
VERBOSE: Exporting function 'Get-MSFNotes'.
VERBOSE: Exporting function 'Get-MSFServices'.
VERBOSE: Exporting function 'Get-MSFHosts'.
VERBOSE: Exporting function 'Get-MSFLoot'.
VERBOSE: Exporting function 'Get-MSFCredentials'.
VERBOSE: Importing function 'Get-MSFCredentials'.
VERBOSE: Importing function 'Get-MSFHosts'.
VERBOSE: Importing function 'Get-MSFJobs'.
VERBOSE: Importing function 'Get-MSFLoot'.
VERBOSE: Importing function 'Get-MSFModuleInfo'.
VERBOSE: Importing function 'Get-MSFNotes'.
VERBOSE: Importing function 'Get-MSFServices'.
VERBOSE: Importing function 'Get-MSFSession'.
VERBOSE: Importing function 'Get-MSFSessions'.
VERBOSE: Importing function 'Invoke-MSFAuxiliary'.
VERBOSE: Importing function 'Invoke-MSFExploit'.
VERBOSE: Importing function 'New-MSFSession'.

If you are developing a module and whant to reload the module with the changes you just made I recommend just using the Import-Module cmdlet with the -Force parameter instead of removing and importing the module again. If we want tot see the command for a specific module we can use the Get-Command cmdlet:

C:\> Get-Command -Module Bitlocker

CommandType Name ModuleName
----------- ---- ----------
FunctionAdd-BitLockerKeyProtectorBitlocker
FunctionBackup-BitLockerKeyProtector Bitlocker
FunctionClear-BitLockerAutoUnlockBitlocker
FunctionDisable-BitLockerBitlocker
FunctionDisable-BitLockerAutoUnlockBitlocker
FunctionEnable-BitLocker Bitlocker
FunctionEnable-BitLockerAutoUnlock Bitlocker
FunctionGet-BitLockerVolumeBitlocker
FunctionLock-BitLocker Bitlocker
FunctionRemove-BitLockerKeyProtector Bitlocker
FunctionResume-BitLocker Bitlocker
FunctionSuspend-BitLockerBitlocker
FunctionUnlock-BitLocker Bitlocker

Working with PSSnapins

PSSnapings is the old method from PowerShell v1 that is used to extend the shell, in PowerShell v2 and PowerShell v3 it can still be used but Microsoft has started to tell developers to move away from the sanpin model and move to the module model of extending the shell. Still many 3rd Party extension, the most popular being VMware PowerCLI, in fact Microsoft PowerShell core cmdlets are still in snapin format so we will still see support for snapins for a while.

We can list the cmdlets available for managing PSSnapin usin the Get-Command cmdlet and giving it PSSnapin as the verb to look for:

C:\> Get-Command -Noun PSSnapin

CommandType Name ModuleName
----------- ---- ----------
CmdletAdd-PSSnapin Microsoft.PowerShell.Core
CmdletGet-PSSnapin Microsoft.PowerShell.Core
CmdletRemove-PSSnapinMicrosoft.PowerShell.Core

Since snapins are DLLs that get registered on the system unlike modules that do not need any registration we use the -Registered paramter with the Get-PSSnapin cmdlet to list the snapins available:

C:\> Get-PSSnapin -Registered


Name: VMware.DeployAutomation
PSVersion : 2.0
Description : Cmdlets for Rule-Based-Deployment

Name: VMware.ImageBuilder
PSVersion : 2.0
Description : This Windows PowerShell snap-in contains VMware ESXi Image Builder cmdlets used to generate custom images.

Name: VMware.VimAutomation.Core
PSVersion : 2.0
Description : This Windows PowerShell snap-in contains Windows PowerShell cmdlets for managing vSphere.

Name: VMware.VimAutomation.License
PSVersion : 2.0
Description : This Windows Powershell snap-in contains cmdlets for managing License components.

To load a snapin we use the Add-PSSnapin cmdlet and give it the name of the PSSnapin we want to load:

C:\> Add-PSSnapin -Name VMware.VimAutomation.Core
C:\> Remove-PSSnapin -Name VMware.VimAutomation.Core
C:\> Add-PSSnapin -Name VMware.VimAutomation.Core -Verbose
C:\>

The cmndlet does not produce any output, even when -Verbose is used as it can be see in the example. To see what snapins are loaded we use the Get-PSSnapin with no parameters:

C:\> Get-PSSnapin


Name: Microsoft.PowerShell.Core
PSVersion : 3.0
Description : This Windows PowerShell snap-in contains cmdlets used to manage components of Windows PowerShell.

Name: VMware.VimAutomation.Core
PSVersion : 2.0
Description : This Windows PowerShell snap-in contains Windows PowerShell cmdlets for managing vSphere.

To get a list of the cmdlets and Functions it importer we use the Get-Command cmdlet wit the -Module parameter and give it the PSSnapin name:

C:\> Get-Command -Module VMware.VimAutomation.Core

CommandType Name ModuleName
----------- ---- ----------
CmdletAdd-PassthroughDeviceVMware.VimAutomation.Core
CmdletAdd-VMHost VMware.VimAutomation.Core
CmdletAdd-VmHostNtpServerVMware.VimAutomation.Core
CmdletApply-DrsRecommendationVMware.VimAutomation.Core
CmdletApply-VMHostProfileVMware.VimAutomation.Core
CmdletConnect-VIServer VMware.VimAutomation.Core
CmdletCopy-DatastoreItem VMware.VimAutomation.Core
CmdletCopy-HardDiskVMware.VimAutomation.Core
CmdletCopy-VMGuestFile VMware.VimAutomation.Core
CmdletDisconnect-VIServerVMware.VimAutomation.Core
CmdletDismount-Tools VMware.VimAutomation.Core
CmdletExport-VAppVMware.VimAutomation.Core
.......

As it can be seen PSSnapins are limited, thus making their management simpler.

As always I hope you found the blogpost useful and informative, as a side note many of the Modules you see in my machine are projects I have started and not finished so do ask for when I will release those because many I just do not know other than the SSH module that is in my GitHub.

Introduction to WMI Basics with PowerShell Part 1 (What it is and exploring it with a GUI)

For a while I have been posting several ways I use WMI (Windows Management Instrumentation) in my day to day and in consulting but have never covered the basics. Talking with other people in the security field and in the system administration worlds they seem to see WMI as this voodoo black magic that only a few who venture in to it master it. Do to the programmatic way that one retrieves information from it I see why some who have not coded or scripted may be afraid of it, so I will take my best attempt at showing the basics of it in a simple easy to understand way.

What is WMI?

WMI is the Microsoft implementation of Web-Based Enterprise Management (WBEM), with some enhancements in the initial version of it, WBEM is a  industry initiative to develop a standard technology for accessing management information in an enterprise environment that covers not only Windows but also many other types of devices like routers, switches, storage arrays …etc. WMI uses the Common Information Model (CIM) industry standard to represent systems, applications, networks, devices, and other managed components. CIM is developed and maintained by the Distributed Management Task Force (DMTF).

All of that sounds pretty but when Microsoft developed the first versions of WMI they use DCOM (Distributed Component Object Model) wish if a proprietary  Microsoft Technology, so the standards and cross compatibility just took a back seat at the time, on more recent versions of the operating system with Windows Management Framework 2.0 and above MS started to include more and more of the standards and shifter to using WS-Management SOAP-based protocol thru their WinRM (Windows Remote Management) protocol.

We can look at WMI as a collection of objects that provide access to different parts of the operating system, just like with PowerShell objects we have properties, methods and events for each. Each of these objects are defined by what is called MOF  (Manage Object Format) files that are saved in %windir%\System32\wbem with the extension of .mof. The MOF files get loaded by what is called a Provider, when the Provider is registered he loads the definitions of the objects in to the current WMI Namespace. The Namespace can be seen a file system structure that organizes the objects on function, inside of each namespace the objects are just like in PowerShell in what is called Class Instances and each of this is populated with the OS and Application information as the system runs so we always have the latest information in this classes.

Namespaces are organize in a hierarchical way where \root is the top level for all other namespaces. The default namespace where most of the other namespaces and classes are located is root\CIMv2 on Windows Kernel 6.x on Kernel 5.x it is Default\CIMv2. Some are installed by default and others are only available when specific applications are installed.
In summary each Namespace contains Classes, these have:

  • Methods Actions that can be taken.
  • Properties Information that can be retrieved.
  • Instances Instances of the class objects (services, Processes, Disks) each instance with Methods and Properties.
  • Events are actions that WMI can monitor for and take action when they happen.

Caveats of WMI

Now WMI is great, do not get me wrong, but sadly it does have some caveats the main ones being:

  • Not all classes are available on all versions of Windows. Check
  • Some applications even from MS have Providers in one version and not in another (Office) and in some cases they even change the properties and methods.

In other words if you plan on running WMI queries against a series of hosts that may be of different versions of Windows or a specific application do make sure you test and validate your results. This goes the same for Architecture if you are testing x64 or x86.

Exploring WMI with a GUI

There are currently several GUI tools out there that can be use to explorer WMI so once can decide what class, instance (object) or event one wants to work with. For many administrators one of the favorite tools to explore WMI has been the standalone WMIExplorer.exe from SAPIENs http://www.sapien.com

image
Microsoft updated to 1.1 their WMI Administrative Tools http://www.microsoft.com/en-us/download/details.aspx?id=24045

image
Microsofts Scripting Guy WMIExplorer.ps1 http://gallery.technet.microsoft.com/scriptcenter/89c759b7-20b4-49e8-98a8-3c8fbdb2dd69

image
All tools provide a GUI way to explorer WMI but they tend to have some issues in common:

  • They tend to be slow since they parse all classes and namespaces when exploring
  • Filtering for information is not the best.

Each tool has it’s advantages and disadvantages my to favorites that I keep using time and time again is the Scripting Guy WMIExplorer.ps1 and the one from Sapiens, the Sapies the main differences is that that one is a binary and the other is in PowerShell, also the PowerShell one allow me to see help information about the class that the Sapiens tool does not, in the Sapiens tool I have to go to MSDN and read the WMI reference documentation http://msdn.microsoft.com/en-us/library/windows/desktop/aa394582(v=vs.85).aspx

Since this will be a series on using WMI in PowerShell I recommend you go with the PowerShell one first. To get up and running with it we start by selecting the code for the script and saving it as WMIExplorer.ps1

image

Since this is a script and more than likely we do not have a code signing certificate to sign it we must change out execution policy to allow the running of locally created scripts. We do this using the Set-ExecutionPolicy cmdlet from a PowerShell session that is running as Administrator.  The command would be:

Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser -Force 

In the example command above I’m setting it only for the current user (No need to allow other accounts to run scripts without signing) and I give it the parameter of force so as to execute it without letting the system ask me if I’m sure I want to enable it.

Once saved and the policy has been set we can execute the script from a console or from ISE, I recommend that you run it as a background job so it will not lock your current session this is done using the Start-Job cmdlet:

Start-Job -FilePath .\WMIExplorer.ps1

When the job is created you should be greeted by the following screen after a couple of seconds:

image

Do make sure you click on connect so it will start populating the information. When a class is selected detailed information about the class is populated so as to make it easier to identify what piece of information we want depending on what we want to do with class or instance of the class, the Help section will contain the information about the class and the definitions of the properties so as to know what each of those return.

image

When we select a method of the class you will be able to see what information the method provides and even see examples of use of the method.

image

You will notice that there are several classes available that we can pull information from, many of these start either with CIM or Win32 and have the same name at the end. The difference between these classes is that one uses the Common Information Model schema and the Win32 classes are called Win32 Enhanced classes, in other words they leverage the Win32 API for information, My personal recommendation when you see both use the Win32 one.

PowerShell uses WMI under hood quite a bit for many of it’s cmdlets. One good example is the Get-Hotfix cmdlet, if we look at the type we can see that it is returning a WMI object:

image

As we can see in the TypeName it is referencing System.Management.ManagementObject (same as WMI in .Net) and it is in the NameSpace root\cimv2 and the class name is win32_QuickFixEngineering if we do a query using the Get-WMIobject cmdlet we would get the same type:

image

On the net blogpost in the series we will go into how to navigate WMI with both the WMI and CIM cmdlets.

As always I hope you have found this information useful.

PowerShell Basics–Objects and the Pipeline

By now you would have noticed if you have been reading my other posts where I use PowerShell that it is not your typical Shell and that it behaves in a unique way when it comes to the output generated by the commands we issue in it, this is because PowerShell is an Object based Shell, this means that everything is an object. Those that have programed in Perl, Ruby, Python, C# or any other Objects based language know very well the power of objects, for those that come from a Bash, cmd.exe or any other regular text based shell you will notice that in PowerShell is a lot simpler to parse and use data, typically on one of this shells we are searching for strings, extracting the strings of text that we need and then piping them to something else, this can be very labor intensive. Lets start by defining what an Object is simple terms, an object is Data and it has 2 types of components:

  • Properties – Information we can retrieve and/or set by name.
  • Method – something we can have happen to the data, it can take arguments to determine what to do or to provide additional information.
To better illustrate Objects and the advantages if offers versus a text based shell lets look at how it is used in PowerShell and why it is one of the foundations for it. Lets look at services. To get a list of services on the system we just do a Get-Service and we get the output, now lets dissect that output: image Man time PowerShell will show the output in a table format or in a list format, looking at a table format like the one above we can see each service is represented individually (as rows) and some information of each is shown (as columns). when we look at this each column represents a property and each row an individual object. But wait we know there has to be more to an service than this, right? well yes. PowerShell uses what is known as Format views for certain types of object so as to show what the creator of the cmdlet considers to be the most common pieces of information for use. To look at the Object be it from a command, cmdlet, function workflow ..etc the most common method is to pipe it to the Get-Member cmdlet to get a view
Get-Service | Get-Member

This will produce a list of:


  • Properties – Information about the object.
  • Methods – Things we can do to the objects.
  • ScriptMethods – Pieces of embedded code that will execute when called.
  • Events – Things that happen to an object we can subscribe to be notified when they happen.

It will also tell us what is the .Net Object Class it is being returned.

image

While using this you may noticed that for some outputs of commands you will see more than one Object Class, Get-Member is smart enough to only show the info for the unique classes that are returned. Lets look at the information we can get from a single object, for the example I will use the BITS service so as to not break my machine.  Lets start by saving it in to a variable so it is easier to manipulate. Variables in PowerShell are maded with a $ in the front just like in Perl .

$BITSSrv = Get-Service -Name BITS

Now lets start with the fun part, the methods. To see what we can do with the object we use the Get-Member cmdlet but specify that we want only the methods shown:

PS C:\> $BITSSrv | Get-Member -MemberType Method


TypeName: System.ServiceProcess.ServiceController

Name MemberType Definition
---- ---------- ----------
Close Method void Close()
Continue Method void Continue()
CreateObjRef Method System.Runtime.Remoting.ObjRef CreateObjRef(type reque...
Dispose Method void Dispose(), void IDisposable.Dispose()
Equals Method bool Equals(System.Object obj)
ExecuteCommand Method void ExecuteCommand(int command)
GetHashCode Method int GetHashCode()
GetLifetimeService Method System.Object GetLifetimeService()
GetType Method type GetType()
InitializeLifetimeService Method System.Object InitializeLifetimeService()
Pause Method void Pause()
Refresh Method void Refresh()
Start Method void Start(), void Start(string[] args)
Stop Method void Stop()
WaitForStatus Method void WaitForStatus(System.ServiceProcess.ServiceContro...

As we can see there are several actions we can take against the service object, we can start, stop, pause, refresh (The object is only the state of what it represents at the given time we retrieved it). Wehn we look at the definitions we can see it shows us that some methods like Pause and Refresh do not take any arguments and others like Start can be called in several ways in some without us giving it arguments in others it tells us the type of class the method will take. Some can be deduce quite easily others we have to look in the MSDN Website for the class information (ServiceController Class)  do the way output is formatted we may loose some of the info we may need. for this we can use one of the Format Cmdlets to make it wrap the line so we can have a better look.

PS C:\> $BITSSrv | Get-Member -MemberType Method | Format-Table -Wrap


TypeName: System.ServiceProcess.ServiceController

Name MemberType Definition
---- ---------- ----------
Close Method void Close()
Continue Method void Continue()
CreateObjRef Method System.Runtime.Remoting.ObjRef CreateObjRef(type
requestedType)
Dispose Method void Dispose(), void IDisposable.Dispose()
Equals Method bool Equals(System.Object obj)
ExecuteCommand Method void ExecuteCommand(int command)
GetHashCode Method int GetHashCode()
GetLifetimeService Method System.Object GetLifetimeService()
GetType Method type GetType()
InitializeLifetimeService Method System.Object InitializeLifetimeService()
Pause Method void Pause()
Refresh Method void Refresh()
Start Method void Start(), void Start(string[] args)
Stop Method void Stop()
WaitForStatus Method void WaitForStatus(System.ServiceProcess.ServiceControlle
rStatus desiredStatus), void WaitForStatus(System.Service
Process.ServiceControllerStatus desiredStatus, timespan
timeout)

Lets stop the service:

PS C:\> $BITSSrv.Stop()

PS C:\> $BITSSrv.Status
Running

PS C:\> $BITSSrv.Refresh()

PS C:\> $BITSSrv.Status
Stopped

As it can be seen I forgot that when the object is in a variable it is just a representation at the moment it was saved. Let look at Parenthetical execution go get around this, when we wrap the command around ( ) we can use the properties and methods of the object it returns directly. 

PS C:\> (Get-Service -Name BITS).Start()

PS C:\> (Get-Service -Name BITS).Status
Running

Now since we are poling the information on each command we get the latest information.  You can notice from the examples that Properties do not require ( ) at the end of invocation and Methods do, just something to keep in mind, in fact using tab completion or the ISE it will remind you.

Let look at the properties:

PS C:\> Get-Service -Name BITS | Get-Member -MemberType Property


TypeName: System.ServiceProcess.ServiceController

Name MemberType Definition
---- ---------- ----------
CanPauseAndContinue Property bool CanPauseAndContinue {get;}
CanShutdown Property bool CanShutdown {get;}
CanStop Property bool CanStop {get;}
Container Property System.ComponentModel.IContainer Container {get;}
DependentServices Property System.ServiceProcess.ServiceController[] DependentServices ...
DisplayName Property string DisplayName {get;set;}
MachineName Property string MachineName {get;set;}
ServiceHandle Property System.Runtime.InteropServices.SafeHandle ServiceHandle {get;}
ServiceName Property string ServiceName {get;set;}
ServicesDependedOn Property System.ServiceProcess.ServiceController[] ServicesDependedOn...
ServiceType Property System.ServiceProcess.ServiceType ServiceType {get;}
Site Property System.ComponentModel.ISite Site {get;set;}
Status Property System.ServiceProcess.ServiceControllerStatus Status {get;}

You will notice that some of the properties have in the end {get;set} or only {get;} this means we can assign a value to the property of the same type as it is listed in the definition. Since PowerShell will only list some of the properties depending on the formatting it has defined. Do take in to account this is only for the instance of the object, we would not be changing the service it self but the representation we may have in a variable. To change the service itself it would have to be thru a Method.

The formatting of what is displayed is shown following the guidelines shown in the format.pmxml file for each type in the Windows PowerShell folder, for the service it would be in C:\Windows\System32\WindowsPowerShell\v1.0 since the view is sometimes limited and we want to do a quick browse of all that is in the properties we can use the formatting cmdlets to exposed all, I tend to use the Format-List cmdlet:

PS C:\> Get-Service -Name BITS | Format-List -Property *


Name : BITS
RequiredServices : {RpcSs, EventSystem}
CanPauseAndContinue : False
CanShutdown : False
CanStop : True
DisplayName : Background Intelligent Transfer Service
DependentServices : {}
MachineName : .
ServiceName : BITS
ServicesDependedOn : {RpcSs, EventSystem}
ServiceHandle : SafeServiceHandle
Status : Running
ServiceType : Win32ShareProcess
Site :
Container :

PipeLine

By now you would have noticed in this blogpost and others that the pipeline is used quite a bit in PowerShell. The typical pipeline in other shells will move the standard out of a command to the standard input of another:

image

In the case of PowerShell we are moving objects so there are 2 ways a cmdlet can receive commands from the pipeline:


  1. By Value – this is where the output of a cmdlet must be the same type as what the –InputObject parameter of another takes:
  2. By Property Name – This is when the object has a property that matched the name of a parameter in the other.

So by Value would be:

image

And when we look at the parameters in help we can identify them by looking of they accept from the pipeline and how:

image

 

By Property it would be:

 

image

 

and when we look at the help information for the parameter it would look like:

image

The examples above are from the Service cmdlets so we could just pipe the Get-Service cmdlet any of the other cmdlets for managing services:

PS C:\> gcm *service* -Module  Microsoft.PowerShell.Management

CommandType Name ModuleName
----------- ---- ----------
Cmdlet Get-Service Microsoft.PowerShell.Man...
Cmdlet New-Service Microsoft.PowerShell.Man...
Cmdlet New-WebServiceProxy Microsoft.PowerShell.Man...
Cmdlet Restart-Service Microsoft.PowerShell.Man...
Cmdlet Resume-Service Microsoft.PowerShell.Man...
Cmdlet Set-Service Microsoft.PowerShell.Man...
Cmdlet Start-Service Microsoft.PowerShell.Man...
Cmdlet Stop-Service Microsoft.PowerShell.Man...
Cmdlet Suspend-Service Microsoft.PowerShell.Man...

So this would allow us to do:

PS C:\> Get-Service -Name BITS | Stop-Service

PS C:\> (Get-Service -Name BITS).Status
Stopped

PS C:\> Get-Service -Name BITS | Start-Service

PS C:\> (Get-Service -Name BITS).Status
Running


I hope that you found this blog post in the series useful and on the next one we will cover how to filter and process the Objects generated so we can glue even more types of cmdlets together.