Задача найти все файлы которые задаем по маске , и удалить последнюю строку.

funman

Знаток
Регистрация
28 Дек 2007
Сообщения
163
Реакции
26
Добрый день!

У меня проблема, есть сайт на joomla, троян зарозил все JS файлы на сервере. пробовал удалять вручную , но файлов оч много.

Решением проблемы вижу написать на PHP скрипт который бы рекурсивно нашел все JS файлы на сервере, потом удалил последнюю строчку с вредоносным кодом. Код везде разный (переменные сформированы из случайных символов, но общая структура одинаковая и главное он находится в конце)

Из проблем по которым мне нужна ваша помощь вижу.
1) Как мне перебрать все файлы во всех директориях начиная с определенной заданной + нужно из этого списка исключить файлы которые к примеру были отредактированы какого числа (к примеру те что я чистил сегодня в ручную . так как у них последняя строчка уже явно будет не вирусная)

2) Как собственно наиболее быстрым способом удалять последнюю строчку , чтобы скрипт не вылетел по тайм-ауту и не сожрал всю память (файлы есть оч не маленькие)

Могу сюда прикрепить образец зараженного файла из которого нужно удалять код, если это поможет. Заранее всем спасибо за любую помощь.
 
Вот ,что получилось , все вроде работает, только проблема в том что у файлов права должны быть минимум 666, как сделать чтобы строчки удалялись у файлов с правами 644

PHP:
<?php
 
function scan_dir($dirname)
  {
    // Открываем текущую директорию
    $dir = opendir($dirname);
    // Читаем в цикле директорию
    while (($file = readdir($dir)) !== false)
    {
      // Если файл обрабатываем его содержимое
      if($file != "." && $file != "..")
      {
        // Если имеем дело с файлом - производим в нём замену
        if(is_file($dirname."/".$file))
        {
//устанавливаем маску файла     
        if (preg_match("/.*?\.js/", "$file"))
          {
//устанавливаем фильтр на дату файла       
if (date ("dmy",filemtime($dirname."/".$file))=="080312"){
// - удаляем первую строку.
$lines = file($dirname."/".$file);
$last = sizeof($lines) - 1 ;
unset($lines[$last]);
$fp = fopen($dirname."/".$file, 'w');
fwrite($fp, implode('', $lines));
fclose($fp);
echo "файл $file " . date ("dmy",filemtime($dirname."/".$file)). "\n <br>";
}}
        }
        // Если перед нами директория, вызываем рекурсивно
        // функцию scan_dir
        if(is_dir($dirname."/".$file))
        {     
          scan_dir($dirname."/".$file);
        }
      }
    }
    // Закрываем директорию
    closedir($dir);
  }
$dirname = ".";
  scan_dir($dirname);  // Вызов рекурсивной функции
?>
 
что то вроде
Код:
function ReadFolderDirectory($dir, $why='file', $shotPath=false, $root_dir='', $listDir = array()) {
    # static $listDir;
    if ($shotPath)
        $root_dir = $dir;
 
    if ($handler = opendir($dir)) {
        while (($sub = readdir($handler)) !== FALSE) {
            if ($sub != "." && $sub != ".." && $sub != "Thumb.db") {
                if (is_file($dir . "/" . $sub) && $why == 'file') {
 
                    $listDir[] = str_replace($root_dir, '', $dir . "/" . $sub);
                } elseif (is_dir($dir . "/" . $sub)) {
 
                    if ($why == 'dir')
                        $listDir[] = str_replace($root_dir, '', $dir . "/" . $sub);
 
 
 
                    $listDir = ReadFolderDirectory($dir . "/" . $sub, $why, 0, $root_dir, $listDir);
                }
            }
        }
        closedir($handler);
    }
    return $listDir;
}
 
$ALL_DIRS = array();
$allFiles = ReadFolderDirectory(SCAN_DIR, 'file' );
echo "files: ".count($allFiles)."\n";
echo "<pre>";
//print_r($allFiles);
//exit;
foreach ($allFiles as $path) {
    // проверяем только js
    if(!preg_match('~\.js$~', $path )){
        continue; 
    }
   
    clearstatcache();
    // test file
    $file = file_get_contents(  $path);
    if (strpos($file, 'eval(base64_decode("="))')) {
 
        echo "$path Fix\n";
        $file_new = preg_replace('~eval\(base64_decode\(.*?\)\);~i', '', $file);
        file_put_contents($path, $file_new);
    } 
 
}
Примерно следующее, единственное -
переписываем 2 строки
if (strpos($file, 'eval(base64_decode("="))')) {
надо указать проверку, чтобы обнаружил вредоносный код в файле.
и
$file_new = preg_replace('~eval\(base64_decode\(.*?\)\);~i', '', $file);
это удаление в принципе, если только последнюю строку надо удалить- то заменяем на
$e = explode("\n", $file);
unset ($e[sizeof($e)-1]);
$file_new = implode("\n", $e);
------------
Память должен не жрать, Хотя может отвалится по времени. И вначале советовал бы отбекапить.
 
там нету Base64 вообще, код который сделал выше в принципе работает, только проблема что все JS имеют права 644, а для удаления строки нужно чтобы файлы имели права 666.

Как вариант думаю можно всем JS сменить владельца на "apache", или может есть какое то другое решение?

p.s. кому интересно прикладываю в архиве пример вредоносного кода, щас уже палится Каспером.

что то вроде
Код:
function ReadFolderDirectory($dir, $why='file', $shotPath=false, $root_dir='', $listDir = array()) {
    # static $listDir;
    if ($shotPath)
        $root_dir = $dir;
 
    if ($handler = opendir($dir)) {
        while (($sub = readdir($handler)) !== FALSE) {
            if ($sub != "." && $sub != ".." && $sub != "Thumb.db") {
                if (is_file($dir . "/" . $sub) && $why == 'file') {
 
                    $listDir[] = str_replace($root_dir, '', $dir . "/" . $sub);
                } elseif (is_dir($dir . "/" . $sub)) {
 
                    if ($why == 'dir')
                        $listDir[] = str_replace($root_dir, '', $dir . "/" . $sub);
 
 
 
                    $listDir = ReadFolderDirectory($dir . "/" . $sub, $why, 0, $root_dir, $listDir);
                }
            }
        }
        closedir($handler);
    }
    return $listDir;
}
 
$ALL_DIRS = array();
$allFiles = ReadFolderDirectory(SCAN_DIR, 'file' );
echo "files: ".count($allFiles)."\n";
echo "<pre>";
//print_r($allFiles);
//exit;
foreach ($allFiles as $path) {
    // проверяем только js
    if(!preg_match('~\.js$~', $path )){
        continue;
    }
 
    clearstatcache();
    // test file
    $file = file_get_contents(  $path);
    if (strpos($file, 'eval(base64_decode("="))')) {
 
        echo "$path Fix\n";
        $file_new = preg_replace('~eval\(base64_decode\(.*?\)\);~i', '', $file);
        file_put_contents($path, $file_new);
    }
 
}
Примерно следующее, единственное -
переписываем 2 строки
if (strpos($file, 'eval(base64_decode("="))')) {
надо указать проверку, чтобы обнаружил вредоносный код в файле.
и
$file_new = preg_replace('~eval\(base64_decode\(.*?\)\);~i', '', $file);
это удаление в принципе, если только последнюю строку надо удалить- то заменяем на
$e = explode("\n", $file);
unset ($e[sizeof($e)-1]);
$file_new = implode("\n", $e);
 

Вложения

  • mod_zooitem.rar
    4 KB · Просмотры: 3
Назад
Сверху