知识点:

一些函数

session_start() 会创建新会话或者重用现有会话。
$_SESSION — Session 变量,当前脚本可用 SESSION 变量的数组。
rand() 函数返回随机整数。
mt_srand(seed)函数通过分发seed种子,然后种子有了后,靠mt_rand()生成随机数。

PHP mt_rand函数

产生伪随机数。它产生随机数值的平均速度比 libc 提供的 rand() 快四倍。由可确定的函数,通过一个种子产生的伪随机数。可以通过种子/已产生的随机数来获得接下来的序列信息。有两个可选参数 min 和 max,如果没有提供可选参数,mt_rand函数将返回返回 0 到 mt_getrandmax() 之间的伪随机数。

破解工具:php_mt_seed是一个破解mt_rand函数seed的工具。参数说明:四个参数(高级模式)下,前两个参数表示mt_rand第一次输出的区间,后两个参数表示mt_rand输出的区间。

link:https://www.freebuf.com/vuls/192012.html

解题:

Ctrl+U查看源代码(坑)

<script type="text/javascript">
$(document).ready(function(){
$("#div1").load("check.php #p1");

$(".close").click(function(){
$("#myAlert").hide();
});

$("#button1").click(function(){
$("#myAlert").hide();
guess=$("input").val();
$.ajax({
type: "POST",
url: "check.php",
data: "num="+guess,
success: function(msg){
$("#div2").append(msg);
alertmsg = $("#flag").text();
if(alertmsg=="没抽中哦,再试试吧"){
$("#myAlert").attr("class","alert alert-warning");
if($("#new").text()=="")
$("#new").append(alertmsg);
}
else{
$("#myAlert").attr("class","alert alert-success");
if($("#new").text()=="")
$("#new").append(alertmsg);
}


}
});
$("#myAlert").show();
$("#new").empty();
$("#div2").empty();
});
});
</script>

发现包含了check.php,直接访问得

C0WhH1dqUB

<?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");

审计源码

开启会话后,判断session中seed值是否为空,是则用rand函数生成一个值,再将其作为mt_srand()的种子,之后利用$str_long1和随机数生成一串字符,最后截取前10个字符呈现。

思路

由于我们可以通过工具进行爆破出种子,那么我们就可以重复操作得出完整的字符串

由题目选择,工具的模式(四个参数),前两个是第一次输出区间(即题目给的字符串对应的生成过程中的每个随机数),后两个是输出区间

生成格式脚本:

<?php
$pass_now = "TxnDsJjdHq";
$allowable_characters = 'abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';

$length = strlen($allowable_characters) - 1;

for ($j = 0; $j < strlen($pass_now); $j++) {
for ($i = 0; $i < $length; $i++) {
if ($pass_now[$j] == $allowable_characters[$i]) {
echo "$i $i 0 $length ";
break;
}
}
}
//55 55 0 61 23 23 0 61 13 13 0 61 39 39 0 61 18 18 0 61 45 45 0 61 9 9 0 61 3 3 0 61 43 43 0 61 16 16 0 61

用工具爆破。

工具下载到Linux中:git clone https://github.com/openwall/php_mt_seed.git  进入目录 make一下,然后使用 
./php_mt_seed 55 55 0 61 23 23 0 61 13 13 0 61 39 39 0 61 18 18 0 61 45 45 0 61 9 9 0 61 3 3 0 61 43 43 0 61 16 16 0 61 后得到不同版本的。
种子得是PHP7.1以上的(找不到哪里显示PHP版本,可能都试一试?)
得到种子:773675551
工具官网(https://www.openwall.com/php_mt_seed/)

后再用题目脚本来得出字符串

<?php
mt_srand(773675551);

$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;
>
//TxnDsJjdHqtrEByP1KYl (版本也得是7.1以上的)

最后根据题目post一下就有了。