📜 ⬆️ ⬇️

Cleaning infected site files from malicious code. Continuation

Good afternoon, dear Habrayuzer!

This article is a logical continuation of this article . In one of the comments to it, left by the user Agel_Nash was indicated a new virus signature. Files subject to attack - * .js.

Several sites of our clients, which did not follow our recommendations to change FTP accesses, clean their cars from malware and change FTP, were infected with this virus. The following code is written to the * .js file: pastebin.com/2PWJycAd . It is placed in one line and strictly at the end of the file.
')
With the help of simple manipulations, the code was deobfuscated. For those who are interested, I post a readable view: of the given code (the same code was already indicated by MrMYSTIC ).
Deobfuscation was carried out in the simplest way. I went to jsfiddle and, instead of eval, brought the generated code to the page. It does simple manipulations, namely the following: Generates the path to the * .js file using url = 305yoy.bdcfwpndqm.is-a-therapist.com/g/, then collects the script element with the resulting path and adds it to the head of the page, to which worked.

To clean the sites I used the scanner, about which I wrote in the last article. However, I decided to “brush” it a little, taking into account the comments in the comments. Special thanks for the constructive criticism of charon and pro100tak (would put + if you could vote).

The algorithm is old, it works line by line in files. Therefore, it was necessary to identify for what to catch the scanner.

Based on the specified Agel_Nash , however, the scanner showed an unexpectedly small number of infected files. Strange, because even if not thousands, but there are hundreds of * .js files in the project. Began to dig and true, trust but verify. The selected signature was not met everywhere because it is not finite. Selectively checking several files in different distances from each other to directories, a couple of options were identified:
)try{Boolean().prototype.q}catch(egewgsd){f=[ 

and
 )try{Date().prototype.q}catch(egewgsd){f=[ 

The difference is small and consists of two words:
 Date()  Boolean() 

Supposedly, all types of data can be moved in this way: dates, numbers, strings, and so on. Well, then take the rest of the line, namely:
 ().prototype.q}catch(egewgsd){f=[ 

This time the scanner showed all the files that were infected with this virus. Exactly what is needed! It remains to check the Jquery, fancybox and a few other libraries used. Pure ... No occurrences found in their source code. Great, you can use.

Slightly reworked the scanner and launched. He again worked as planned, did not disappoint.

Changes:
- began to collect a list of signatures (at the moment there are two of them, you can run the scanner without the required string parameter);
- indicates which of the signatures found in the file;
- added function to delete backups (delete_backups ());
- the function call can be performed without parameters (in this case, the default values ​​are used):
  $dron->find(); $dron->scan(); $dron->restore_backups(); $dron->delete_backups(); 

- added functionality to change the owner of the directory while working with her scanner, but I commented out this section. It was not possible to test:
  /* //     $unformated_path_stat = stat($path); $path_stat = posix_getpwuid($unformated_path_stat['uid']); $path_user_name = $path_stat['name']; //     chown($path, 'www'); */ ... //     // chown($path, $path_user_name); 

- the function dir_content () is added which collects all files into an array, which is subsequently used by all other functions;
- when scanning ignores itself.

I give the code of the updated scanner, with detailed comments:
 <? /* ---------------------------------------------------------------------------------- dScaner Class - START ---------------------------------------------------------------------------------- */ /** * @param : dScaner * @param :          *    * * @param :   * @param  : 0.0.5 (13-04-2012) * */ Class dScaner { //   private $arr_files = array(); //     public $signatures = array( '=Array.prototype.slice.call(arguments).join(""),', '().prototype.q}catch(egewgsd){f=[' ); /** *      * * @param string $get_str   * @param string $separator     * @return array -    FALSE */ function request($get_str, $separator) { if (!empty($get_str)) { //        $obj = explode($separator, $get_str); return $obj; } else { return false; } } /** *       * * @param string $path -   ,      * @param string $files_allowed -  ,    */ function dir_content($path = './', $files_allowed = '.') { //      ,    $dir_disallow = array('.', '..', '.htaccess', '.git', 'zlordwaters'); if(is_dir($path)) { $temp = opendir($path); while (false !== ($dir = readdir($temp))) { if ((is_dir($path . $dir)) && (!in_array($dir, $dir_disallow)) ) { //   -   $sub_dir = $path . $dir . '/'; $this->dir_content($sub_dir, $files_allowed); } elseif ((is_file($path . $dir)) && (!in_array($dir, $dir_disallow)) && (strpos($dir, $files_allowed) == true) && (strpos($dir, '_BACKUP') == false) && (strpos($dir, trim($_SERVER['SCRIPT_NAME'], '/')) === false) ) { //  ,     $this->arr_files[] = $path . $dir; } } closedir($temp); } } /** *       : * * @param string $path -   ,      * @param string $files_allowed -  ,    * @param string $requested_string -   */ function find($path = './', $files_allowed = '.', $requested_string = '().prototype.q}catch(egewgsd){f=[') { //      $this->dir_content($path, $files_allowed); foreach($this->arr_files AS $in_dir_file) { //     $temporary_file = file_get_contents($in_dir_file); //      $file_founded = false; //     $tf_strings = explode("\n", $temporary_file); //    foreach ($tf_strings AS $item) { //     $item = strval($item); if (strpos($item, $requested_string) !== false) { $file_founded = true; $founded_str = $requested_string; } //     foreach ($this->signatures AS $signa) { $signa = strval($signa); if (strpos($item, $signa) !== false) { $file_founded = true; $founded_str = $signa; } } } //      if ($file_founded) { //         print "<span style='display:block; padding:5px; border:1px solid #1f4f18; background-color:#d5f5ce; font-size:12px; line-height:16px; font-family:tahoma, sans-serif; margin-bottom:-15px;'><h3>" . $in_dir_file . "</h3>     . <br> C: <b>" . $founded_str . "</b> </span><br>"; } } } /** *    : * * @param string $path -   ,      * @param string $files_allowed -  ,    * @param string $requested_string - ,       */ function scan($path = './', $files_allowed = '.', $requested_string = '().prototype.q}catch(egewgsd){f=[') { //      $this->dir_content($path, $files_allowed); foreach($this->arr_files AS $in_dir_file) { //     $temporary_file = file_get_contents($in_dir_file); //    $create_backup = false; //         $tf_strings = explode("\n", $temporary_file); //    $str_index = 0; //     foreach ($tf_strings AS $item) { //     $item = strval($item); if (strpos($item, $requested_string) !== false) { //        //   ,      $create_backup = true; //       unset($tf_strings[$str_index]); $founded_str = $requested_string; } //     foreach ($this->signatures AS $signa) { $signa = strval($signa); if (strpos($item, $signa) !== false) { //        //   ,      $create_backup = true; //       unset($tf_strings[$str_index]); $founded_str = $signa; } } //     $str_index++; } //   if ($create_backup) { /* //     $unformated_path_stat = stat($path); $path_stat = posix_getpwuid($unformated_path_stat['uid']); $path_user_name = $path_stat['name']; //     chown($path, 'www'); */ //              chmod($path, 0777); //     $temp_file_backup = $in_dir_file.'_BACKUP'; //       file_put_contents($temp_file_backup, $temporary_file); //      $scanned_file = implode("\n", $tf_strings); //    if (file_put_contents($in_dir_file, $scanned_file)) { //   print "<span style='display:block; padding:5px; border:1px solid #1f4f18; background-color:#d5f5ce; font-size:12px; line-height:16px; font-family:tahoma, sans-serif; margin-bottom:-15px;'><h3>" . $in_dir_file . "</h3>  . (+ BACKUP) <br> C: <b>" . $founded_str . "</b> </span><br>"; } else { //    print "<span style='display:block; padding:5px; border:1px solid #822121; background-color:#ea7575; font-size:12px; line-height:16px; font-family:tahoma, sans-serif; margin-bottom:-15px;'><h3>" . $in_dir_file . "</h3>   . C: <b>" . $founded_str . "</b> </span><br>"; } //          755 chmod($path, 0755); //     // chown($path, $path_user_name); } } } /** *     * * @param string $path -   ,      * @param string $files_allowed -  ,    */ function restore_backups($path = './', $files_allowed = '.') { //      $this->dir_content($path, $files_allowed); foreach($this->arr_files AS $in_dir_file) { if (is_file($in_dir_file.'_BACKUP')) { //  ,    $temporary_file_from_backup = file_get_contents($in_dir_file.'_BACKUP'); //    if (file_put_contents($in_dir_file, $temporary_file_from_backup)) { //   unlink($_SERVER['DOCUMENT_ROOT'].'/'.$in_dir_file.'_BACKUP'); //   print "<span style='display:block; padding:5px; border:1px solid #1f4f18; background-color:#d5f5ce; font-size:12px; line-height:16px; font-family:tahoma, sans-serif; margin-bottom:-15px;'><h3>".$in_dir_file ."</h3> . </span><br>"; } else { //    print "<span style='display:block; padding:5px; border:1px solid #822121; background-color:#ea7575; font-size:12px; line-height:16px; font-family:tahoma, sans-serif; margin-bottom:-15px;'><h3>".$in_dir_file ."</h3>  . </span><br>"; } } } } /** *     * * @param string $path -   ,       * @param string $files_allowed -  ,    */ function delete_backups($path = './', $files_allowed = '.') { //      $this->dir_content($path, $files_allowed); foreach($this->arr_files AS $in_dir_file) { if (is_file($in_dir_file.'_BACKUP')) { //  ,   if (unlink($_SERVER['DOCUMENT_ROOT'].'/'.$in_dir_file.'_BACKUP')) { print " <span style='display:block; padding:5px; border:1px solid #1f4f18; background-color:#d5f5ce; font-size:12px; line-height:16px; font-family:tahoma, sans-serif; margin-bottom:-15px;'><h3>".$in_dir_file ."_BACKUP</h3> . </span><br>"; } else { //    print "<span style='display:block; padding:5px; border:1px solid #822121; background-color:#ea7575; font-size:12px; line-height:16px; font-family:tahoma, sans-serif; margin-bottom:-15px;'><h3>".$in_dir_file ."_BACKUP</h3>  . </span><br>"; } } } } } /* ---------------------------------------------------------------------------------- dScaner Class - END ---------------------------------------------------------------------------------- */ ?> 

Well, an example of use with basic search options.
 <? //    -  $dron = new dScaner; //       $dron->find('./', '.'); //   // $dron->scan('./', '.'); //    // $dron->restore_backups('./', '.'); //    // $dron->delete_backups('./', '.'); ?> 


That's all I wanted to share with you.
Clean servers to you and their stable operation.
Best Regards!

Source: https://habr.com/ru/post/141938/


All Articles