拯救大兵艾伦
题目
众所周知,艾伦(eren)身怀坐标之力(flag)可以变身成为巨人(kyojin)于是,他又双叒叕被抓走啦233三爷当然是选择原谅,啊呸,救回他不过救回来的是巨人状态的艾伦,我们需要把他复原回去
解题报告
打开提供的链接,查看源代码发现如下Javascript
function check() {
let p = document.getElementById("eren").value;
let flag = document.getElementById("flag").value;
let kyojin = "~dyl[fj!XHAu)(Hj~$HT}i";
let f = (x, y) => (x == 1) ? 1 : f(y % x, y) * (y - parseInt(y / x)) % y; let fail = flag.length != kyojin.length;
Array.from(flag).forEach((x, i) => fail |= String.fromCharCode(f(x.charCodeAt(0), p)) != kyojin[i]);
fail ? alert("不正常") : alert("正常");
}
可以用脚本直接暴力破解
let kyojin = "~dyl[fj!XHAu)(Hj~$HT}i";
let result = ""
let f = (x, y) => (x == 1) ? 1 : f(y % x, y) * (y - parseInt(y / x)) % y;
for (let i = 0; i < kyojin.length; ++i) {
for (let j = 0x20; j <= 0x7E; ++j) {
if (String.fromCharCode(f(j, 193)) == kyojin[i]) {
// console.log(String.fromCharCode(j));
result += String.fromCharCode(j);
break;
}
}
}
console.log(result);
或者阅读js代码,发现f函数是求模p乘法逆元
跟异或一样,把“整容后”再整一次容就可以变回“整容前”
然后问题是连p也未知
不过p一定是素数,候选项不会太多,果断爆破
// copy from 地下室.html
let f = (x, y) => (x == 1) ? 1 : f(y % x, y) * (y - parseInt(y / x)) % y;
let kyojin = "~dyl[fj!XHAu)(Hj~$HT}i";
// get prime
const MAXP = 1000000;
let prime = new Array(MAXP).fill(0);
for (let i = 2; i <= MAXP; ++i) {
if (!prime[i])
prime[++prime[0]] = i;
for (let j = 1; j <= prime[0] && prime[j] * i <= MAXP; ++j) {
prime[prime[j]*i] = 1;
if (i % prime[j] == 0)
break;
}
}
//try prime
for (let i = 1; i <= prime[0]; ++i) {
let eren = prime[i];
let flag = [];
Array.from(kyojin).forEach(x => {
if (x.charCodeAt(0) >= eren)
return;
let y = f(x.charCodeAt(0), eren);
if (y < 33 || y > 126)
return;
flag.push(y);
});
if (flag.length == kyojin.length) {
console.log(eren);
console.log(flag.map(x => String.fromCharCode(x)).join(""));
}
}
Flag
HSCTF{zuD~b!qo~zH;~li}