页面提示需要输入以lw1ar7AWmn开头的20位字符串才能获得flag,查看页面源码发现check.php
访问check.php,发现源码
伪随机数
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);
}
可以发现这里是使用mt_rand()来随机生成字符串,但是mt_rand()存在一个问题,同一个种子下随机生成的随机数值是相同的,只要获得了seed值就可以生成相同的字符串
CTF| web篇之伪随机数
mt_rand()存在的问题:
由于mt_rand()的生成的随机数只跟seed和调用该函数的次数有关。假设使用mt_srand(1111111)进行了一次播种操作,接下来调用mt_rand()函数,第一次生成的数值为a,第二次生成的为b,第三次生成的为c。任何一个人拿到这样的一串代码,所执行的结果都是跟刚刚描述的一样。所以当你的seed数值被他人知道后,就可以预测出你接下来的数值是多少,这就是该函数的一个问题,他并不能起到一个真随机数的作用。
获取seed
php_mt_seed可以根据一串int 或者一串由许多4个一组的数字组成的数据爆破出seed
根据已有字符串转换数据
php_mt_seed需要的是一串由许多4个一组的数字组成的数据,所以需要根据已有字符串进行转换
str1 = "lw1ar7AWmn"
str2 = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
length = 61
result = ''
for i in range(0, len(str1)):
for j in range(0, len(str2)):
if str1[i] == str2[j]:
result += str(j) + ' ' + str(j) + ' ' + '0' + ' ' + str(length) + ' '
break
print(result)
11 11 0 61 22 22 0 61 27 27 0 61 0 0 0 61 17 17 0 61 33 33 0 61 36 36 0 61 58 58 0 61 12 12 0 61 13 13 0 61
4个一组的数字格式
前面两个数是随机数的结果区间,后两位是随机数的随机范围区间,中间以一个空格为间隔
前面两个数是随机数的结果区间:str1在str2的位置,两位都一位
后两位是随机数的随机范围区间:str2的范围,每组都是一样,str2有62位,因为从0开始计数所以为61
爆破seed
./php_mt_seed 11 11 0 61 22 22 0 61 27 27 0 61 0 0 0 61 17 17 0 61 33 33 0 61 36 36 0 61 58 58 0 61 12 12 0 61 13 13 0 61
使用php_mt_seed爆破出seed为156489612
计算完整字符串
<?php
mt_srand(156489612);
$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;
?>
计算出20位完整字符串为lw1ar7AWmnI0Pp0fPEOC
获取flag
flag{8f018bcf-6b8d-4228-b246-8cd0eaeb83d0}
标签:WEB,随机数,61,mt,GWCTF,seed,2019,str,rand
From: https://www.cnblogs.com/scarecr0w7/p/17377296.html