[GWCTF 2019]枯燥的抽奖
提交一个数字,network里发现提交给了check.php,访问:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 <?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中随机生成一个种子,如果种子确定,则后来生成的随机数也是确定的……
更改session,相同的session出现的字符串前十位不变
生成的字符串由种子确定的随机数确定,我们要从已有的几组数据中爆破出种子
本来想用php写个脚本,发现这个想法不现实,性能拉跨……
php_mt_seed-4.0 工具可以帮助我们完成破解,但首先我们要还原数据为合法的格式
一个参数
当只有一个参数的时候,这个参数代表mt_rand第一次输出的值。
两个参数
当有两个参数的时候,他们代表mt_rand第一次输出应该位于什么区间内。
第一个参数为最小值,第二个参数为最大值。
四个参数
前两个参数表示mt_rand第一次输出的区间,后两个参数表示mt_rand输出的区间。
多于五个参数
每四个参数一组,但是最后一组可以是1,2或4个参数。每一组引用对应的输出。
还原脚本:
1 2 3 4 5 6 7 8 9 10 11 str1='abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ' str2='' str3 = str1[::-1 ] length = len(str2) res='' for i in range(len(str2)): for j in range(len(str1)): if str2[i] == str1[j]: res+=str(j)+' ' +str(j)+' ' +'0' +' ' +str(len(str1)-1 )+' ' break print (res)
第一次输出的区间:固定相同的两个数
mt_rand输出的区间:只能是0-61
放到php_mt_seed里:
得到seed,再根据seed找到完整字符串即可~