Quantcast
Viewing all articles
Browse latest Browse all 32

MaxFocus Script to Check for CryptoWall Infection

The CryptoWall ransomware virus is getting a lot of attention lately but this is one angle I haven’t seen covered:  how to get an alert in the MaxFocus (formerly GFI) dashboard if a machine is infected. The sooner you know, the sooner you can work on restoring a current backup.

Here’s a standalone PowerShell script that checks a few file and registry locations for evidence of CryptoWall and raises an error if found.

Note that this does nothing about preventing an infection; it is purely an after-the-fact alert.

Test and use this at your own risk. If you find a bug, or have a suggestion for a file or registry path that is not checked, leave a comment.

Compatibility and Functionality

The script should work on XP/2003 and above, and PowerShell 2 and above. It only works on U.S. English (and possibly other English) locales due to some hard-coded file paths (“Documents” etc.).

The script checks for DECRYPT_INST*.* files in two public folders and in three folders in each user’s profile. It also checks the registry for known CryptoLocker Decrypter keys. See more details in the script code and comments.

Primary references used:

http://www.pcsgo.com/quickly-remove-cryptowall-decrypter-from-your-computer-ransomware-removal-guides/
http://www.virusresearch.org/remove-cryptowall-manually/
http://www.bleepingcomputer.com/virus-removal/cryptowall-ransomware-information

Use in MaxFocus

If you deploy the script to MaxFocus, you should see a quick summary of the results in the dashboard:

Image may be NSFW.
Clik here to view.
CryptoWall Check 1

Hopefully you won’t see this:

Image may be NSFW.
Clik here to view.
CryptoWall Check 2

If you click on the blue text, a window appears with more detail:

Image may be NSFW.
Clik here to view.
CryptoWall Check 3

The Script

Copy and paste this as a PowerShell script (e.g. MCB.CheckCryptoWall.ps1).

<#
.Synopsis
	Check for the existence of some common CryptoWall files and registry keys.
  This is not a comprehensive threat detection engine, and it does NOTHING to
  prevent or block the threat.  It just checks for the presence of decryption 
  instructions in some common folders, and for the presence of some registry
  keys used by the CryptoWall Decrypter.  Hopefully if you find out right away 
  that you have an encrypted machine, you can restore it from a recent backup.
  
  Only handles U.S. (and maybe other English) locales.

	Copyright (c) 2014 by MCB Systems. All rights reserved.
  Free for personal or commerical use.  May not be sold.
  No warranties.  Use at your own risk.

  Can be used with MaxFocus Advanced Monitoring Agent.
  Returns summary line first, followed by list of paths checked.  The
  summary will be visible in the MaxFocus dashboard as a hyperlink.  
  When you click on the hyperlink, the details display in a window.
  Returns exit code 1001 if matching path found.  This will cause the
  MaxFocus check to fail and optionally to send an alert.
  
  References:

http://www.pcsgo.com/quickly-remove-cryptowall-decrypter-from-your-computer-ransomware-removal-guides/


http://www.virusresearch.org/remove-cryptowall-manually/


http://www.bleepingcomputer.com/virus-removal/cryptowall-ransomware-information

.Notes 
    Name:       MCB.CheckCryptoWall.ps1
    Author:     Mark Berry, MCB Systems
	  Created:    11/14/2014
    Last Edit:  11/14/2014
    
	Changes:

.Parameter FilePattern
  Filename to look for in the hard-coded list of paths.  Wildcards allowed.  
  Do not include backslash.
	Default:  "DECRYPT_INST*.*", which covers DECRYPT_INSTRUCTION.TXT, .URL, and .HTML.
.Parameter LogFile
  Path to a log file. Required by GFI MAX script player.  Not used here.
  Default:  "".
#>
param(
    [Parameter(Mandatory = $false,
                    Position = 0,
                    ValueFromPipelineByPropertyName = $true)]
    [String]$FilePattern="DECRYPT_INST*.*", 

	  [Parameter(Mandatory = $false,
                    Position = 1,
                    ValueFromPipelineByPropertyName = $true)]
    [String]$LogFile=""
)

# ----------------------------------------------------------
# Define functions
# ----------------------------------------------------------
function CheckFilePath( `
	[String]$FilePath="", `
	[String]$FilePattern="", `
  [ref]$OutputDetail) {

  # Always check for the same file pattern, DECRYPT_INST*.*
  $FilePath += "\" + $FilePattern
  
  if (Test-Path $FilePath) { 
    $OutputDetail.value += ("`nFile path """ + $FilePath + """ FOUND")
    $CheckFilePath = $true 
  } else {
    $OutputDetail.value += ("`nFile path """ + $FilePath + """ not found")
    $CheckFilePath = $false
  }
  return $CheckFilePath
}

function CheckRegistryPath( `
	[String]$RegistryPath="", `
  [ref]$OutputDetail) {

  if (Test-Path $RegistryPath) { 
    $OutputDetail.value += ("`nRegistry path """ + $RegistryPath + """ FOUND")
    $CheckRegistryPath = $true 
  } else {
    $OutputDetail.value += ("`nRegistry path """ + $RegistryPath + """ not found")
    $CheckRegistryPath = $false
  }
  return $CheckRegistryPath
}

# ----------------------------------------------------------
# Initialize variables
# ----------------------------------------------------------
$CryptoWallFound = $false
$OutputDetail = "" # Will build up a string in this variable to be output AFTER summary line

# ----------------------------------------------------------
# Check file paths
# ----------------------------------------------------------
# Per http://www.bleepingcomputer.com/virus-removal/cryptowall-ransomware-information, CryptoWall
# puts DECRYPT_INSTRUCTION.TXT, .URL, and .HTML files in every encrypted folder.  Check a few common folders.
$OutputDetail += "`nCheck file paths"
$OutputDetail += "`n----------------"
$OutputDetail += "`nCommon paths"
$SpecialFolder = [environment]::getfolderpath("CommonApplicationData")
if (CheckFilePath($SpecialFolder) $FilePattern ([ref]$OutputDetail)) { $CryptoWallFound = $true }

# Because we run this as the SYSTEM user under MaxFocus, we need to "manually" derive 
# the paths to users' folders (on XP or Vista/7/8), then loop through them.  

$ProfileRoot = $env:SystemDrive + "\Users"
if (Test-Path $ProfileRoot) { # Windows Vista/7/8/2008/2012
  
  # [environment]::getfolderpath("CommonDesktopDirectory") not available in PowerShell 2 so code path directly
  if (CheckFilePath($ProfileRoot + "\Public\Desktop") $FilePattern ([ref]$OutputDetail)) { $CryptoWallFound = $true }

  $OutputDetail += "`nUser-specific paths"
  # List directories ("containers") only in the $ProfileRoot path. Exclude hidden folders and junction points.
  get-childitem $ProfileRoot |  Where-Object { $_.PSIsContainer } | ForEach-Object {
    # $_.Name is directory name only; $_.FullName includes full path 
    if ($_.Name -ne "Public") { # We handle common (Public) paths above
      if (CheckFilePath($_.FullName + "\Documents") $FilePattern ([ref]$OutputDetail)) { $CryptoWallFound = $true }    
      if (CheckFilePath($_.FullName + "\Desktop") $FilePattern ([ref]$OutputDetail)) { $CryptoWallFound = $true }    
      if (CheckFilePath($_.FullName + "\AppData\Local") $FilePattern ([ref]$OutputDetail)) { $CryptoWallFound = $true }    
    }
  }
} else { # should be XP/2003

  $ProfileRoot = $env:SystemDrive + "\Documents and Settings"
  if (Test-Path $ProfileRoot) {
    
    # [environment]::getfolderpath("CommonDesktopDirectory") not available in PowerShell 2 so code path directly
    if (CheckFilePath($ProfileRoot + "\All Users\Desktop") $FilePattern ([ref]$OutputDetail)) { $CryptoWallFound = $true }

    $OutputDetail += "`nUser-specific paths"
    # List directories ("containers") only in the $ProfileRoot path. Exclude hidden folders and junction points.
    get-childitem $ProfileRoot |  Where-Object { $_.PSIsContainer } | ForEach-Object {
      # $_.Name is directory name only; $_.FullName includes full path 
      if ($_.Name -ne "All Users") { # We handle common (All Users) paths above
        if (CheckFilePath($_.FullName + "\My Documents") $FilePattern ([ref]$OutputDetail)) { $CryptoWallFound = $true }    
        if (CheckFilePath($_.FullName + "\Desktop") $FilePattern ([ref]$OutputDetail)) { $CryptoWallFound = $true }    
        if (CheckFilePath($_.FullName + "\Local Settings\Application Data") $FilePattern ([ref]$OutputDetail)) { $CryptoWallFound = $true }    
      }
    }
  }
}

# ----------------------------------------------------------
# Check registry paths
# ----------------------------------------------------------
$OutputDetail += "`n`nCheck registry paths"
$OutputDetail += "`n--------------------"
# From http://www.pcsgo.com/quickly-remove-cryptowall-decrypter-from-your-computer-ransomware-removal-guides/
# This only checks the existence of registry _keys_, not values
# Most keys are "CryptoWall Decrypter" but use a wildcard "CryptoWall*" for  a slightly more generic search.
if (CheckRegistryPath "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\CryptoWall*" ([ref]$OutputDetail)) { $CryptoWallFound = $true }
if (CheckRegistryPath "HKLM:\SOFTWARE\CryptoWall*" ([ref]$OutputDetail)) { $CryptoWallFound = $true }
# I'm also adding searches under Wow6432Node in case it gets deployed as a 32-bat app on a 64-bit platform:
if (CheckRegistryPath "HKLM:\SOFTWARE\Wow6432Node\CryptoWall*" ([ref]$OutputDetail)) { $CryptoWallFound = $true }
if (CheckRegistryPath "HKCU:\Software\CryptoWall*" ([ref]$OutputDetail)) { $CryptoWallFound = $true }
# Note:  Not all keys in those articles are added here.  Some keys look like legitimate Windows settings 
#        that CryptoWall manipulates, e.g. turning off System Restore.  Some keys require checking values,
#        which PowerShell's Test-Path does not do.

if ($CryptoWallFound) {
  $Status = "CRYPTOWALL FILE OR REGISTRY KEY FOUND."
	$ExitCode = 1001
}
else {
  $Status = "No CryptoWall files or registry keys found."
	$ExitCode = 0
}
#Print SummaryLine for display in monitoring system. Abbreviate date/time.
$Status + " [" + (Get-Date -Format "MM/dd HH:mm") + "]"

$OutputDetail
"`n======================================================"
"`nLocal Machine Time:  " + (Get-Date -Format G)
"Exit Code: " + $ExitCode

Exit $ExitCode

Viewing all articles
Browse latest Browse all 32

Trending Articles