有点搞笑的一道题,没太搞明白考察的知识点,完全凭一手骚操作做完了。。。
解题过程
打开题目进入主页面:
然后发现过一会后会跳转到/die/页面中:
到这里感觉应该是有一个时间判断的跳转过程,手快一点看一下第一个页面的源码:
<!DOCTYPE html>
<html>
<head>
<title>Welcome to Earth</title>
</head>
<body>
<h1>AMBUSH!</h1>
<p>You've gotta escape!</p>
<img src="/static/img/f18.png" alt="alien mothership" style="60vw;" />
<script>
document.onkeydown = function(event) {
event = event || window.event;
if (event.keyCode == 27) {
event.preventDefault();
window.location = "/chase/";
} else die();
};
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function dietimer() {
await sleep(10000);
die();
}
function die() {
window.location = "/die/";
}
dietimer();
</script>
</body>
</html>
不难看出是通过JavaScript来实现的页面跳转,做到这里其实最初考虑的是直接禁用Javascript,这样就能防止页面跳转,后来想起来用Burp抓包也是一样可以看到跳转前的页面源码的,从上面这个源码可以看出一旦超时就会跳转到/die/,当keyCode == 27的时候就会跳转到/chase/,讲道理,既然知道路径了直接访问/chase/就可以了,直接贴上/chase/的Javascript代码:
<script>
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function dietimer() {
await sleep(1000);
die();
}
function die() {
window.location = "/die/";
}
function left() {
window.location = "/die/";
}
function leftt() {
window.location = "/leftt/";
}
function right() {
window.location = "/die/";
}
dietimer();
</script>
进入/die/就凉了,然后我们继续访问/leftt/,发现一行注释:
<!-- <button onClick="window.location='/shoot/'">Take the shot</button> -->
继续访问/shoot/:
<button onClick="window.location='/door/'">Continue</button>
跟进/door/,发现源码中有一大堆选项,然后调用了check_door()函数:
没有直接发现Js代码,往上翻发现<script src="/static/js/door.js"></script>
js代码放在了/static/js/door.js这个文件里,直接访问这个文件:
function check_door() {
var all_radio = document.getElementById("door_form").elements;
var guess = null;
for (var i = 0; i < all_radio.length; i++)
if (all_radio[i].checked) guess = all_radio[i].value;
rand = Math.floor(Math.random() * 360);
if (rand == guess) window.location = "/open/";
else window.location = "/die/";
}
不用管逻辑验证,直接访问/open/,发现<script src="/static/js/open_sesame.js"></script>
继续访问/static/js/open_sesame.js:
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
function open(i) {
sleep(1).then(() => {
open(i + 1);
});
if (i == 4000000000) window.location = "/fight/";
}
然后继续跟到/fight/里面:
<script src="/static/js/fight.js"></script>
跟上面同理,访问fight.js得到:
// Run to scramble original flag
//console.log(scramble(flag, action));
function scramble(flag, key) {
for (var i = 0; i < key.length; i++) {
let n = key.charCodeAt(i) % flag.length;
let temp = flag[i];
flag[i] = flag[n];
flag[n] = temp;
}
return flag;
}
function check_action() {
var action = document.getElementById("action").value;
var flag = ["{hey", "_boy", "aaaa", "s_im", "ck!}", "_baa", "aaaa", "pctf"];
// TODO: unscramble function
}
这个时候得到8部分被打乱的flag,大概看了一下,突然就想到了施瓦辛格在终结者里面的最后一句:I will be back.
然后直接猜出来flag:pctf{hey_boys_im_baaaaaaaaaack!}