From 34a89a95185640376abed20a5d4a75190712c0c9 Mon Sep 17 00:00:00 2001 From: Gabor Gyorvari Date: Sat, 25 Aug 2018 18:13:45 +0200 Subject: [PATCH] Added new argument to display matching pattern's line number in the file. --- README.md | 1 + scan.php | 48 ++++++++++++++++++++++++++++++++++++------------ 2 files changed, 37 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 6ea71f0..637670f 100644 --- a/README.md +++ b/README.md @@ -30,6 +30,7 @@ Usage: php scan.php -d -s --no-stop Continue scanning file after first hit -p --pattern Show Patterns next to the file name -t --time Show time of last file change + --line-number Display matching pattner line number in file ``` Ignore argument could be used multiple times and accept glob style matching ex.: "`cache*`", "`??-cache.php`" or "`/cache`" etc. diff --git a/scan.php b/scan.php index a7f9be3..44486fa 100644 --- a/scan.php +++ b/scan.php @@ -37,6 +37,7 @@ class MalwareScanner private $flagTime = false; private $flagExtraCheck = false; private $flagFollowSymlink = false; + private $flagLineNumber = false; private $whitelist = array(); private $ignore = array(); private $stat = array( @@ -197,7 +198,8 @@ class MalwareScanner 'no-color', 'no-stop', 'pattern', - 'time' + 'time', + 'line-number' ) ); @@ -263,6 +265,9 @@ class MalwareScanner if (isset($options['time']) || isset($options['t'])) { $this->setFlagTime(true); } + if (isset($options['line-number'])) { + $this->setFlagLineNumber(true); + } } public function setExtensions(array $a) @@ -301,6 +306,11 @@ class MalwareScanner $this->flagTime = $b; } + public function setFlagLineNumber($b) + { + $this->flagLineNumber = $b; + } + public function setFlagBase64($b) { $this->flagBase64 = $b; @@ -367,7 +377,7 @@ class MalwareScanner -Pattern Matched -The last comment to appear in the pattern file before this pattern */ - private function printPath(&$found, &$path, &$pattern, &$comment, &$hash) + private function printPath($found, $path, $pattern, $comment, $hash, $lineNumber) { $output_string = '# '; @@ -414,15 +424,18 @@ class MalwareScanner //'#' added again as code snippets have the potential to be valid shell commands if ($found) { if ($this->flagPattern) { - $opatt = "# $pattern "; - $output_string = $output_string . $state_color . $opatt . $this->ANSI_OFF; + $opatt = "# $pattern"; + $output_string = $output_string . $state_color . $opatt . $this->ANSI_OFF . ' '; } if ($this->flagComments) { - $output_string = $output_string . $this->ANSI_BLUE . $comment . $this->ANSI_OFF; + $output_string = $output_string . $this->ANSI_BLUE . $comment . $this->ANSI_OFF . ' '; + } + if ($this->flagLineNumber) { + $output_string = $output_string . '# ' . $lineNumber; } } - $output_string = $output_string . PHP_EOL; + $output_string = trim($output_string) . PHP_EOL; echo $output_string; } @@ -516,7 +529,7 @@ class MalwareScanner } if (!$found) { - $this->printPath($found, $path, $toSearch, $comment, $hash); + $this->printPath($found, $path, $toSearch, $comment, $hash, -1); return false; } @@ -532,14 +545,14 @@ class MalwareScanner //Returns true if the raw string exists in the file contents. private function scanFunc_STR(&$pattern, &$content) { - return (strpos($content, $pattern) !== false); + return strpos($content, $pattern); } //Performs raw string, case insensitive matching. //Returns true if the raw string exists in the file contents, ignoring case. private function scanFunc_STRI(&$pattern, &$content) { - return (stripos($content, $pattern) !== false); + return stripos($content, $pattern); } //Performs regular expression matching. @@ -547,7 +560,11 @@ class MalwareScanner //Patterns will match multiple lines, though you can use ^$ to match the beginning and end of a line. private function scanFunc_RE(&$pattern, &$content) { - return preg_match('/' . $pattern . '/im', $content); + $ret = preg_match('/' . $pattern . '/im', $content, $match, PREG_OFFSET_CAPTURE); + if ($ret) { + return $match[0][1]; + } + return false; } //First parameter '$scanFunction' is a defined function name passed as a string. @@ -563,12 +580,19 @@ class MalwareScanner 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. - if ($this->$scanFunction($pattern, $fileContent)) { + $position = $this->$scanFunction($pattern, $fileContent); + if ($position !== false) { $found = true; if ($hash === '') { $hash = md5($fileContent); } - $this->printPath($found, $path, $pattern, $comment, $hash); + $lineNumber = 1; + if ($this->flagLineNumber) { + if ($pos = strrpos(substr($fileContent, 0, $position), "\n")) { + $lineNumber = substr_count(substr($fileContent, 0, $pos + 1), "\n") + 1; + } + } + $this->printPath($found, $path, $pattern, $comment, $hash, $lineNumber); if (!$this->flagNoStop) { return; }