标签:utf-8 alt 实践 输入 截取 flag 还原 区间 获得
直接看源码,发现输入的值会被POST的check.php:
访问一下Check.php,给了源码:
分析吧。
<?php
#这不是抽奖程序的源代码!不许看!
header("Content-Type: text/html;charset=utf-8");
session_start();
if(!isset($_SESSION[‘seed‘])){
$_SESSION[‘seed‘]=rand(0,999999999);
}
mt_srand($_SESSION[‘seed‘]);
$str_long1 = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
$str=‘‘;
$len1=20;
for ( $i = 0; $i < $len1; $i++ ){
$str.=substr($str_long1, mt_rand(0, strlen($str_long1) - 1), 1);
}
$str_show = substr($str, 0, 10);
echo "<p id=‘p1‘>".$str_show."</p>";
if(isset($_POST[‘num‘])){
if($_POST[‘num‘]===$str){x
echo "<p id=flag>抽奖,就是那么枯燥且无味,给你flag{xxxxxxxxx}</p>";
}
else{
echo "<p id=flag>没抽中哦,再试试吧</p>";
}
}
show_source("check.php");
思路是:
如果没有session首先rand()
初始化session,然后作为种子传给mt_srand
.
之后构造20位密码,只截取前10位给你。
如果最后能POST正确的20位,获得flag。
那么关键就是,要根据给你的10位密码,反推出mt_srand
的种子是什么,从而依葫芦画瓢构造私钥。
之前做过的[MRCTF]Ezaudit里学习了这个问题,这回实践一波。
Step 1 因为要交给php_mt_seed
去跑,我们先把给的密码转成它能读懂的形式:
<?php
$pass = "2dHUhTubvf"; //密钥
$alphabet = ‘abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ‘;//字母表
$len = strlen($alphabet) - 1; //区间长度
for($j = 0; $j < strlen($pass); $j++) //遍历密钥,确定当前字符在密钥的顺序
{
for ($i = 0; $i <= $len; $i++) { //遍历字母表,确定当前字符在字母表的顺序
if($pass[$j] == $alphabet[$i])//是找到了对应的随机数
{
echo "$i $i 0 $len "; //输出符合要求的参数格式
break;
}
}
}
?>
获得结果:
28 28 0 61 3 3 0 61 43 43 0 61 56 56 0 61 7 7 0 61 55 55 0 61 20 20 0 61 1 1 0 61 21 21 0 61 5 5 0 61
Step 2 利用php_mt_seed
去爆破种子:
成功获得种子。注意有版本要求 PHP 7.1.0+
Step3 还原:
<?php
mt_srand(119825810);
$str_long1 = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
$str=‘‘;
$len1=20;
for ( $i = 0; $i < $len1; $i++ ){
$str.=substr($str_long1, mt_rand(0, strlen($str_long1) - 1), 1);
}
echo "$str";
?>
用phpstudy环境,在PHP 7.1.13下跑出来的结果:
前10位完美匹配,爆破成功:
Step 4
提交
flag到手:
这道题当初比赛的时候没做出来(整个就做出来一道Web……)。
最近刷了不少题,做到这个了,尝试一波,没想到拿下了。
而且还考的是之前刷题时研究过的知识点。挺高兴的,记录一下!希望之后更进一步!
标签:utf-8 alt 实践 输入 截取 flag 还原 区间 获得
原文地址:https://www.cnblogs.com/keelongz/p/12643834.html