mirror of
https://github.com/scr34m/php-malware-scanner.git
synced 2026-06-16 12:30:35 +00:00
Several Significant changes to scan.php
- Gave each flag option a short or long option; like i:ignore or d:directory or k:hide-ok
- Added a verbose option that instructs the scan to scan a file for ALL matches and not just stop at the first one.
- Restructured the output code to allow for the verbose flag, mainly a new function printPath and where the md5 hash is computed
- Modified the output to be cleaner, checksum is printed first as it is fix-width and to make it easier to paste into the whitelist file.
- Modified the output to be 'bash safe', ie when I accidentally paste my scan results into my terminal, the '#' should make sure everything is treated as a comment. This is in contrast to possibly attempting to execute absolute paths to potentially malicious PHP scripts and the usage of the '>' which tells the shell to write to a file. Also enclosed each path in {} for similar purposes.
- Printing the matched string/pattern in $color... might change later depending on preference.
This commit is contained in:
71
scan.php
71
scan.php
@@ -21,12 +21,14 @@ class MalwareScanner
|
|||||||
const ANSI_GREEN = "\033[32m";
|
const ANSI_GREEN = "\033[32m";
|
||||||
const ANSI_RED = "\033[31m";
|
const ANSI_RED = "\033[31m";
|
||||||
const ANSI_YELLOW = "\033[33m";
|
const ANSI_YELLOW = "\033[33m";
|
||||||
|
const ANSI_BLUE = "\033[36m";
|
||||||
const ANSI_OFF = "\033[0m";
|
const ANSI_OFF = "\033[0m";
|
||||||
|
|
||||||
private $extension = '.php';
|
private $extension = '.php';
|
||||||
private $flagHideOk = false;
|
private $flagHideOk = false;
|
||||||
private $flagHideWhitelist = false;
|
private $flagHideWhitelist = false;
|
||||||
private $extraCheck = false;
|
private $extraCheck = false;
|
||||||
|
private $verbose = false;
|
||||||
private $whitelist = array();
|
private $whitelist = array();
|
||||||
private $ignore = array();
|
private $ignore = array();
|
||||||
private $stat = array(
|
private $stat = array(
|
||||||
@@ -38,7 +40,7 @@ class MalwareScanner
|
|||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
$options = getopt('he:i:kwxd:l', array('help', 'extension:', 'ignore:', 'hide-ok', 'hide-whitelist', 'extra-check', 'directory:', 'follow-symlink'));
|
$options = getopt('he:i:kwxd:lv', array('help', 'extension:', 'ignore:', 'hide-ok', 'hide-whitelist', 'extra-check', 'directory:', 'follow-symlink', 'verbose'));
|
||||||
if (isset($options['help']) || isset($options['h'])) {
|
if (isset($options['help']) || isset($options['h'])) {
|
||||||
$this->showHelp();
|
$this->showHelp();
|
||||||
exit;
|
exit;
|
||||||
@@ -66,6 +68,9 @@ class MalwareScanner
|
|||||||
if (isset($options['follow-symlink']) || isset($options['l'])) {
|
if (isset($options['follow-symlink']) || isset($options['l'])) {
|
||||||
$this->followSymlink = true;
|
$this->followSymlink = true;
|
||||||
}
|
}
|
||||||
|
if (isset($options['verbose']) || isset($options['v'])){
|
||||||
|
$this->verbose = true;
|
||||||
|
}
|
||||||
if (isset($options['directory']) || isset($options['d'])) {
|
if (isset($options['directory']) || isset($options['d'])) {
|
||||||
$tmp = isset($options['directory']) ? $options['directory'] : $options['d'];
|
$tmp = isset($options['directory']) ? $options['directory'] : $options['d'];
|
||||||
$this->run($tmp);
|
$this->run($tmp);
|
||||||
@@ -163,6 +168,7 @@ class MalwareScanner
|
|||||||
|
|
||||||
$fileContent = file_get_contents($path);
|
$fileContent = file_get_contents($path);
|
||||||
$found = false;
|
$found = false;
|
||||||
|
$hash = '';
|
||||||
$toSearch = '';
|
$toSearch = '';
|
||||||
$patterns = $this->loadPatterns(dirname(__FILE__) . '/patterns_raw.txt');
|
$patterns = $this->loadPatterns(dirname(__FILE__) . '/patterns_raw.txt');
|
||||||
if ($this->extraCheck) {
|
if ($this->extraCheck) {
|
||||||
@@ -177,7 +183,13 @@ class MalwareScanner
|
|||||||
}
|
}
|
||||||
if (strpos($fileContent, $toSearch) !== FALSE){
|
if (strpos($fileContent, $toSearch) !== FALSE){
|
||||||
$found = true;
|
$found = true;
|
||||||
break;
|
if ($hash === ''){
|
||||||
|
$hash = md5($fileContent);
|
||||||
|
}
|
||||||
|
$this->printPath($found, $path, $toSearch, $hash);
|
||||||
|
if (!$this->verbose){
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -192,7 +204,13 @@ class MalwareScanner
|
|||||||
}
|
}
|
||||||
if (stripos($fileContent, $toSearch) !== FALSE){
|
if (stripos($fileContent, $toSearch) !== FALSE){
|
||||||
$found = true;
|
$found = true;
|
||||||
break;
|
if ($hash === ''){
|
||||||
|
$hash = md5($fileContent);
|
||||||
|
}
|
||||||
|
$this->printPath($found, $path, $toSearch, $hash);
|
||||||
|
if (!$this->verbose){
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -208,33 +226,50 @@ class MalwareScanner
|
|||||||
}
|
}
|
||||||
if (preg_match('/' . $toSearch . '/im', $fileContent)) {
|
if (preg_match('/' . $toSearch . '/im', $fileContent)) {
|
||||||
$found = true;
|
$found = true;
|
||||||
break;
|
if ($hash === ''){
|
||||||
|
$hash = md5($fileContent);
|
||||||
|
}
|
||||||
|
$this->printPath($found, $path, $toSearch, $hash);
|
||||||
|
if (!$this->verbose){
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$found) {
|
if (!$found) {
|
||||||
if (!$this->flagHideOk) {
|
$this->printPath($found, $path, $toSearch, $hash);
|
||||||
$this->out(self::ANSI_GREEN, 'OK', $path);
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// file hash is on whithelist hash then skip
|
if ($found && $this->inWhitelist($hash)) {
|
||||||
$hash = md5($fileContent);
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->stat['files_infected']++;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function printPath($found, $path, $pattern, $hash)
|
||||||
|
{
|
||||||
|
$blank_hash = ' ';
|
||||||
|
$blank_pattern = '';
|
||||||
|
$safe_path = '{' . $path . '}';
|
||||||
if ($found && $this->inWhitelist($hash)) {
|
if ($found && $this->inWhitelist($hash)) {
|
||||||
if (!$this->flagHideWhitelist) {
|
if (!$this->flagHideWhitelist) {
|
||||||
$this->out(self::ANSI_YELLOW, 'WL', $path);
|
$this->out(self::ANSI_YELLOW, 'WL', $blank_hash, $safe_path, $blank_pattern);
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($found) {
|
elseif ($found) {
|
||||||
$this->stat['files_infected']++;
|
$this->out(self::ANSI_RED, 'ER', $hash, $safe_path, $pattern);
|
||||||
$this->out(self::ANSI_RED, 'ER', $path . ' -> ' . $toSearch . ' ' . $hash);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
else {
|
||||||
|
if (!$this->flagHideOk) {
|
||||||
|
$this->out(self::ANSI_GREEN, 'OK', $blank_hash, $safe_path, $blank_pattern);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function isIgnored($pathname)
|
private function isIgnored($pathname)
|
||||||
@@ -274,9 +309,9 @@ class MalwareScanner
|
|||||||
return (bool)preg_match($expr, $path);
|
return (bool)preg_match($expr, $path);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function out($color, $serv, $text)
|
private function out($color, $serv, $hash, $path, $pattern)
|
||||||
{
|
{
|
||||||
echo $color . ' ' . $serv . ' ' . self::ANSI_OFF . $text . PHP_EOL;
|
echo $color . '#' . ' ' . $serv . self::ANSI_BLUE . " $hash " . self::ANSI_OFF . "# " . $path . $color . ' # ' . $pattern . self::ANSI_OFF . PHP_EOL;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function showHelp()
|
private function showHelp()
|
||||||
@@ -290,8 +325,10 @@ class MalwareScanner
|
|||||||
echo ' -w --hide-whitelist Hide whitelisted messages' . PHP_EOL;
|
echo ' -w --hide-whitelist Hide whitelisted messages' . PHP_EOL;
|
||||||
echo ' -x --extra-check Adds GoogleBot and htaccess to Scan List' . 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 ' -l --follow-symlink Follow symlinked directories' . PHP_EOL;
|
||||||
|
echo ' -v --verbose Continue scanning file afater first hit' . PHP_EOL;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
new MalwareScanner();
|
new MalwareScanner();
|
||||||
|
?>
|
||||||
|
|||||||
Reference in New Issue
Block a user