This is the third post of a three part series in which we explore the world of svchost.exe. In part 1, I introduced the topic of the multiple svchost.exe instances running on Microsoft operating systems; their implied usage; as well as why it is something we should learn more about. In part 2, I went into more depth about how the operating system  makes use of this Host Process for its needs. In part 3, I present you with a Powershell script which can be used to better understand what is running on your system as well as investigate and discover potential malware which can be hiding behind this innocent-looking process on your own machines.

Powershell:

  • Version 1.0
  • If this is your first time with Powershell, it’s best to ensure that you have the PowerShell scripting engine installed on your system, as well as enabling the rights to run Powershell scripts on your system by using the command “Set-ExecutionPolicy RemoteSigned” from within the powershell prompt.

  • To run script:
  1. Save the script below to a file named “c:\myFiles\CheckSvc.ps1” .
  2. Open the command prompt with administrator rights: Start > Programs > Accessories > Right click on “Command Prompt” and select “Run as Administrator”.
  3. Start Powershell by typing “Powershell”.
  4. Run the script by typing “c:\myFiles\CheckSvc.ps1”

This is what the script outputs:

  • Directly enumerates and checks out all of the processes which have their process name ‘svchost.exe’.
  • Get a clear view about how many such processes are running on your system and get a feeling of what is normal on your system when run over different days.
  • For each of those processes, it checks if there are any services running under that instance. If there are, it extracts from them:
  1. How many services are running under that svchost.exe instance.
  2. The service group (as described in part 2) running under that svchost.exe instance.
  3. The service names and descriptions (as described in part 1 and part 2) of the services running under that svchost.exe instance.  

  • In cases where something out of the norm is detected such as a malformed command line initiator or no service running under that process a warning is displaced clearly to you. 

I hope that this three part series has been able to provide you with more visibility into the under wirings of those normally unknown processes which come up under your process explorer views via task manager or other tools, as well as their usage and meanings.

You can also customize this script to your needs. I only ask you keep me posted on your updates as for me to learn from them too by emailing me on andre@gfi.com.

You can download the script here.

 

$FgText1 = "DarkGreen"
$FgText2 = "DarkGray"
$FgError="Red"

Write-Host("==============================================================================") -foreground $FgText1;
Write-Host("SvcHost Explorer...") -foreground $FgText1;
Write-Host("==============================================================================") -foreground $FgText1;
Write-Host("");
$ProcessToCheckFor = "'svchost.exe'";
$TotalProcessesCount = 0;
$TotalServicesCount = 0;

# Create a list of process handles which are running on the system
$PidList = @(Get-WmiObject win32_process -Filter "name=$ProcessToCheckFor");
$TotalProcessesCount = $PidList.length;

$PidHandleList = $PidList | Foreach-Object { $_.Handle };

Write-Host("Total {0} Processes Count: {1}" -f $ProcessToCheckFor, $TotalProcessesCount) -foreground $FgText1;

Write-Host("------------------------------------------------------------------------------") -foreground $FgText1;
Write-Host("");
$CurrentPos = 0;

# For every process detected, check which windows services are running under
# that process
foreach ($procid in $PidHandleList){
$CurrentPos +=1;
$ServicesUnderThisPID = @(Get-WmiObject win32_service -Filter "processID = $procid");

if($ServicesUnderThisPID.length -gt 0){
$ShowHeader = $True;
$PossibleMalware = $False;

$ProcGroup = "";

# For every windows service, break down the command triggered to ensure of
# proper format
# Typical format: C:\Windows\system32\svchost.exe -k netsvcs

foreach($serv in $ServicesUnderThisPID){
if($ProcGroup -eq("")){
$ProcGroup = $serv.PathName;
$CommandComponents = @($ProcGroup.Split(" "));
if ($CommandComponents.length -eq 3 ){
$ProcGroup = $CommandComponents[2];
}
else{
$ProcGroup = "WARNING: POSSIBLE MALWARE - NON STANDARD RUN COMMAND DETECTED";
$PossibleMalware = $True;
}
}

if($ShowHeader){
if($PossibleMalware){
Write-Host("{0}" -f $ProcGroup);
}
else {
Write-Host("Process {0,2} - (Process ID: {1}) - (Services running under this process: {2})" -f $CurrentPos, $procid, $ServicesUnderThisPID.length) -foreground $FgText1;
Write-Host(" (Group {0})" -f $ProcGroup) -foreground $FgText1;
}
$ShowHeader = $False;
}

Write-Host(" {0}" -f $Serv.Name);
Write-Host(" {0}" -f $Serv.DisplayName) -foreground $FgText2;

$DescriptionProc = $Serv.Description;
$DescriptionProc = @($DescriptionProc.Split(" "));
$TempStr = " ";
foreach($word in $DescriptionProc){
if ($TempStr.length -lt 67){
$TempStr += $Word + " ";
}
else{
Write-Host( "{0}" -f $TempStr) -foreground $FgText2;
$TempStr = " ";
}
}
}
}
else {
Write-Host("WARNING: POTENTIAL MALWARE: NO WINDOWS SERVICE DETECTED") -foreground $FgError;
Write-Host(" AS RUNNING UNDER THIS PROCESS. CAN BE A MALWARE RUNNING") -foreground $FgError;
Write-Host(" UNDER THE NAME {0} TO DISGUISE ITSELF" -f $ProcessToCheckFor) -foreground $FgError;
}
" ";
$TotalServicesCount += $ServicesUnderThisPID.length;
}

Write-Host("------------------------------------------------------------------------------") -foreground $FgText1;
Write-Host("Summary:") -foreground $FgText1;
Write-Host("------------------------------------------------------------------------------") -foreground $FgText1;
Write-Host("Total {0} processes counted: {1}" -f $ProcessToCheckFor, $PidList.length) -foreground $FgText1;
Write-Host("Total services running under these processes: {0}" -f $TotalServicesCount) -foreground $FgText1;
Write-Host("==============================================================================") -foreground $FgText1;
Write-Host("");
Write-Host("");