mirror of
https://github.com/scr34m/php-malware-scanner.git
synced 2026-06-16 12:30:35 +00:00
Code style formatting
This commit is contained in:
237
scan.php
237
scan.php
@@ -19,38 +19,38 @@
|
||||
class MalwareScanner
|
||||
{
|
||||
//Pretty Colors
|
||||
private $ANSI_GREEN = "\033[32m";
|
||||
private $ANSI_RED = "\033[31m";
|
||||
private $ANSI_YELLOW = "\033[33m";
|
||||
private $ANSI_BLUE = "\033[36m";
|
||||
private $ANSI_OFF = "\033[0m";
|
||||
private $ANSI_GREEN = "\033[32m";
|
||||
private $ANSI_RED = "\033[31m";
|
||||
private $ANSI_YELLOW = "\033[33m";
|
||||
private $ANSI_BLUE = "\033[36m";
|
||||
private $ANSI_OFF = "\033[0m";
|
||||
|
||||
private $dir = '';
|
||||
private $extension = '.php';
|
||||
private $flagBase64 = false;
|
||||
private $flagChecksum = false;
|
||||
private $flagComments = false;
|
||||
private $flagHideOk = false;
|
||||
private $dir = '';
|
||||
private $extension = '.php';
|
||||
private $flagBase64 = false;
|
||||
private $flagChecksum = false;
|
||||
private $flagComments = false;
|
||||
private $flagHideOk = false;
|
||||
private $flagHideWhitelist = false;
|
||||
private $flagNoStop = false;
|
||||
private $flagPattern = false;
|
||||
private $flagTime = false;
|
||||
private $extraCheck = false;
|
||||
private $whitelist = array();
|
||||
private $ignore = array();
|
||||
private $stat = array(
|
||||
'directories' => 0,
|
||||
'files_scanned' => 0,
|
||||
'files_infected' => 0,
|
||||
);
|
||||
private $flagNoStop = false;
|
||||
private $flagPattern = false;
|
||||
private $flagTime = false;
|
||||
private $extraCheck = false;
|
||||
private $whitelist = array();
|
||||
private $ignore = array();
|
||||
private $stat = array(
|
||||
'directories' => 0,
|
||||
'files_scanned' => 0,
|
||||
'files_infected' => 0,
|
||||
);
|
||||
private $followSymlink = false;
|
||||
|
||||
//Pattern File Attributes
|
||||
private $patterns_raw = array();
|
||||
private $patterns_iraw = array();
|
||||
private $patterns_re = array();
|
||||
private $patterns_raw = array();
|
||||
private $patterns_iraw = array();
|
||||
private $patterns_re = array();
|
||||
private $patterns_b64functions = array();
|
||||
private $patterns_b64keywords = array();
|
||||
private $patterns_b64keywords = array();
|
||||
|
||||
//Constructor - Likes to do as little as possible.
|
||||
public function __construct()
|
||||
@@ -65,11 +65,11 @@ class MalwareScanner
|
||||
//Allows the -n/--no-color flag to easily remove color characters.
|
||||
private function disableColor()
|
||||
{
|
||||
$this->ANSI_GREEN = '';
|
||||
$this->ANSI_RED = '';
|
||||
$this->ANSI_GREEN = '';
|
||||
$this->ANSI_RED = '';
|
||||
$this->ANSI_YELLOW = '';
|
||||
$this->ANSI_BLUE = '';
|
||||
$this->ANSI_OFF = '';
|
||||
$this->ANSI_BLUE = '';
|
||||
$this->ANSI_OFF = '';
|
||||
}
|
||||
|
||||
//Prints the passed 'string' in red text, calls showHelp().
|
||||
@@ -85,19 +85,19 @@ class MalwareScanner
|
||||
//Handles pattern loading and saving to the class object
|
||||
private function initializePatterns()
|
||||
{
|
||||
//Loads either the primary scanning patterns or the base64 patterns depending on -b/--base64 flag
|
||||
$dir = dirname(__FILE__);
|
||||
//Loads either the primary scanning patterns or the base64 patterns depending on -b/--base64 flag
|
||||
if (!$this->flagBase64) {
|
||||
$this->patterns_raw = $this->loadPatterns(dirname(__FILE__) . '/definitions/patterns_raw.txt');
|
||||
$this->patterns_iraw = $this->loadPatterns(dirname(__FILE__) . '/definitions/patterns_iraw.txt');
|
||||
$this->patterns_re = $this->loadPatterns(dirname(__FILE__) . '/definitions/patterns_re.txt');
|
||||
$this->patterns_raw = $this->loadPatterns($dir . '/definitions/patterns_raw.txt');
|
||||
$this->patterns_iraw = $this->loadPatterns($dir . '/definitions/patterns_iraw.txt');
|
||||
$this->patterns_re = $this->loadPatterns($dir . '/definitions/patterns_re.txt');
|
||||
} else {
|
||||
$this->patterns_b64functions = $this->loadPatterns($dir . '/base64_patterns/php_functions.txt');
|
||||
$this->patterns_b64keywords = $this->loadPatterns($dir . '/base64_patterns/php_keywords.txt');
|
||||
}
|
||||
else {
|
||||
$this->patterns_b64functions = $this->loadPatterns(dirname(__FILE__). '/base64_patterns/php_functions.txt');
|
||||
$this->patterns_b64keywords = $this->loadPatterns(dirname(__FILE__). '/base64_patterns/php_keywords.txt');
|
||||
}
|
||||
|
||||
|
||||
//Adds additional checks to patterns_raw
|
||||
//This may be something to move into a pattern file rather than leave hardcoded.
|
||||
//This may be something to move into a pattern file rather than leave hardcoded.
|
||||
if ($this->extraCheck) {
|
||||
$this->patterns_raw['googleBot'] = '# ';
|
||||
$this->patterns_raw['htaccess'] = '# ';
|
||||
@@ -137,8 +137,8 @@ class MalwareScanner
|
||||
continue;
|
||||
}
|
||||
//Check if first char in pattern is a '#' which indicates a comment and skips.
|
||||
//Stores the comment to be stored with the pattern in the list as key:value pairs.
|
||||
//The pattern is the key and the comment is the value.
|
||||
//Stores the comment to be stored with the pattern in the list as key:value pairs.
|
||||
//The pattern is the key and the comment is the value.
|
||||
if ($pattern[0] === '#') {
|
||||
$last_comment = $pattern;
|
||||
continue;
|
||||
@@ -166,32 +166,34 @@ class MalwareScanner
|
||||
//All flag handling stuff should be setup here.
|
||||
private function parseArgs()
|
||||
{
|
||||
$options = getopt( 'd:e:i:abmcxlhkwnspt',
|
||||
array(
|
||||
'directory:',
|
||||
'extension:',
|
||||
'ignore:',
|
||||
'all-output',
|
||||
'base',
|
||||
'checksum',
|
||||
'comment',
|
||||
'extra-check',
|
||||
'follow-link',
|
||||
'help',
|
||||
'hide-ok',
|
||||
'hide-whitelist',
|
||||
'no-color',
|
||||
'no-stop',
|
||||
'pattern',
|
||||
'time'
|
||||
));
|
||||
|
||||
$options = getopt(
|
||||
'd:e:i:abmcxlhkwnspt',
|
||||
array(
|
||||
'directory:',
|
||||
'extension:',
|
||||
'ignore:',
|
||||
'all-output',
|
||||
'base',
|
||||
'checksum',
|
||||
'comment',
|
||||
'extra-check',
|
||||
'follow-link',
|
||||
'help',
|
||||
'hide-ok',
|
||||
'hide-whitelist',
|
||||
'no-color',
|
||||
'no-stop',
|
||||
'pattern',
|
||||
'time'
|
||||
)
|
||||
);
|
||||
|
||||
//Help Option should be first
|
||||
if (isset($options['help']) || isset($options['h'])) {
|
||||
$this->showHelp();
|
||||
exit;
|
||||
}
|
||||
|
||||
|
||||
//Options that Require Additional Parameters
|
||||
if (isset($options['directory']) || isset($options['d'])) {
|
||||
$this->dir = isset($options['directory']) ? $options['directory'] : $options['d'];
|
||||
@@ -210,12 +212,15 @@ class MalwareScanner
|
||||
|
||||
//Simple Flag Options
|
||||
if (isset($options['all-output']) || isset($options['a'])) {
|
||||
$this->flagChecksum = true; $this->flagComments = true; $this->flagPattern = true; $this->flagTime = true;
|
||||
$this->flagChecksum = true;
|
||||
$this->flagComments = true;
|
||||
$this->flagPattern = true;
|
||||
$this->flagTime = true;
|
||||
}
|
||||
if (isset($options['base64']) || isset($options['b'])) {
|
||||
$this->flagBase64 = true;
|
||||
}
|
||||
if (isset($options['checksum']) || isset($options['m'])) {
|
||||
if (isset($options['checksum']) || isset($options['m'])) {
|
||||
$this->flagChecksum = true;
|
||||
}
|
||||
if (isset($options['comment']) || isset($options['c'])) {
|
||||
@@ -289,18 +294,20 @@ class MalwareScanner
|
||||
|
||||
//OK
|
||||
if (!$found) {
|
||||
if ($this->flagHideOk){return;}
|
||||
if ($this->flagHideOk) {
|
||||
return;
|
||||
}
|
||||
$state = 'OK';
|
||||
$hash = ' ';
|
||||
$state_color = $this->ANSI_GREEN;
|
||||
}
|
||||
//WL
|
||||
} //WL
|
||||
elseif ($this->inWhitelist($hash)) {
|
||||
if ($this->flagHideWhitelist) {return;}
|
||||
if ($this->flagHideWhitelist) {
|
||||
return;
|
||||
}
|
||||
$state = 'WL';
|
||||
$state_color = $this->ANSI_YELLOW;
|
||||
}
|
||||
//ER
|
||||
} //ER
|
||||
else {
|
||||
$state = 'ER';
|
||||
$state_color = $this->ANSI_RED;
|
||||
@@ -311,12 +318,12 @@ class MalwareScanner
|
||||
if ($this->flagTime) {
|
||||
$changed_time = filectime($path);
|
||||
$htime = date('H:i d-m-Y', $changed_time);
|
||||
$output_string = $output_string . $this->ANSI_BLUE . $htime . $this->ANSI_OFF . ' ';
|
||||
$output_string = $output_string . $this->ANSI_BLUE . $htime . $this->ANSI_OFF . ' ';
|
||||
}
|
||||
|
||||
//Include Checksum/Hash
|
||||
if ($this->flagChecksum) {
|
||||
$output_string = $output_string . $this->ANSI_BLUE . $hash . $this->ANSI_OFF . ' ';
|
||||
$output_string = $output_string . $this->ANSI_BLUE . $hash . $this->ANSI_OFF . ' ';
|
||||
}
|
||||
|
||||
//Append Path
|
||||
@@ -389,24 +396,24 @@ class MalwareScanner
|
||||
//Calls the load pattern and load whitelist functions
|
||||
//Calls the process and report functions.
|
||||
private function run($dir)
|
||||
{
|
||||
{
|
||||
//Make sure a directory was specified.
|
||||
if ($this->dir === '') {
|
||||
if ($this->dir === '') {
|
||||
$this->error('No directory specified');
|
||||
}
|
||||
|
||||
|
||||
//Make sure the input is a valid directory path.
|
||||
$dir = rtrim($dir, '/');
|
||||
if (!is_dir($dir)) {
|
||||
$this->error('Specified path is not a directory: ' . $dir);
|
||||
}
|
||||
|
||||
//Load Patterns
|
||||
|
||||
//Load Patterns
|
||||
$this->initializePatterns();
|
||||
|
||||
//Load Whitelist
|
||||
$this->loadWhitelist();
|
||||
|
||||
|
||||
//Load Whitelist
|
||||
$this->loadWhitelist();
|
||||
|
||||
$start = time();
|
||||
$this->process($dir . '/');
|
||||
$this->report($start, $dir . '/');
|
||||
@@ -419,18 +426,17 @@ class MalwareScanner
|
||||
$this->stat['files_scanned']++;
|
||||
$fileContent = file_get_contents($path);
|
||||
$found = false;
|
||||
$hash = '';
|
||||
$hash = '';
|
||||
$toSearch = '';
|
||||
$comment = '';
|
||||
|
||||
if (!$this->flagBase64) {
|
||||
$this->scanLoop('scanFunc_STR', $fileContent, $this->patterns_raw, $path, $found, $hash);
|
||||
$this->scanLoop('scanFunc_STR', $fileContent, $this->patterns_raw, $path, $found, $hash);
|
||||
$this->scanLoop('scanFunc_STRI', $fileContent, $this->patterns_iraw, $path, $found, $hash);
|
||||
$this->scanLoop('scanFunc_RE', $fileContent, $this->patterns_re, $path, $found, $hash);
|
||||
}
|
||||
else {
|
||||
$this->scanLoop('scanFunc_STR', $fileContent, $this->patterns_b64functions, $path, $found, $hash);
|
||||
$this->scanLoop('scanFunc_STR', $fileContent, $this->patterns_b64keywords, $path, $found, $hash);
|
||||
$this->scanLoop('scanFunc_RE', $fileContent, $this->patterns_re, $path, $found, $hash);
|
||||
} else {
|
||||
$this->scanLoop('scanFunc_STR', $fileContent, $this->patterns_b64functions, $path, $found, $hash);
|
||||
$this->scanLoop('scanFunc_STR', $fileContent, $this->patterns_b64keywords, $path, $found, $hash);
|
||||
}
|
||||
|
||||
if (!$found) {
|
||||
@@ -442,7 +448,7 @@ class MalwareScanner
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->stat['files_infected']++;
|
||||
$this->stat['files_infected']++;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -472,20 +478,24 @@ class MalwareScanner
|
||||
//This function should accept a pattern string and a content string.
|
||||
//This function will return true if the pattern exists in the content.
|
||||
//See 'scanFunc_STR', 'scanFunc_STRI', 'scanFUNC_RE' above as examples.
|
||||
|
||||
|
||||
//Loops through all patterns in a file using the passed function name to determine a match.
|
||||
//Variables passed by reference for performance and modification access.
|
||||
private function scanLoop($scanFunction, &$fileContent, &$patterns, &$path, &$found, &$hash)
|
||||
{
|
||||
if (!$found || $this->flagNoStop) {
|
||||
foreach ($patterns as $pattern => $comment) {
|
||||
//Call the function that is named in $scanFunction
|
||||
//This allows multiple search/match functions to be used without duplicating the loop code.
|
||||
//Call the function that is named in $scanFunction
|
||||
//This allows multiple search/match functions to be used without duplicating the loop code.
|
||||
if ($this->$scanFunction($pattern, $fileContent)) {
|
||||
$found = true;
|
||||
if ($hash === ''){$hash = md5($fileContent);}
|
||||
if ($hash === '') {
|
||||
$hash = md5($fileContent);
|
||||
}
|
||||
$this->printPath($found, $path, $pattern, $comment, $hash);
|
||||
if (!$this->flagNoStop){return;}
|
||||
if (!$this->flagNoStop) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -494,27 +504,26 @@ class MalwareScanner
|
||||
//Prints out the usage menu options.
|
||||
private function showHelp()
|
||||
{
|
||||
echo 'Usage: php scan.php -d <directory>' . PHP_EOL;
|
||||
echo ' -h --help Show this help message' . PHP_EOL;
|
||||
echo ' -d <directory> --directory Directory for searching' . PHP_EOL;
|
||||
echo ' -e <file extension> --extension File Extension to Scan' . PHP_EOL;
|
||||
echo ' -i <directory|file> --ignore Directory of file to ignore' . PHP_EOL;
|
||||
echo ' -a --all-output Enables --checksum,--comment,--pattern,--time' . PHP_EOL;
|
||||
echo ' -b --base64 Scan for base64 encoded PHP keywords' . PHP_EOL;
|
||||
echo ' -m --checksum Display MD5 Hash/Checksum of file' . PHP_EOL;
|
||||
echo ' -c --comment Display comments for matched patterns' . PHP_EOL;
|
||||
echo ' -x --extra-check Adds GoogleBot and htaccess to Scan List' . PHP_EOL;
|
||||
echo ' -l --follow-symlink Follow symlinked directories' . PHP_EOL;
|
||||
echo ' -k --hide-ok Hide results with \'OK\' status' . PHP_EOL;
|
||||
echo ' -w --hide-whitelist Hide results with \'WL\' status' . PHP_EOL;
|
||||
echo ' -n --no-color Disable color mode' . PHP_EOL;
|
||||
echo ' -s --no-stop Continue scanning file after first hit' . PHP_EOL;
|
||||
echo ' -p --pattern Show Patterns next to the file name' . PHP_EOL;
|
||||
echo ' -t --time Show time of last file change' . PHP_EOL;
|
||||
echo 'Usage: php scan.php -d <directory>' . PHP_EOL;
|
||||
echo ' -h --help Show this help message' . PHP_EOL;
|
||||
echo ' -d <directory> --directory Directory for searching' . PHP_EOL;
|
||||
echo ' -e <file extension> --extension File Extension to Scan' . PHP_EOL;
|
||||
echo ' -i <directory|file> --ignore Directory of file to ignore' . PHP_EOL;
|
||||
echo ' -a --all-output Enables --checksum,--comment,--pattern,--time' . PHP_EOL;
|
||||
echo ' -b --base64 Scan for base64 encoded PHP keywords' . PHP_EOL;
|
||||
echo ' -m --checksum Display MD5 Hash/Checksum of file' . PHP_EOL;
|
||||
echo ' -c --comment Display comments for matched patterns' . PHP_EOL;
|
||||
echo ' -x --extra-check Adds GoogleBot and htaccess to Scan List' . PHP_EOL;
|
||||
echo ' -l --follow-symlink Follow symlinked directories' . PHP_EOL;
|
||||
echo ' -k --hide-ok Hide results with \'OK\' status' . PHP_EOL;
|
||||
echo ' -w --hide-whitelist Hide results with \'WL\' status' . PHP_EOL;
|
||||
echo ' -n --no-color Disable color mode' . PHP_EOL;
|
||||
echo ' -s --no-stop Continue scanning file after first hit' . PHP_EOL;
|
||||
echo ' -p --pattern Show Patterns next to the file name' . PHP_EOL;
|
||||
echo ' -t --time Show time of last file change' . PHP_EOL;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//Creates a new MalwareScanner object which does all the work.
|
||||
new MalwareScanner();
|
||||
?>
|
||||
new MalwareScanner();
|
||||
Reference in New Issue
Block a user