0%

[GWCTF_2019]枯燥的抽奖

[GWCTF 2019]枯燥的抽奖

伪随机数安全的一个题,通过php_mt_rand这个工具逆向出随机数种子,然后通过种子获取字符串

贴一下源码

<?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");

mt_rand(min,max)函数返回该区间内的任意一个数,通过如下脚本得到逆向所需数据,通过php_mt_rand工具爆破出种子

str1 = 'abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'
str2 = 'o117Ak7VLV'
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)

个人认为res就是还原了伪随机数生成的序列,四个数字一组,重复两遍随机结果,后接随机数范围(不知道为什么随机结果要重复两遍)

坑点

php不同版本随机数之间是有差距的,php_mt_rand工具会提示获取的种子对应的PHP版本,这个题跑出来的种子为PHP7版本的,我本地实验的时候选的PHP5的解释器,发现结果不对想了半天