Skip to main content

Use PowerShell to Look for Viruses

I’m sitting in the USO at the San Jose airport this evening waiting on a flight back home.  A good friend and Shipmate of mine contacted me with a bit of a virus issue.  He needed a way to scan all of his clients for this bad bug.  He unfortunately did not have access to his organizations central antivirus system.
After a bit of online research, I found what I was looking for.  Either files or registry keys that would mark a potential infection.  I wrote up some code and sent it over to him.  Yes, I could have wrote code very quickly that focused only the little critter running around his network, but what fun would that be.  This code is reusable.
The cmdlet is Search-VirusSignature.  I included a help file to show you how to use it.  It does require access to the Active Directory module and also for all of your clients to have PowerShell Remoting turned on.
Happy Hunting!
Function Search-VirusSignature
{
[cmdletbinding()]
Param(
    [String[]]$RegKey = $Null,
    [String[]]$Files
)

    Function New-ScriptObject
    {
        # Empty VirusSignatureObject
        $Obj = New-Object -TypeName PSObject -Property @{
            'ComputerName' = $Null;
            'Online' = $False;
            'RegValueMatch' = $False;
            'FileValueMatch' = $False;
            'PSSessionAvailable' = $True
        }
        $Obj.PSObject.Typenames.insert(0,"VirusSignatureObject")

        Write-Output $Obj
    } # End: Function New-ScriptObject

    Function Search-RegValue
    {
    Param (
        [String[]]$RegKey,
        [String]$C,
        $Session)

        # Initialize the memory to be used in this function.
        $Found = $False
        $PSPro = $Null
        $OutResult = $False

        # Cycle through each provided registry key.
        ForEach ($R in $RegKey)
        {
            # Discover the key being used.  Since documentation can
            # list the PSDrive value differently, convert the
            # provided drive name to one that PowerShell will
            # recognize.
            Switch -Wildcard ($R)
            {
                "HKEY_CURRENT_USER*" {$PSPro = "HKCU"
                                      $Key = $R.Replace("HKEY_CURRENT_USER","")}
                "HKCU*" {$PSPro = "HKCU"
                         $Key = $R.Replace("HKCU","")}
                "HKEY_LOCAL_MACHINE*" {$PSPro = "HKLM"
                                       $Key = $R.Replace("HKEY_LOCAL_MACHINE","")}
                "HKLM*" {$PSPro = "HKLM"
                         $Key = $R.Replace("HKLM","")}
            }
           

            # Determine if this key is present.
            $Result = $False
            $Result = Invoke-Command -ScriptBlock {Param ($PSPro, $Key) Test-path -Path "$($PSPro):$($Key)"} `
                -Session $Session `
                -ArgumentList $PSPro, $Key
           
            If ($Result -eq $True {$OutResult = $True}
        }
        Write-Output $OutResult

    } # End: Function Search-RegValue

    Function Search-File
    {
    Param ([String[]]$Files,
           [String]$C,
           $Session)
       
        # Initialize the memory to be used in this function.
        $Found = $False
        $PSPro = $Null
        $OutResult = $False

        ForEach ($F in $Files)
        {

            # Determine if this file is present.
            $Result = $False
            $Result = Invoke-Command -ScriptBlock {Param ($F) Test-path -Path "$($F)"} `
                -Session $Session `
                -ArgumentList $F
           
            If ($Result -eq $True {$OutResult = $True}
        }
        Write-Output $OutResult

    } # End: Search-File


    # For PowerShell V2 Compatibility
    Import-Module ActiveDirectory

    ForEach ($C in (Get-ADComputer -Filter * | Select-Object -ExpandProperty Name))
    {
        #Create the object for this instance.
        $Obj = New-ScriptObject

        # Write the name of the client for this instance.
        $Obj.ComputerName = $C

        # Test for online
        $Obj.Online = Test-Connection -ComputerName $C -Count 1 -Quiet
   
        If ($Obj.Online -eq $True)
        {
            # Establish a PSSession to the client.
            Try
            {
                $Session = New-PSSession -ComputerName $C -ErrorAction Stop
            }
            Catch
            {
                $Obj.PSSessionAvailable = $False
            }

            If ($Obj.PSSessionAvailable -eq $True)
            {
                # Search for a matching registry value.
                If ($RegKey -ne $NUll)
                    {
                         $Obj.RegValueMatch = Search-RegValue -RegKey $RegKey `
                                                                -c $Obj.ComputerName `
                                                                -Session $Session
                    }
           
                # Search for a matching file.
                If ($Files -ne $NUll)
                    {$Obj.FileValueMatch = Search-File -Files $Files `
                                                       -C $Obj.ComputerName `
                                                       -Session $Session
                    }
                $Session | Remove-PSSession
            } # End: If ($Obj.PSSessionAvailable -eq $True)
        } # End: If ($Obj.Online -eq $True)  

       
        # Send the object to the pipeline
        Write-Output $Obj
    }

<#
.SYNOPSIS
Allows you to scan for potential viruses signatures in your environment.

.DESCRIPTION
Allows you to search for registry keys and files that may signal if a virus is present.

You will have to provide the registry keys and or files to search for.  This script does
not contain any virus signatures.

.PARAMETER RegKey
A comma separated list of all registry keys to search for.  The is a comma separate list
of possible values.  Each value must be contained inside of double quotes.

The following example contains 2 separate registry keys.
"HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Run\aqjunayn", "HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run\aqjunayn"

.PARAMETER Files
A comma separated list of all files to search for.  The is a comma separate list
of possible values.  Each value must be contained inside of double quotes.

The following example contains 2 separate files to be searched for.
"C:\Windows\System32\aqjunayn.exe", "C:\Documents and Settings\user-account-name\aqjunayn.exe"

.EXAMPLE
Search-VirusSignature -RegKey "HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Run\aqjunayn", "HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run\aqjunayn" -Files  "C:\Windows\System32\aqjunayn.exe", "C:\Documents and Settings\user-account-name\aqjunayn.exe"

Searches for 2 potential registry keys and 2 potential files that may signal a particular virus.

.NOTES
Script requirements:
- Active Directory Module for Windows PowerShell.
    You can get access to the Active Directory Module for Windows PowerShell
    by downloading and installing the Remote Server Administrator tools from
    Microsoft or running this script on a Domain Controller

- PowerShell Remoting turned on on all clients.
    PowerShell remoting is turned on for all domain joined Windows 8 and
    Windows Server 2012 clients.

    You can enable PowerShell remoting for Windows 7 and Server 2008 R2
    using these instructions:
    http://mctexpert.blogspot.com/2011/03/enable-powershell-v2-remote-management.html

Object Properties Definitions
ComputerName:       The name of the client where contact is being attempted.
Online:             The client's online status  Offline clients will not be
                    contacted.
RegValueMatch:      If True, the a registry value that you have search for
                    was found.
FileValueMatch:     If True, the a file that you have search for was found.
PSSessionAvailable: True represents a successful PSSession establishment.
                    Unsuccessful sessions will not be tested for Reg and file
                    matches.

Only client that return a true value for both Online and PSSessionAvailable
have been tested.

===============================================================================
== Cmdlet: Search-VirusSignature                                             ==
== Module: PSV3                                                              ==
==---------------------------------------------------------------------------==
== Author: Jason A. Yoder                                                    ==
== Company: MCTExpert or Arizona, Inc.                                       ==
== Blog: MCTExpert.Blogspot.com                                              ==
== Twitter: @JasonYoder_MCT                                                  ==
==---------------------------------------------------------------------------==
== License Information:                                                      ==
== Copyright 2013 - MCTExpert, Inc.                                          ==
== This code is licensed for personal use only.  This code may not be        ==
== re published or distributed in whole or in part without the express       ==
== written consent of MCTExpert of Arizona, Inc.  All rights reserved.       ==
==---------------------------------------------------------------------------==
== Disclaimer: The user takes full responsibility for the execution of any   ==
== PowerShell code.  This code is provided without warranty or support.      ==
== As with all PowerShell code, review it and test it in a test environment  ==
== prior to using it in a production environment.  The user takes complete   ==
== responsibility for the results of executing this code.                    ==
===============================================================================


#>

} # End: Search-VirusSignature


Comments

Popular posts from this blog

Adding a Comment to a GPO with PowerShell

As I'm writing this article, I'm also writing a customization for a PowerShell course I'm teaching next week in Phoenix.  This customization deals with Group Policy and PowerShell.  For those of you who attend my classes may already know this, but I sit their and try to ask the questions to myself that others may ask as I present the material.  I finished up my customization a few hours ago and then I realized that I did not add in how to put a comment on a GPO.  This is a feature that many Group Policy Administrators may not be aware of. This past summer I attended a presentation at TechEd on Group Policy.  One organization in the crowd had over 5,000 Group Policies.  In an environment like that, the comment section can be priceless.  I always like to write in the comment section why I created the policy so I know its purpose next week after I've completed 50 other tasks and can't remember what I did 5 minutes ago. In the Group Policy module for PowerShell V3, th

Return duplicate values from a collection with PowerShell

If you have a collection of objects and you want to remove any duplicate items, it is fairly simple. # Create a collection with duplicate values $Set1 = 1 , 1 , 2 , 2 , 3 , 4 , 5 , 6 , 7 , 1 , 2   # Remove the duplicate values. $Set1 | Select-Object -Unique 1 2 3 4 5 6 7 What if you want only the duplicate values and nothing else? # Create a collection with duplicate values $Set1 = 1 , 1 , 2 , 2 , 3 , 4 , 5 , 6 , 7 , 1 , 2   #Create a second collection with duplicate values removed. $Set2 = $Set1 | Select-Object -Unique   # Return only the duplicate values. ( Compare-Object -ReferenceObject $Set2 -DifferenceObject $Set1 ) . InputObject | Select-Object – Unique 1 2 This works with objects as well as numbers.  The first command creates a collection with 2 duplicates of both 1 and 2.   The second command creates another collection with the duplicates filtered out.  The Compare-Object cmdlet will first find items that are diffe

How to list all the AD LDS instances on a server

AD LDS allows you to provide directory services to applications that are free of the confines of Active Directory.  To list all the AD LDS instances on a server, follow this procedure: Log into the server in question Open a command prompt. Type dsdbutil and press Enter Type List Instances and press Enter . You will receive a list of the instance name, both the LDAP and SSL port numbers, the location of the database, and its status.