函数介绍
mt_rand(),用于产生一个随机数,用Mersenne Twister算法的特性,有两个可选参数(min,max)
mt_rand(5,15)随机产生5-15之间的随机数
mt_rand()随机产生0-mt_getrandmax()之间的伪随机数
伪随机数:
伪随机数,并不是真正的随机,如果种子不变,那么这个伪随机数存在一定风险
mt_rand()安全问题:
mt_rand就是一个伪随机数生成函数,通过一个种子产生伪随机数,如果知道了种子,或者已经产生的随机数,都可能获得其他随机数的信息
假设mt_rand()生成算法为,rand=seed+(i*10),seed是种子,这是我们不知道的,i是第几次调用,如果我们知道rand(结果)和i(第几次调用)那么就能反推出来seed(种子)的值,拿到种子,就能利用种子,自己调用mt_rand()生成结果
[GWCTF 2019]枯燥的抽奖
进入题目,随手翻翻有什么东西。robots.txt。源代码。源码泄露。都看看
找到一个php文件。访问看看
OK。程序源码
这段代码就是根据rand函数随机生成一个seed(种子),然后去mt_rand生成随机数。然后把字符串前十个输出给我们
很明显。这题就是伪随机数。由于我们已经知道了前面10个字符。那么就可以通过php_mt_rand工具来破解
https://www.openwall.com/php_mt_seed/
我们先来通过那10个字符串转换为php_mt_seed可识别的格式
str1='abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'
#源代码中的字符串
str2='xaLyvX6QTh'
#给你的10个字符串
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)
得到结果
23 23 0 61 0 0 0 61 47 47 0 61 24 24 0 61 21 21 0 61 59 59 0 61 32 32 0 61 52 52 0 61 55 55 0 61 7 7 0 61
使用php_mt_seed来获取seed的值,这里我的seed值为751184378
用seed的值重新播种。注意。这里用PHP7.1.0+版本。才能获取正确结果
<?php
mt_srand(751184378);
$str1='abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
$len=20;
$str2='';
for($i=0;$i<$len;$i++){
$str2.=substr($str1,mt_rand(0,strlen($str1)-1),1);
}
echo $str2;
?>
就是照着源代码打一遍。只不过mt_srand换成我们已知的
拿到flag