凌晨两点,码解密服务器日志里躺着一行刺眼的码解密eval(base64_decode(...))。我盯着那串乱码一样的码解密字符串,后颈发凉——客户网站被人挂了后门。码解密这行代码藏在一个看似正常的码解密缓存文件里,混在几百行PHP中间,码解密不仔细看根本发现不了。码解密
解密的码解密第一步永远是别急着跑脚本。先把代码复制出来,码解密肉眼扫一遍结构。码解密攻击者通常不会只留一个eval,码解密周边往往有配套的码解密混淆手法,比如字符串拼接、码解密十六进制编码、码解密甚至用注释夹带隐藏指令。码解密我见过最离谱的一次,后门代码被拆成几十段,散落在不同文件里,靠一个自定义函数在运行时拼装起来。
那次我花了三个小时才理清思路。真正起作用的不是某个神器,而是最笨的办法:把变量名全部重命名,逐行打印中间结果。PHP的eval就像个黑箱,你永远不知道它执行了什么。但如果你能拦截它执行前的字符串,就等于拿到了攻击者的剧本。方法很土,用临时文件替换eval函数,把参数写到日志里,再手动还原。
有个细节值得留意——很多新手拿到加密代码就直接扔给在线解密工具。工具确实能解开base64和简单的gzinflate,但对付真正的恶意代码远远不够。攻击者早就不玩单一编码了,他们用多层嵌套,外层是正常的业务逻辑,内层才是真正的payload。你解开了第一层,看到的还是一个函数调用,参数又是一串乱码,这时候就得靠耐心了。
我习惯用手工方式拆解。先格式化代码,把每个函数调用单独拎出来,再逐层剥。有一次遇到个用变量函数名加动态调用的案例,$a = 'str' . '_rot13',然后$a($b)。这种混淆其实不难破,关键是别被吓住。你只要记住一个原则:无论怎么加密,最终都要调用系统函数或者写文件,所以盯着system、exec、file_put_contents这些敏感函数跑不掉。
解到最里层时,往往是一段明文的PHP代码。这时候才算真正开始分析。后门通常干两件事:要么上传文件,要么执行命令。我见过一个特别狡猾的样本,它先检查当前请求的User-Agent,只有特定字符串才触发恶意逻辑,平时就是个无害的缓存文件。这种潜伏型后门最难防,因为你扫描的时候它不发作,一旦攻击者带着“暗号”访问,网站就成了他的肉鸡。
解密这件事,说到底就是跟攻击者玩心理战。他们费尽心思藏代码,就是为了拖延你的响应时间。但反过来想,代码既然要运行,就必须经过PHP解释器,这给了我们天然的突破口。用Xdebug跟踪执行流程,或者干脆在关键函数上打断点,看它实际调用了什么参数。有一次我监控到file_put_contents的目标路径是/tmp/sess_xxx,顺着查下去,发现攻击者利用PHP会话机制做文件包含,这招比直接写webshell隐蔽得多。
处理完代码,别急着收工。得溯源——这段后门怎么进来的?查访问日志,找上传接口的异常请求,看有没有利用已知漏洞的痕迹。我遇到过一个案例,后门是通过旧版插件的一个SQL注入点进来的,攻击者先拖库拿到管理员密码,再上传恶意主题文件。整个过程环环相扣,光清理文件不补漏洞,过两天又会被种新的。
说实话,每次解密都是一次学习机会。攻击者的手法在进化,从简单的base64到现在的PHP混淆器,但核心逻辑没变过——总得有个入口,总得有个出口。你要做的,就是找到那个入口堵上,顺着出口揪出真凶。这份工作没有捷径,拼的就是细心和耐心。下次再看到eval,别慌,泡杯茶,坐下来慢慢拆。