large 'scan' function broken up comment flag added

scan function has been broken up into a multiple functions which should make it more modular if future scan types are needed.
--comment, -a flag was added which prints the first comment to appear prior to the matched pattern in the pattern file.
This commit is contained in:
nichogenius
2017-08-19 17:46:09 -06:00
committed by GitHub
parent ea2da42f8e
commit dea08acd2e

129
scan.php
View File

@@ -27,7 +27,9 @@ class MalwareScanner
private $dir = '';
private $extension = '.php';
private $flagBase64 = false;
private $flagChecksum = false;
private $flagComments = false;
private $flagHideOk = false;
private $flagHideWhitelist = false;
private $flagTime = false;
@@ -42,9 +44,11 @@ class MalwareScanner
);
private $followSymlink = false;
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();
public function __construct()
{
@@ -77,9 +81,17 @@ class MalwareScanner
private function initializePatterns()
{
$this->patterns_raw = $this->loadPatterns(dirname(__FILE__) . '/patterns_raw.txt');
$this->patterns_iraw = $this->loadPatterns(dirname(__FILE__) . '/patterns_iraw.txt');
$this->patterns_re = $this->loadPatterns(dirname(__FILE__) . '/patterns_re.txt');
if (!$this->flagBase64) {
$this->patterns_raw = $this->loadPatterns(dirname(__FILE__) . '/patterns_raw.txt');
$this->patterns_iraw = $this->loadPatterns(dirname(__FILE__) . '/patterns_iraw.txt');
$this->patterns_re = $this->loadPatterns(dirname(__FILE__) . '/patterns_re.txt');
}
if ($this->flagBase64) {
$this->patterns_b64functions = $this->loadPatterns(dirname(__FILE__). '/php_functions.txt');
$this->patterns_b64keywrds = $this->loadPatterns(dirname(__FILE__). '/php_keywords.txt');
}
if ($this->extraCheck) {
array_push($this->patterns_raw, "googleBot", "htaccess");
}
@@ -103,6 +115,7 @@ class MalwareScanner
private function loadPatterns($file)
{
$last_comment = '';
$list = array();
if (is_readable($file)) {
foreach (file($file) as $pattern) {
@@ -112,9 +125,10 @@ class MalwareScanner
}
//Check if first char in pattern is a '#' which indicates a comment and skips.
if ($pattern[0] === '#') {
$last_comment = $pattern;
continue;
}
$list[] = trim($pattern);
$list[trim($pattern)] = trim($last_comment);
}
}
return $list;
@@ -134,7 +148,7 @@ class MalwareScanner
private function parseArgs()
{
$options = getopt('d:e:i:cxlhkwntv', array('directory:', 'extension:', 'ignore:', 'checksum', 'extra-check', 'follow-link', 'help', 'hide-ok', 'hide-whitelist', 'no-color', 'time', 'verbose'));
$options = getopt('d:e:i:bacxlhkwntv', array('directory:', 'extension:', 'ignore:', 'base', 'checksum', 'comment', 'extra-check', 'follow-link', 'help', 'hide-ok', 'hide-whitelist', 'no-color', 'time', 'verbose'));
//Help Option should be first
if (isset($options['help']) || isset($options['h'])) {
@@ -159,9 +173,15 @@ class MalwareScanner
}
//Simple Flag Options
if (isset($options['base64']) || isset($options['b'])){
$this->flagBase64 = true;
}
if (isset($options['checksum']) || isset($options['c'])){
$this->flagChecksum = true;
}
if (isset($options['comment']) || isset($options['a'])){
$this->flagComments = true;
}
if (isset($options['extra-check']) || isset($options['x'])) {
$this->extraCheck = true;
}
@@ -211,7 +231,7 @@ class MalwareScanner
return (bool)preg_match($expr, $path);
}
private function printPath($found, $path, $pattern, $hash)
private function printPath(&$found, &$path, &$pattern, &$comment, &$hash)
{
$output_string = '# ';
@@ -256,6 +276,9 @@ class MalwareScanner
if ($found) {
$opatt = "# $pattern";
$output_string = $output_string . $state_color . $opatt . $this->ANSI_OFF;
if ($this->flagComments) {
$output_string = $output_string . ' ' . $comment;
}
}
$output_string = $output_string . PHP_EOL;
@@ -331,52 +354,20 @@ class MalwareScanner
$found = false;
$hash = '';
$toSearch = '';
foreach ($this->patterns_raw as $toSearch) {
if (strpos($fileContent, $toSearch) !== FALSE){
$found = true;
if ($hash === ''){
$hash = md5($fileContent);
}
$this->printPath($found, $path, $toSearch, $hash);
if (!$this->verbose){
break;
}
}
}
if (!$found || $this->verbose) {
foreach ($this->patterns_iraw as $toSearch) {
if (stripos($fileContent, $toSearch) !== FALSE){
$found = true;
if ($hash === ''){
$hash = md5($fileContent);
}
$this->printPath($found, $path, $toSearch, $hash);
if (!$this->verbose){
break;
}
}
}
}
$comment = '';
if (!$found || $this->verbose) {
foreach ($this->patterns_re as $toSearch) {
if (preg_match('/' . $toSearch . '/im', $fileContent)) {
$found = true;
if ($hash === ''){
$hash = md5($fileContent);
}
$this->printPath($found, $path, $toSearch, $hash);
if (!$this->verbose){
break;
}
}
}
if (!$this->flagBase64) {
$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);
}
if ($this->flagBase64) {
$this->scanLoop('scanFunc_STR', $fileContent, $this->patterns_b64functions, $path, $found, $hash);
$this->scanLoop('scanFunc_STR', $fileContent, $this->patterns_b64keywords, $path, $found, $hash);
}
if (!$found) {
$this->printPath($found, $path, $toSearch, $hash);
$this->printPath($found, $path, $toSearch, $comment, $hash);
return false;
}
@@ -388,6 +379,40 @@ class MalwareScanner
return true;
}
private function scanFunc_STR(&$pattern, &$content)
{
return (strpos($content, $pattern) !== false);
}
private function scanFunc_STRI(&$pattern, &$content)
{
return (stripos($content, $pattern) !== false);
}
private function scanFunc_RE(&$pattern, &$content)
{
return preg_match('/' . $pattern . '/im', $content);
}
private function scanLoop($scanFunction, &$fileContent, &$patterns, &$path, &$found, &$hash)
{
if (!$found || $this->verbose) {
foreach ($patterns as $pattern => $comment) {
if ($this->$scanFunction($pattern, $fileContent)) {
$found = true;
if ($hash === ''){
$hash = md5($fileContent);
}
$this->printPath($found, $path, $pattern, $comment, $hash);
if (!$this->verbose){
return;
}
}
}
}
}
private function showHelp()
{
echo 'Usage: scan.php -d <directory>' . PHP_EOL;
@@ -395,7 +420,9 @@ class MalwareScanner
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 igonre' . PHP_EOL;
echo ' -b --base64 Scan for base64 encoded PHP keywords' . PHP_EOL;
echo ' -c --checksum Display MD5 Checksum of file' . PHP_EOL;
echo ' -a --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 OK aka not infected messages' . PHP_EOL;