不难不易的js加密
问题
就是这里 → http://ctf.idf.cn/game/web/28
write up
首先查看源码,是一堆看不懂的js代码(其实也不是完全看不懂),放进 http://tool.lu/js/ 解密一下,得到下面这堆:
var a = prompt("输入你的flag吧,少年!", "");
var b = "f3373e36c677750779f5d04ff7885b3e";
var c = /.+_.+_.+/gi;
var d = 0x0;
var e = a.substr(0x8, 0x5);
if ($.md5(e) == b.replace(/7/ig, ++d).replace(/8/ig, d * 0x2)) {
var f = a.substr(0x0 / d, 0x7);
if (f.substr(0x5, 0x2) == "js" && $.md5(f.substr(0x0 / d, d + 0x3)) == "d0154d5048b5a5eb10ef1646400719f1") {
r = a.substr(0xd);
if (r.charCodeAt(d) - 0x19 == r.charCodeAt(++d) - 0x19 && r.charCodeAt(--d) - 0x19 == r.charCodeAt(--d)) {
var g = String.fromCharCode(0x4f);
g = g.toLowerCase() + g.toLowerCase();
if (r.substr((++d) * 0x3, 0x6) == g.concat("easy") && c.test(a)) {
d = String(0x1) + String(a.length)
}
}
}
};
if (a.substr(0x4, 0x1) != String.fromCharCode(d) || a.substr(0x4, 0x1) == "z") {
alert("额,再去想想。。")
} else {
alert("恭喜恭喜!")
}
排版后是上面这个样子,用 http://jsfiddle.net/ 一步一步跑下来看懂程序:
var b = "f3373e36c677750779f5d04ff7885b3e";
var d = 0;
b = b.replace(/7/ig, ++d).replace(/8/ig, d * 0x2);
document.write(b)
得到:
f3313e36c611150119f5d04ff1225b3e
一行一行分析代码,最终解密:
var a = prompt("输入你的flag吧,少年!", "");
var b = "f3373e36c677750779f5d04ff7885b3e";
var c = /.+_.+_.+/gi; //.是通配符,妹的!表明格式是???_???_???
/*
var str = "a_b_c";
var patt1 = /.+_.+_.+/gi;
var result = patt1.test(str);
document.write("Result: " + result);
*/
var d = 0x0;
var e = a.substr(8, 5);
if ($.md5(e) == b.replace(7, 1).replace(8, 2) {
//md5(e) = f3313e36c611150119f5d04ff1225b3e
//e = “jiami” == a[8:8+5-1]
var f = a.substr(0, 7);
if (f.substr(5, 2) == "js" && $.md5(f.substr(0, 4)) == "d0154d5048b5a5eb10ef1646400719f1") {
//a[5:6] = “js”
//a[0:3] = “wctf”
r = a.substr(0xd);
//r = “ctf???????”,错了这里,应该是r=a[13:],注意d是十六进制
//charCodeAt() 方法可返回指定位置的字符的 Unicode 编码。这个返回值是 0 - 65535 之间的整数。 //unicode编码格式:\u0001
//a[13] = ?
//下面&&前,表示第14位和第15位是相等的,且这里++d了,使d变成2
//&&后:14位-19 = 第13位,然而第13位已经知道是_了,所以?加19(0x19,更准确的说)得到14位和15位都是_+0x19
//js打印一下:
/*
var tmp = "_".charCodeAt(0);
var g = String.fromCharCode(tmp+0x19);
document.write(g);
*/
if (r.charCodeAt(d) - 0x19 == r.charCodeAt(++d) - 0x19 && r.charCodeAt(--d) - 0x19 == r.charCodeAt(--d)) {
//执行完上面这句d变成了0
var g = String.fromCharCode(0x4f);//g = O //是字母O不是0
/* 用 Python 看一下 \u004f 是什么
>>> print("\u004f")
>>> O
*/
g = g.toLowerCase() + g.toLowerCase();// g = oo
if (r.substr((++d) * 0x3, 0x6) == g.concat("easy") && c.test(a)) {
//d变成了1,
//r.substr(3,6) == ooeasy == a[15:15 + 6 - 1]
//c.test(a)? 表明a中含有c,现在看来c
//test() 方法用于检测一个字符串是否匹配某个模式.
d = String(0x1) + String(a.length)
//d = “1”+“23”
}
}
}
};
if (a.substr(0x4, 0x1) != String.fromCharCode(d) || a.substr(0x4, 0x1) == "z") {
//||后的那句表明string.fromCharcode(d) == 122?
//其实应该知道标准格式wctf{,所以应该直到a[4] = {,故此时d=123,推得len(a)=23
alert("额,再去想想。。")
} else {
alert("恭喜恭喜!")
}
综上,字符依次为: 0 w 1 c 2 t 3 f 4 { 5 j 6 s 7 8 j 9 i 10 a 11 m 12 i 13 14 x 15 x 16 o 17 o 18 e 19 a 20 s 21 y 22 }
Last updated
Was this helpful?