Posted on 

php伪随机数

php伪随机数

// 图裂
题目给了一个简短的字符串,但是一共有二十位,所以后面有一部分需要自己爆出来
爆源码的多种姿势后。。

源码显示随机生成了一个字符串,所以要通过伪随机数的预测来破解
相关函数:

1
2
mt_rand( void) : int
mt_rand( int $min, int $max) : int

缺陷:生成的随机数跟seed和调用该函数的次数有关,也就是只要种子是一样的,任何人拿该种子去生成的随机数都是可预测的,顾名思义伪随机数
所以解决方法就是要找到该种子

1
mt_srand([ int $seed] ) : void

用 seed 来给随机数发生器设置种子。 没有设定 seed 参数时,会被设为随时数(一般可以根据本地时间,来使得rand一类函数得到的数字达到随机的效果)。使用者在进行一次mt_srand()操作后,seed数值将被固定下来,给接下来的mt_rand()函数使用。

参考一篇解析原理的文章
https://www.freebuf.com/column/205240.html

使用工具:

1
http://www.openwall.com/php_mt_seed/

这里如果版本对应不正确是安排不了的,很奇怪
将压缩包拉到linux下

1
2
3
tar -zxvf php_mt_seed-4.0.tar.gz
cd到目录下后
make

这里顺便学习一下make命令
http://www.ruanyifeng.com/blog/2015/02/make.html

根据README,我们要将数据处理成便于种子爆破的格式,所以要根据源码写脚本进行数据处理,即获取”样本随机数”

https://github.com/lepiaf/php_mt_seed
根据源码的思路逆向
脚本:

1
2
3
4
5
6
7
8
9
str1 = 'abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'
str2 = 'Z7M56fQQBN'
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)

得到一串数据
进到目录里丢到php_mt_seed中

1
./php_mt_seed ....

可以得到种子和php版本

1
2
3
4
5
6
7
8
9
<?php
mt_srand(474122877);
$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 "<p id='p1'>".$str."</p>";

最后这里同样是要注意php的版本,只好即可得flag