美文网首页
[PHP] Webshell简单的免杀思路

[PHP] Webshell简单的免杀思路

作者: w_w_wei | 来源:发表于2018-08-02 09:12 被阅读0次

接到一个简单的需求, 客户自己的扫描工具把我们的代码,误认为是webshell。经过简单排查, 确认了误报 原因, 这个确认思路,也可以作为webshell的免杀思路。

前提条件是,源码类型的webshell,没有经过加密的。
而且代码被杀软识别成webshell

思路

  1. 截取文件部分代码,然后对文件进行扫描, 如果不报毒,则表示存在特征码使得代码被识别为webshell。
  2. 截取文件部分代码,然后对截取进行扫描, 如果报毒,则表示存在特征码使得代码被识别为webshell。
  3. 在代码中随机截取一定数量行的代码,生成样本, 对大量的样本进行扫描,再对有毒样本,进行思路1方法处理。

再对代码量相对比较小的样本,进行人工分析, 基本是可以完全找出所有的特征码关键字。

代码片段

之前排查问题写的一些代码片段。

#1 截取文件部分代码,然后对文件进行扫描
<?php
ini_set('display_errors', 'On');
/**
* 特征码查找
*/
class KeyFind {
    public $config;
    public $valider = null;
    public $filepath = '';
    public $file = null;

    public function __construct($config)
    {
        $default_config = array(
            'line'          => 3,
            'source_file'   => '',
            'source_dir'    => dirname(__FILE__) . '/',
            'dest_file'         => dirname(__FILE__) . '/dest/file.php',
            'log_file'      => dirname(__FILE__) . '/log.txt'
        );
        $this->config = array_merge($default_config, $config);
    }
    //记录日志
    public function log( $info ){
        if (!file_exists($this->config['log_file'])) {
            $myfile = fopen($this->config['log_file'], "w") or die("Unable to open file!");
            $txt = "log\n";
            fwrite($myfile, $txt);
            fclose($myfile);
        }
        file_put_contents($this->config['log_file'], $info, FILE_APPEND);
    }
    public function _desturct() {
        // if (!is_null($this->file)) {
        //  $this->file = null;
        // }
    }
public function valider()
    {
        $number = 0;
        $command = "./webshellscanner -d dest";
        exec($command, $output);
        foreach( $output as $str) {
                if ( preg_match('/发现webshell数量(.*?)(\d{1,})(.*?)$/', $str, $matches)) {
                        $number = $matches[2];
                }
        }
        return $number;
    }
public function fileCreate($array, $temp_str)
    {
        file_put_contents($this->config['dest_file'], implode("",$array));
    }
    /**
    * 打开文件
    */
    public function preCheck() {
        $this->filepath = $this->config['source_dir'] . $this->config['source_file'];
        if (empty($this->config['source_file'])
            || !file_exists($this->filepath)) {
            throw new Exception('File ['.$this->filepath.'] not Exists');
        }
        // if (is_null($this->valider)) {
        //  throw new Exception('Valider not Set');
        // }
        //$this->filepath = $this->config['source_dir'] . $this->config['source_file'];
        // $this->file = new SplFileObject($this->filepath, 'r');  
    }
    public function readFile() {
        $array = array();
        $file = new SplFileObject($this->filepath, 'r');  
        while (!$file->eof()) {
            $array[] = $file->current();
            $file->next();
          }
        $file = null;
        return $array;
    }
public function search() {
        $this->preCheck();
        $problem = array();
        
        $array = $this->readFile($this->filepath);
        $line_count = count($array);
        $line_deal = $this->config['line'];
        $temp_str = '';
        for ( $i=0; $i<$line_count; $i=$i+$line_deal) {
            //置空
            $temp_str = $array[$i];
            $array[$i] = '';
            for ( $j=1; $j<$line_deal; $j++) {
                $temp_str = $temp_str . $array[$i+$j];
                $array[$i+$j] = '';
            }
            //$temp_str = $array[$i];
            $this->fileCreate($array, $temp_str);
            if ( $this->valider($this->config['dest_file']) ) {
                // 存在关键字
                $this->log( $i . ' line  exists key' . "\r\n");
            } else {
                $this->log( $i . ' line  nonexists key' . "\r\n");
            }

            unlink($this->config['dest_file']);
            if (file_exists($this->config['dest_file'])) {
                die('file not delete');
            }

            //恢复数据
            $temp_list = explode("\r\n", $temp_str);
            $temp_str = '';
            for ( $j=0; $j<$line_deal; $j++) {
                if ($array[$i+$j] != '') {
                    echo 'error';
                }
                $array[$i+$j] = $temp_list[$j] . "\r\n";
            }
            $temp_list = array();
        }
    }

}
if ( $argc < 2 ) {
    echo "\r\n Usage : scan.php file_need_scan";
    exit();
}
$config = array(
    'source_file' => $argv[1]
);
$search = new KeyFind($config);
$search->search();
#2 截取文件部分代码,然后对截取的代码进行扫描
<?php
ini_set('display_errors', 'On');
/**
* 特征码查找
*/
class KeyFind {
    public $config;
    public $valider = null;
    public $filepath = '';
    public $file = null;

    public function __construct($config)
    {
        $default_config = array(
            'line'          => 100,
            'source_file'   => '',
            'source_dir'    => dirname(__FILE__) . '/',
            'dest_file'         => dirname(__FILE__) . '/dest/file.php',
            'log_file'      => dirname(__FILE__) . '/log.txt',
'result_dir'    => dirname(__FILE__) . '/result/'
        );
        $this->config = array_merge($default_config, $config);
    }
    //记录日志
    public function log( $info ){
        if (!file_exists($this->config['log_file'])) {
            $myfile = fopen($this->config['log_file'], "w") or die("Unable to open file!");
            $txt = "log\n";
            fwrite($myfile, $txt);
            fclose($myfile);
        }
        file_put_contents($this->config['log_file'], $info, FILE_APPEND);
    }
    public function _desturct() {
        // if (!is_null($this->file)) {
        //  $this->file = null;
        // }
    }
public function valider()
    {
        $number = 0;
        $command = "./webshellscanner -d dest";
        exec($command, $output);
        foreach( $output as $str) {
                if ( preg_match('/发现webshell数量(.*?)(\d{1,})(.*?)$/', $str, $matches)) {
                        $number = $matches[2];
                }
        }
        return $number;
    }
public function fileCreate($array, $temp_str)
    {
        if ($dest_file == '') {
            $dest_file = $this->config['dest_file'];
        }
        file_put_contents($dest_file, "<?php", FILE_APPEND);
        file_put_contents($dest_file, $temp_str, FILE_APPEND);
    }
    /**
    * 打开文件
    */
    public function preCheck() {
        $this->filepath = $this->config['source_dir'] . $this->config['source_file'];
        if (empty($this->config['source_file'])
            || !file_exists($this->filepath)) {
            throw new Exception('File ['.$this->filepath.'] not Exists');
        }
        // if (is_null($this->valider)) {
        //  throw new Exception('Valider not Set');
        // }
        //$this->filepath = $this->config['source_dir'] . $this->config['source_file'];
        // $this->file = new SplFileObject($this->filepath, 'r');  
    }
    public function readFile() {
        $array = array();
        $file = new SplFileObject($this->filepath, 'r');  
        while (!$file->eof()) {
            $array[] = $file->current();
            $file->next();
          }
        $file = null;
        return $array;
    }
public function search() {
        $this->preCheck();
        $problem = array();
        
        $array = $this->readFile($this->filepath);
        $line_count = count($array);
        $line_deal = $this->config['line'];
        $temp_str = '';
        for ( $i=0; $i<$line_count; $i=$i+$line_deal) {
            //$temp_str = $array[$i];
            $this->fileCreate($array, $temp_str);
            if ( $this->valider($this->config['dest_file']) ) {
                // 存在关键字
                $this->log( $i . ' line  exists key' . "\r\n");
                echo "发现异常代码串" . "\r\n";
                $this->fileCreate($array, $temp_str, $this->config['result_dir'] . rand(1000,9999) . time() . '.php');
            } else {
                $this->log( $i . ' line  nonexists key' . "\r\n");
            }

            unlink($this->config['dest_file']);
            if (file_exists($this->config['dest_file'])) {
                die('file not delete');
            }
        }
    }

}
if ( $argc < 2 ) {
    echo "\r\n Usage : scan.php file_need_scan";
    exit();
}
$config = array(
    'source_file' => $argv[1]
);
$search = new KeyFind($config);
$search->search();
#3 生成随机样本
<?php
ini_set('display_errors', 'On');
/**
* 特征码查找
*/
class KeyFind {
    public $config;
    public $valider = null;
    public $filepath = '';
    public $file = null;

    public function __construct($config)
    {
        $default_config = array(
            'line'          => 100,
            'source_file'   => '',
            'source_dir'    => dirname(__FILE__) . '/',
            'dest_file'         => dirname(__FILE__) . '/dest/file.php',
            'log_file'      => dirname(__FILE__) . '/log.txt',
'result_dir'    => dirname(__FILE__) . '/result/'
        );
        $this->config = array_merge($default_config, $config);
    }
    //记录日志
    public function log( $info ){
        if (!file_exists($this->config['log_file'])) {
            $myfile = fopen($this->config['log_file'], "w") or die("Unable to open file!");
            $txt = "log\n";
            fwrite($myfile, $txt);
            fclose($myfile);
        }
        file_put_contents($this->config['log_file'], $info, FILE_APPEND);
    }
    public function _desturct() {
        // if (!is_null($this->file)) {
        //  $this->file = null;
        // }
    }
public function valider()
    {
        $number = 0;
        $command = "./webshellscanner -d dest";
        exec($command, $output);
        foreach( $output as $str) {
                if ( preg_match('/发现webshell数量(.*?)(\d{1,})(.*?)$/', $str, $matches)) {
                        $number = $matches[2];
                }
        }
        return $number;
    }
public function fileCreate($array, $temp_str)
    {
        if ($dest_file == '') {
            $dest_file = $this->config['dest_file'];
        }
        file_put_contents($dest_file, "<?php", FILE_APPEND);
        file_put_contents($dest_file, $temp_str, FILE_APPEND);
    }
    /**
    * 打开文件
    */
    public function preCheck() {
        $this->filepath = $this->config['source_dir'] . $this->config['source_file'];
        if (empty($this->config['source_file'])
            || !file_exists($this->filepath)) {
            throw new Exception('File ['.$this->filepath.'] not Exists');
        }
        // if (is_null($this->valider)) {
        //  throw new Exception('Valider not Set');
        // }
        //$this->filepath = $this->config['source_dir'] . $this->config['source_file'];
        // $this->file = new SplFileObject($this->filepath, 'r');  
    }
    public function readFile() {
        $array = array();
        $file = new SplFileObject($this->filepath, 'r');  
        while (!$file->eof()) {
            $array[] = $file->current();
            $file->next();
          }
        $file = null;
        return $array;
    }
    /**
     * 生成随机行数
     *
     * @param [type] $line_count
     * @param [type] $line_deal
     * @return void
     */
    public function getRandLine($line_count, $line_deal)
    {
        if ( $line_count <= $line_deal) {
            die('fatel error!!!!');
        }
        $line_array = array(); //保存行数
        // 生成行数
        for ( $i=0; $i<$line_deal; $i++) {
            $rand_line = rand(1,$line_count-1);             //不需要第0行 <?php
            while( in_array($rand_line, $line_array) )  {
                $rand_line = rand(1, $line_count-1);
            }
            $line_array[]= $rand_line;
            
        }
        return $line_array;
    }
    /**
     * 文件创建
     *
     * @param [type] $array
     * @param [type] $line_array
     * @return void
     */
    public function createSample($array, $line_array)
    {
        $dir = $this->config['result_dir'];
        $lines = join(',', $line_array);
        $file = $dir . md5($lines) . '.php';

        file_put_contents($file, '<?php');
        file_put_contents($file, "//$lines", FILE_APPEND);
        $temp_str = '';
        foreach( $line_array as $line) {
            $temp_str .= $array[$line];
        }
        file_put_contents($file, $temp_str, FILE_APPEND);
    }

public function search() {
        $this->preCheck();
        $problem = array();
        
        $array = $this->readFile($this->filepath);
        $line_count = count($array)-1;
        $line_deal = $this->config['line'];
        $temp_str = '';
        $line_array = $this->getRandLine($line_count, $line_deal); //保存行数
        $this->createSample($array, $line_array);
        for ( $i=0; $i<10000;$i++) {
            $line_array = array();
            $line_array = $this->getRandLine($line_count, $line_deal); //保存行数
            $this->createSample($array, $line_array);
        }
    }

}
if ( $argc < 2 ) {
    echo "\r\n Usage : scan.php file_need_scan";
    exit();
}
$config = array(
    'source_file' => $argv[1]
);
$search = new KeyFind($config);
$search->search();

实现了简单的脚本辅助手工确认特征码, 根据这个思路,应该是可以做到自动化的

相关文章

  • [PHP] Webshell简单的免杀思路

    接到一个简单的需求, 客户自己的扫描工具把我们的代码,误认为是webshell。经过简单排查, 确认了误报 原因,...

  • 无限免杀D盾脚本之aspx ——yzddMr6

    前言 自己曾经写过一篇文章:利用随机异或无限免杀某盾 php的webshell免杀方法有很多,但是市面上很少有讲a...

  • Webshell免杀

    前言 最近在研究php免杀绕过安全狗、D盾等WAF防护软件。也算是小有成绩。故记录下来。 一句话木马 在渗透测试中...

  • webshelle免杀套路

    转载自:https://nosec.org/home/detail/2574.html webshell免杀套路 ...

  • webshell以及免杀方式

    Webshell简介 Webshell就是以asp、php、jsp或者cgi等网页文件形式存在的一种代码执行环境,...

  • webshell

    kali中存放webshell的目录为/usr/share/webshell 反弹型webshell 例:php-...

  • 安全实战:webshell的几种免杀方式

    php的免杀 传统的php免杀不用多说了 无非就是各种变形和外部参数获取,对于一些先进的waf和防火墙来说,不论如...

  • 初识webshell及免杀基础

    初识Webshell: 上传Webshell的目的: 1.权限维持,方便下次连接控制系统2.权限提升,利用某些漏洞...

  • webshell多种方法免杀

    转载自公众号:开源聚合网络空间安全研究院 webshell这个东西对于web方向的还是极其重要的,getshell...

  • Jsp Webshell 免杀-命令执行

    前言 php的一句话木马即可以直接命令执行又可以作为冰蝎、蚁剑的客户端,而java就显得比较复杂。在经过java基...

网友评论

      本文标题:[PHP] Webshell简单的免杀思路

      本文链接:https://www.haomeiwen.com/subject/aptpsftx.html