ღ Miranda

IDF实验室-不难不易的JS加密

IDF上一道JS加密的题目。

题目链接: http://ctf.idf.cn/game/web/28/

打开会有提示框要输入flag,查看源代码得到下面的js代码:

eval(function(p,a,c,k,e,d){e=function(c){return(c<a?"":e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)d[e(c)]=k[c]||e(c);k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1;};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p;}('4 a=1d("\\T\\Q\\Z\\10\\5\\Y\\n\\S\\X\\L\\W\\V\\x","");4 b="\\5\\j\\j\\0\\j\\h\\j\\k\\11\\k\\0\\0\\0\\3\\2\\0\\0\\C\\5\\3\\p\\2\\i\\5\\5\\0\\q\\q\\3\\u\\j\\h";4 c=/.+w.+w.+/P;4 d=t;4 e=a.1(O,y);9($.A(e)==b.B(/7/D,++d).B(/8/D,d*z)){4 f=a.1(t/d,R);9(f.1(y,z)=="\\1b\\M"&&$.A(f.1(t/d,d+E))=="\\p\\2\\6\\3\\i\\p\\3\\2\\i\\q\\u\\3\\n\\3\\h\\u\\6\\2\\h\\5\\6\\k\\i\\k\\i\\2\\2\\0\\6\\C\\5\\6"){r=a.1(15);9(r.m(d)-o==r.m(++d)-o&&r.m(--d)-o==r.m(--d)){4 g=l.H(1e);g=g.v()+g.v();9(r.1((++d)*E,1c)==g.19("\\h\\n\\M\\18")&&c.16(a)){d=l(s)+l(a.17)}}}};9(a.1(F,s)!=l.H(d)||a.1(F,s)=="\\12"){K("\\13\\L\\14\\1a\\N\\N\\J\\J")}U{K("\\I\\G\\I\\G\\x")}',62,77,'x37|substr|x30|x35|var|x66|x31|||if||||||||x65|x34|x33|x36|String|charCodeAt|x61|0x19|x64|x38||0x1|0x0|x62|toLowerCase|_|uff01|0x5|0x2|md5|replace|x39|ig|0x3|0x4|u559c|fromCharCode|u606d|u3002|alert|uff0c|x73|u60f3|0x8|gi|u5165|0x7|x67|u8f93|else|u5e74|u5c11|u5427|x6c|u4f60|u7684|x63|x7a|u989d|u518d|0xd|test|length|x79|concat|u53bb|x6a|0x6|prompt|0x4f'.split('|'),0,{}))

找在线解密的解密一下得到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("恭喜恭喜!")
}

先对一些函数做解读:

  1. substr(start,length)方法可在字符串中抽取从start下标开始的指定数目的字符,length为可选参数,不写默认取到字符串最后一个字符。
  2. fromCharCode()方法可接受一个指定的Unicode值,然后返回一个字符串。
  3. test()方法用于检测一个字符串是否匹配某个模式,如果字符串 string 中含有与 RegExpObject 匹配的文本,则返回 true,否则返回 false。
  4. concat()方法用于连接两个或多个数组。

先看变量,c为一个正则表达式,d为0,e为取a索引8开始的5个字符。

$.md5(e) == b.replace(/7/ig, ++d).replace(/8/ig, d * 2)判断对emd5加密后的值与f3313e36c611150119f5d04ff1225b3e是否相等,解密为jiamia.substr(8, 5)='jiami',f为a开头取7位,d变为1。

f.substr(0x5, 0x2) == "js" && $.md5(f.substr(0x0 / d, d + 0x3)) == "d0154d5048b5a5eb10ef1646400719f1"其中md5解密为wctf,可以得到f.substr(5,2)='js'f.substr(0,4)='wctf',所以f为wctf*js,进一步得到a为wctf*js*jiami****...

r.charCodeAt(d) - 0x19 == r.charCodeAt(++d) - 0x19 && r.charCodeAt(--d) - 0x19 == r.charCodeAt(--d)r的第二位与第三位相同,第一位是第二位减去0x19,g为oo,因为a匹配c正则,所以r的第一位是_所以a为wctf{js_jiami_xx,由r.substr((++d) * 0x3, 0x6) == g.concat("easy")得a为wctf{js_jiami_xxooeasy}

发表评论

电子邮件地址不会被公开。