BUUCTF刷题
相关知识:mt_rand——通过梅森旋转随机数生成器生成随机值
mt_rand(min,max)可以返回min到max之间的伪随机数。因为是伪随机数,这个随机数还是有规律的,通过种子,完全可以得到一串相同的伪随机数。
解题过程:
打开题目之后,我们得到如下信息
我们需要猜中字符串,才能得到flag
查看页面源代码,找到了“check.php”,得到源码
<?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这个函数,这个就是本题的考点。通过看WP看到了一篇大佬的博客:大佬博客
伪随机数:
伪随机数是用确定性的算法计算出来的随机数序列,它并不真正的随机,但具有类似于随机数的统计特征,如均匀性、独立性等。在计算伪随机数时,若使用的初值(种子)不变,那么伪随机数的数序也不变。伪随机数可以用计算机大量生成,在模拟研究中为了提高模拟效率,一般采用伪随机数代替真正的随机数。模拟中使用的一般是循环周期极长并能通过随机数检验的伪随机数,以保证计算结果的随机性。伪随机数的生成方法有线性同余法、单向散列函数法、密码法等。
mt_rand存在的安全问题:
mt_rand就是一个伪随机数生成函数,它由可确定的函数,通过一个种子产生的伪随机数。这意味着:如果知道了种子,或者已经产生的随机数,都可能获得接下来随机数序列的信息(可预测性)。因此只要我们能拿到题目中字符串的种子,就能获得这串字符串。
php_mt_seed——mt_rand 的克星:
php_mt_seed 可以通过mt_rand 的一部分输出结果算出mt_rand 的种子,从而可以还原出这一串字符串。
php_mt_seed 安装和使用(LINUX下,我用的kali)
下载链接:php_mt_seed – PHP mt_rand() seed cracker (openwall.com)下载4.0版本
(1)解压
tar -zxvf php_mt_seed-4.0.tar.gz
(2)进入php_mt_seed-4.0目录下,并为php_mt_seed.c赋予权限
chmod 777 php_mt_seed.c
(3)编译
make
(4)执行
./php_mt_seed 28 28 0 61 2 2 0 61 0 0 0 61 17 17 0 61 42 42 0 61 60 60 0 61 61 61 0 61 47 47 0 61 33 33 0 61 10 10 0 61
OK,工具准备妥当,下面开始正式解题。
因为php_mt_seed 执行时所需的数字比较特殊,因此我们需要将题目给出的字符串进行转码。(在这贴别人写的PY代码)
str1 ='题目所给的字符串'
str2 = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
result =''
length = str(len(str2)-1)
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' + ' ' + length + ' '
break
print(result)
执行后会得到一串数字
28 28 0 61 2 2 0 61 0 0 0 61 17 17 0 61 42 42 0 61 60 60 0 61 61 61 0 61 47 47 0 61 33 33 0 61 10 10 0 61
然后使用php_mt_seed就可以了
./php_mt_seed 28 28 0 61 2 2 0 61 0 0 0 61 17 17 0 61 42 42 0 61 60 60 0 61 61 61 0 61 47 47 0 61 33 33 0 61 10 10 0 61
这里还要注意一下php版本
最后就是借鉴一下题目的源码,写个脚本跑一下字符串了
<?php
mt_srand(646512206);
$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, 20);
echo "<p id='p1'>".$str_show."</p>";
?>
原文地址:http://www.cnblogs.com/paomianjiacha/p/16815069.html