Expert Solution for 2011 Scripting Games Advanced Event 4: Use PowerShell to Find Services Hiding in the SvcHost Process

Expert Solution for 2011 Scripting Games Advanced Event 4: Use PowerShell to Find Services Hiding in the SvcHost Process

  • Comments 5
  • Likes

Summary: Microsoft research software developer, Chris O'Prey, solves Windows PowerShell 2011 Scripting Games Advanced Event 4 and finds services that are running in the SvcHost process.

Microsoft Scripting Guy, Ed Wilson, here. With us today with his solution to the Windows PowerShell 2011 Scripting Games Advanced Event 4 is Chris O’Prey. Chris tells us about himself then and continues with his solution.

adv4-1

I've been a professional developer and tester since 1995, working mainly in the web development and research fields and using a plethora of different operating systems and programming languages. Currently, I'm working for Microsoft Research in Cambridge, UK as a senior development engineer in test, and I am working on leading edge research and development projects. I've been using Windows PowerShell on a daily basis since the early days of version 1.

Worked solution

The basic requirements from the team lead are as follows:

  • Show all SvcHost processes with committed memory, page fault count, and command line
  • Show all services running inside each SvcHost process
  • Use a single server only
  • Provide reusable code
  • Produce a written report
  • Return objects instead of string or table data

Although Windows PowerShell contains its own implementation of the Get-Process and Get-Service cmdlets, in this case we require information that is not easily obtained from the resulting objects from these cmdlets. Therefore, the better option will be to rely on the Get-WmiObject cmdlet, which returns further information of use.

To ensure a fast response (because WMI can be slow), the filtering should begin by only selecting the SvcHost processes. In WMI, these are identified readily by selecting the entries with the name svchost.exe. Using the filter parameter on the Get-WmiObject cmdlet allows us to do this easily and also speeds up the return of data because we no longer have to filter in Windows PowerShell. Note that we make a copy of the current entry in the pipeline ($_) into a local variable ($process) because we intend to use this in the next pipeline level.

For each of the returned process objects, we can make a second WMI call to get the services filtered by the Process ID, which will provide the services running in this particular instance of the SvcHost process.

We would prefer to return objects. To this end we can use the intrinsic PSObject type, and use the Property parameter on the New-Object cmdlet to allow us to easily splat all the required properties from both the Process and Service WMI objects into a single PSObject. By explicitly not assigning the return of this cmdlet, it will automatically become part of the script output.

One of the requirements was the ability to provide a written report. We have a nice object set, so we can rely on the ConverTo-HTML cmdlet to do this automatically, and the Out-File cmdlet to write it to the current folder. A nice feature was to use the “&” operator to also automatically display the resulting HTML file in the active browser. By adding an OutHMTL switch parameter we can make this script reusable without impacting the ability to provide this report.

For instant use, an OutGrid switch parameter was also added, which takes the output data and shows it using the Out-GridView cmdlet.

Finally, although there was no explicit requirement for multiple computer support, a Computers parameter was provided, defaulting to the current machine, to allow the code to be reusable and access machines other than the current one.

The complete script is shown here. 

<#

 .Synopsis

  Provide a report on all SvcHost processes and embedded services.

 

 .Description

  Gets the details on all services running inside of SvcHost processes along with memory

  consumption, page faults and command lines.

 

 .Parameter computer

  The machine to test. Defaults to the current machine.

 

 .Parameter outHTML

  A switch. Will return a HTML formatted output of the process & service details.

 

 .Parameter outGrid

  A switch. Will return a GridView formatted output of the process & service details.

 

 .INPUTS

  None. You cannot pipe objects to Invoke-Task.

 

 .OUTPUTS

  A collection of PSObjects containing the details of each service.

 

 .Example

   Get-ServiceDetails

   Gets the details for the current machine as a PSObject collection.

 

 .Example

   Get-ServiceDetails "SERVER-001"

   Gets the details for the given machine as a PSObject collection.

 

 .Example

   Get-ServiceDetails -outHTML

   Gets the details for the current machine as a PSObject collection and also displays the details in

   the current browser as an HTML formatted file. This file is also persisted to the current folder.

 

 .Example

   Get-ServiceDetails -outGrid

   Gets the details for the current machine as a PSObject collection and also displays the details in

   a GridView.

#>

 

param (

    [string]$computer = ".",

    [switch]$outHTML,

    [switch]$outGrid

)

 

$results = (Get-WmiObject -Class Win32_Process -ComputerName $computer -Filter "Name='svchost.exe'" | % {

    $process = $_

    Get-WmiObject -Class Win32_Service -ComputerName $computer -Filter "ProcessId=$($_.ProcessId)" | % {

        New-Object PSObject -Property @{ProcessId=$process.ProcessId;

                                        CommittedMemory=$process.WS;

                                        PageFaults=$process.PageFaults;

                                        CommandLine=$_.PathName;

                                        ServiceName=$_.Name;

                                        State=$_.State;

                                        DisplayName=$_.DisplayName;

                                        StartMode=$_.StartMode}

    }

})

 

if ($outHTML)

{

    $results | ConvertTo-Html | Out-File ".\temp.html"

    & .\temp.html

}

 

if ($outGrid)

{

    $results | Out-GridView

}

 

$results

Thanks, Chris, for writing this solution to Advanced Event 4.

I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy

Your comment has been posted.   Close
Thank you, your comment requires moderation so it may take a while to appear.   Close
Leave a Comment
  • A very good, short and precise solution that can be well understood!

    Bur ... my famous last words: There is no error handling at all!

    kind regards,

    Klaus (Schulte)

  • Trying to ask a question or two on all I submit, or write and fail to look at a calendar.  I was proud of this one I wrote but didn't turn it in on time.  I had it look at all the svchosts running and pulled the ProcessIDs.  Then I went through all the services running and got the ones whose pathname contained svchost.exe and sorted/grouped by ProcessId on those.  This was the only way I could think of to get the services running under the svchost process.  I was getting hung up on the fact that on my machine that does not have admin rights running the query to get the commandline path for a service was null.  Permissions issue; fine.  My down and dirty way to check for permissions was to see if the commandline path value was being returned null.  If it was, not a local admin.  What's the proper way to check for local admin rights on things like this?

  • How about adding the localport to the list?

  • if the local port used and whether it was TCP /UDP was added it would be perfect....

  • thank you