이 문제는 JavaScript를 이용해 특정 .box
요소를 클릭하면 XOR 연산을 통해 플래그를 복호화하여 출력하는 방식입니다.
const boxes = document.querySelectorAll('.box');
let flagbox = boxes[Math.floor(Math.random() * boxes.length)];
boxes
배열에서 무작위로 하나를 선택해 flagbox
로 지정합니다.
for (const box of boxes) {
if (box === flagbox) {
box.onclick = () => {
let enc = `"\\u000e\\u0003\\u0001\\u0016\\u0004\\u0019\\u0015V\\u0011=\\u000bU=\\u000e\\u0017\\u0001\\t=R\\u0010=\\u0011\\t\\u000bSS\\u001f"`;
for (let i = 0; i < enc.length; ++i) {
try {
enc = JSON.parse(enc);
} catch (e) { }
}
let rw = [];
for (const e of enc) {
rw ^ 0x62);
}
const x = rw['\x6dap'](x => String['\x66rom\x43har\x43ode'](x));
alert(`Congrats ${x['\x6aoin']('')}`);
};
flagbox = null;
} else {
box.onclick = () => alert('no flag here');
}
};
여기서 중요한 부분은 enc
문자열이 여러 번 JSON.parse
를 통해 디코딩된다는 점입니다. 이후 XOR 연산을 통해 복호화가 진행됩니다.
let enc = `"\\u000e\\u0003\\u0001\\u0016\\u0004\\u0019\\u0015V\\u0011=\\u000bU=\\u000e\\u0017\\u0001\\t=R\\u0010=\\u0011\\t\\u000bSS\\u001f"`;
이 문자열은 UTF-16 이스케이프 형태로 저장된 문자열입니다. 여러 번 JSON.parse(enc)
를 수행하면 원래 문자열로 변환됩니다.
rw.push(e.charCodeAt(0) ^ 0x62);
각 문자의 ASCII 코드에 0x62
(98)와 XOR 연산을 수행하여 원래 값을 복원합니다.
import json
# 원본 인코딩된 문자열
enc = "\u000e\u0003\u0001\u0016\u0004\u0019\u0015V\u0011=\u000bU=\u000e\u0017\u0001\t=R\u0010=\u0011\t\u000bSS\u001f"
# XOR 복호화
rw = [chr(ord(e) ^ 0x62) for e in enc]
# 결과 문자열
decoded_flag = "".join(rw)
print(decoded_flag)
출력 결과:
lactf{w4s_i7_luck_0r_ski11}
이 문제는 JSON 디코딩 → XOR 연산을 통한 복호화 방식으로 이루어진 JavaScript 기반 CTF 문제였습니다. XOR 연산의 성질을 이용해 쉽게 플래그를 복원할 수 있었습니다. 🚀
lactf{1_sp0773d_z_t0k3ns_4v3rywh3r3}
개발자 도구를 사용할 줄 아는지 물어보는 문제입니다.
const msg = document.getElementById("msg");
const flagInp = document.getElementById("flag");
const checkBtn = document.getElementById("check");
function checkFlag(flag) {
const step1 = btoa(flag);
const step2 = step1.split("").reverse().join("");
const step3 = step2.replaceAll("Z", "[OLD_DATA]");
const step4 = encodeURIComponent(step3);
const step5 = btoa(step4);
return step5 === "JTNEJTNEUWZsSlglNUJPTERfREFUQSU1RG85MWNzeFdZMzlWZXNwbmVwSjMlNUJPTERfREFUQSU1RGY5bWI3JTVCT0xEX0RBVEElNURHZGpGR2I=";
}
checkBtn.addEventListener("click", () => {
const flag = flagInp.value.toLowerCase();
if (checkFlag(flag)) {
flagInp.remove();
checkBtn.remove();
msg.innerText = flag;
msg.classList.add("correct");
} else {
checkBtn.classList.remove("shake");
checkBtn.offsetHeight;
checkBtn.classList.add("shake");
}
});
웹 사이트에 접속하는 정보를 제공한다.
해당 코드를 분석하면
여기 나온대로 하면 플래그를 획득 할 수 있다.
lactf{no_grizzly_walls_here}