[GWCTF 2019]枯燥的抽奖
查看页面源码可以看到一段JS代码:
$(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();});
});
这段代码实现了一个与后端 check.php 交互的功能,通过 AJAX 提交用户输入,根据后端返回结果显示不同的提示信息。
通过抓包获取后端响应:
y5DXaGgCOC没抽中哦,再试试吧
<?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){xecho "<p id=flag>抽奖,就是那么枯燥且无味,给你flag{xxxxxxxxx}</p>";}else{echo "<p id=flag>没抽中哦,再试试吧</p>";}
}
show_source("check.php");
随机生成一个SESSION['seed']并且当作生成随机数的种子值。同一个种子每次运行随机生成的序列都是相同的:
但是在本题中种子值也是随机生成的,我们不知道。但是我们可以本地跑出来,因为给了我们随机序列的前十位。
种子随机范围太大了。跑不了一点。只能换个思路.......
用爆破工具php_mt_seed。首先将题中给出的前十位转换成原始数列:
<?php
$str_long1 = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
$max = strlen($str_long1)-1;
$min = 0;
$str = 'ZrNsqX9wYd';
for ($i = 0; $i < strlen($str); $i++) {$s = $str[$i];$num = strpos($str_long1, $s);if ($num !== false) {echo "$num $num $min $max "; //这是官方文档指定的格式}
}
得到
61 61 0 61 17 17 0 61 49 49 0 61 18 18 0 61 16 16 0 61 59 59 0 61 35 35 0 61 22 22 0 61 60 60 0 61 3 3 0 61
然后使用php7.1.1+使用该随机种子利用题目源码生成序列:
<?php
mt_srand(798533660);
$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_show = substr($str, 0, 20);
最后成功拿到flag。
总结一下:首先客户端网页源代码是由JS程序控制,需要通过抓包直接查看服务端响应获得源码提示。然后利用php_mt_seed工具爆破随机种子。