[CTF Writeup / Web] DiceCTF 2024 - dicedicegoose
웹 JS 기반 게임.
javascript를 보면 win() 함수가 있다.
function win(history) {
const code = encode(history) + ";" + prompt("Name?");
const saveURL = location.origin + "?code=" + code;
displaywrapper.classList.remove("hidden");
const score = history.length;
display.children[1].innerHTML = "Your score was: <b>" + score + "</b>";
display.children[2].href =
"https://twitter.com/intent/tweet?text=" +
encodeURIComponent(
"Can you beat my score of " + score + " in Dice Dice Goose?",
) +
"&url=" +
encodeURIComponent(saveURL);
if (score === 9) log("flag: dice{pr0_duck_gam3r_" + encode(history) + "}");
}
score는 움직인 칸의 개수다. 9칸만 움직여서 검은 블록을 잡으면 조건이 성립한다. 조건이 참일 때, code(history)의 결과만 알면 flag를 얻을 수 있다.
function encode(history) {
const data = new Uint8Array(history.length * 4);
let idx = 0;
for (const part of history) {
data[idx++] = part[0][0];
data[idx++] = part[0][1];
data[idx++] = part[1][0];
data[idx++] = part[1][1];
}
let prev = String.fromCharCode.apply(null, data);
let ret = btoa(prev);
return ret;
}
encode() 함수는 위와 같다. history 배열 내 존재하는 값을 flatten 한 결과를 base64로 encoding 한다.
let history = [];
history.push([player, goose]);
document.onkeypress = (e) => {
// (...)
history.push([player, goose]);
redraw();
};
history는 위와 같이 [player, goose] 좌표 정보를 포함한다. onkeypress event에서 history에 변화된 위치 정보를 추가한다.
앞서 score가 9라는 조건을 만족해야한다고 했다.
정상적인 플레이라면, 위 조건을 만족하는 경우의 수는 오직 한 가지다.
그 상황에서의 history를 직접 입력하여 계산하면 flag를 얻을 수 있다.
댓글
댓글 쓰기