SEC504: Hacker Tools, Techniques, and Incident Handling

Experience SANS training through course previews.
Learn MoreLet us help.
Contact usConnect, learn, and share with other cybersecurity professionals
Engage, challenge, and network with fellow CISOs in this exclusive community of security leaders
Become a member for instant access to our free resources.
Sign UpMission-focused cybersecurity training for government, defense, and education
Explore industry-specific programming and customized training solutions
Sponsor a SANS event or research paper
We're here to help.
Contact UsSomething I always have to look up are commands for object properties. Fortunately, PowerShell makes this pretty easy. Let's take a look.
As I learn PowerShell, I quickly get overwhelmed with the number of commands available. I try to anticipate the Verb/Noun syntax, and command completion helps a lot.
I can rattle off PowerShell commands for lots of things, but something I always have to look up are the object properties. Fortunately, PowerShell makes this pretty easy. Let me explain by posing a question:
What are the dependent services for the Windows EventLog service?
The first part of this is pretty easy: [code]Get-Service[/code] will enumerate the services. We can specify the service name as an unnamed argument, or following [code]-Name[/code]:
PS C:\WINDOWS\system32> Get-Service eventlog
Status Name DisplayName
------ ---- -----------
Running eventlog Windows Event Log
PS C:\WINDOWS\system32> Get-Service -Name EventLog
Status Name DisplayName
------ ---- -----------
Running EventLog Windows Event Log
In PowerShell, the pipeline allows us to process the objects that are returned from the command. If objects seems vague, it's intentionally so: objects can be properties, code, scripts, alias, events, and more. Often, we're interested in the properties, displayed as columns of information.
To identify the available properties, we have some options. The first is to send the output of [code]Get-Service[/code] to [code]Get-Member[/code]:
PS C:\WINDOWS\system32> Get-Service | Get-Member
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 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.ServiceControllerStatus desiredSt...
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 {get;}
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 {get;}
ServiceType Property System.ServiceProcess.ServiceType ServiceType {get;}
Site Property System.ComponentModel.ISite Site {get;set;}
StartType Property System.ServiceProcess.ServiceStartMode StartType {get;}
Status Property System.ServiceProcess.ServiceControllerStatus Status {get;}
ToString ScriptMethod System.Object ToString();
This is a lot of output, and for our purposes we are mostly interested in properties, so we can refine our pipeline adding [code]-MemberType Property[/code]:
PS C:\WINDOWS\system32> Get-Service | 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 {get;}
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 {get;}
ServiceType Property System.ServiceProcess.ServiceType ServiceType {get;}
Site Property System.ComponentModel.ISite Site {get;set;}
StartType Property System.ServiceProcess.ServiceStartMode StartType {get;}
Status Property System.ServiceProcess.ServiceControllerStatus Status {get;}
In this output we see all of the properties available in the object sent to the pipeline from [code]Get-Service[/code]. This is useful, but the definition column doesn't always offer intuitive insight. Our second option is to use [code]Select-Object[/code] instead:
PS C:\WINDOWS\system32> Get-Service | Select-Object -First 1 -Property *
Name : AarSvc_23e54
RequiredServices : {}
CanPauseAndContinue : False
CanShutdown : False
CanStop : True
DisplayName : AarSvc_23e54
DependentServices : {}
MachineName : .
ServiceName : AarSvc_23e54
ServicesDependedOn : {}
ServiceHandle : SafeServiceHandle
Status : Running
ServiceType : 240
StartType : Manual
Site :
Container :
We see the same property names, but sometimes seeing the property name in the context of a sample value can be more useful than the [code]Get-Member[/code] output.
Note: Using [code]-First 1[/code] in the [code]Select-Object[/code] command limits the output to just a single property list; omitting [code]-First 1[/code] would return the properties for all objects, which may be more than you really want to read though.
In the output of [code]Get-Member[/code] and [code]Select-Object[/code], we see the property [code]DependentServices[/code]. Let's take a look for the [code]EventLog[/code] service:
PS C:\WINDOWS\system32> Get-Service EventLog | Select-Object -Property DependentServices
DependentServices
-----------------
{Wecsvc, uhssvc, NcdAutoSetup, AppVClient...}
Fantastic! We have the list of dependent services for EventLog. However, Notice the ellipsis at the end of the dependent services list, and the curly braces surrounding the values? This indicates that the output is an object that is truncated.
To get the complete list, we have to backtrack a bit. When we use the [code]Select-Object[/code] cmdlet in a pipeline, it will change the output object to a custom [[code]PSObject[/code]](https://msdn.microsoft.com/en-us/library/system.management.automation.psobject%28v=vs.85%29.aspx) class. That is, it's a wrapper that provides alternate ways of viewing the available member objects. Instead of working with the [code]Select-Object[/code] output, we can return right to [code]Get-Service[/code], declaring the output as a variable:
PS C:\WINDOWS\system32> $eventlogsvc = Get-Service EventLog
PS C:\WINDOWS\system32>
With the variable [code]$eventlogsvc[/code], we can access the member object [code]DependentServices[/code] using dot notation:
PS C:\WINDOWS\system32> $eventlogsvc.DependentServices
Status Name DisplayName
------ ---- -----------
Stopped Wecsvc Windows Event Collector
Running uhssvc Microsoft Update Health Service
Stopped NcdAutoSetup Network Connected Devices Auto-Setup
Stopped AppVClient Microsoft App-V Client
Running netprofm Network List Service
Running NlaSvc Network Location Awareness
To get the complete list of dependent service names, we can use [code]Select-Object[/code] again to access just the [code]Name[/code] property:
PS C:\WINDOWS\system32> $eventlogsvc.DependentServices | Select-Object -Property Name
Name
----
Wecsvc
uhssvc
NcdAutoSetup
AppVClient
netprofm
NlaSvc
PowerShell purists will point out that declaring a variable is not necessary, since you can enclose the [code]Get-Service[/code] command in parenthesis to accomplish the same goal: [code](Get-Service EventLog).DependentServices | Select-Object -Property name[/code]. While this is true, I think declaring the [code]$eventlogsvc[/code] is worth the memory required for the enhanced legibility. YMMV.
PowerShell often feels like a safe form of what I imagine spelunking is like. There's lots of twists and turns, and sometimes you have to backtrack quite a bit, but eventually you find your way, or you give up trying.
-Joshua Wright
Return to Getting Started With PowerShell
Joshua Wright is the author of SANS SEC504: Hacker Tools, Techniques, and Incident Handling, a faculty fellow for the SANS Institute, and a senior technical director at Counter Hack.
As Senior Technical Director at Counter Hack and SANS Faculty Fellow, Joshua has advanced cybersecurity through ethical penetration testing, uncovering critical vulnerabilities across Fortune 500 companies and national infrastructure providers.
Read more about Joshua Wright