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

1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长! 2. 分享目的仅供大家学习和交流,请务用于商业用途! 3. 如果你也有好源码或者教程,可以到用户中心发布,分享有积分奖励和额外收入! 4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解! 5. 如有链接无法下载、失效或广告,请联系管理员处理! 6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需! 7. 如遇到加密压缩包,默认解压密码为"gltf",如遇到无法解压的请联系管理员! 8. 因为资源和程序源码均为可复制品,所以不支持任何理由的退款兑现,请斟酌后支付下载 声明:如果标题没有注明"已测试"或者"测试可用"等字样的资源源码均未经过站长测试.特别注意没有标注的源码不保证任何可用性