查看源代码
<html> <head> <script src="/tpl/wctf/Public/js/lib/jquery.js"></script> <script src="/tpl/wctf/Public/js/lib/md5.js"></script> </head> <body> <script type="text/javascript"> 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,{})) </script> </body> </html>
把eval换成alert,得到源码,将其中的十六进制和UNICODE编码转换,得到:
1 <script type="text/javascript"> 2 var a=prompt("输入你的flag吧,少年!",""); 3 var b="f3373e36c677750779f5d04ff7885b3e"; 4 var c=/.+_.+_.+/gi; 5 var d=0x0; 6 var e=a.substr(0x8,0x5); 7 if($.md5(e)==b.replace(/7/ig,++d).replace(/8/ig,d*0x2)){ 8 var f=a.substr(0x0/d,0x7); 9 if(f.substr(0x5,0x2)=="js"&&$.md5(f.substr(0x0/d,d+0x3))=="d0154d5048b5a5eb10ef1646400719f1"){ 10 r=a.substr(0xd); 11 if(r.charCodeAt(d)-0x19==r.charCodeAt(++d)-0x19&&r.charCodeAt(--d)-0x19==r.charCodeAt(--d)){ 12 var g=String.fromCharCode(0x4f); 13 g=g.toLowerCase()+g.toLowerCase(); 14 if(r.substr((++d)*0x3,0x6)==g.concat("easy")&&c.test(a)){ 15 d=String(0x1)+String(a.length) 16 } 17 } 18 } 19 }; 20 if(a.substr(0x4,0x1)!=String.fromCharCode(d)||a.substr(0x4,0x1)=="z"){ 21 alert("额,再去想想。。") 22 } 23 else{ 24 alert("恭喜恭喜!") 25 } 26 </script>
现在根据代码中的判断条件去反向猜解flag
变量a就是我们要猜的flag
变量b是一串MD5值
变量c是正则表达式
变量d是十六进制数字0
变量e是从flag中下标为5的地方开始取5个字符
第7行:变量e经MD5加密后的值与变量b替换后的值相等,替换规则是先把b中的7替换成1(++d),再把8替换成2.得到e经过MD5加密后的值为“f3313e36c611150119f5d04ff1225b3e”,解密得“jiami”,也就是flag从下标为8的地方开始为"jiami"
第8行:变量f为flag从头开始截取7个字符,注意这时d的值经过第7行运算后变为1.
第9行:变量f从下标5处截取两个字符为“js”,也就是flag的下标5和下标6对应的字符为“js”,并且f的前四个字符(也是flag的前4个字符)的MD5值为“d0154d5048b5a5eb10ef1646400719f1”,解出得“wctf”,flag的形式为wctf{XXXXX},所以下标为4的字符为“{”.
先来看第20行:String.fromCharCode(d)将一个UNICODE值返回成字符,这里截取的是下标为4的字符,也就是“{”,由此可以反向解出d的值为123.
第15行:这里是d最后一次进行运算,d是两个字符串“1”和flag长度的拼接,d为123,得出a.length的值为23
有了flag的长度,现在可以构造出flag的形式,用“?”代替未知字符,现在已知flag为wctf{js?jiami?????????}
第10行:变量r是从flag下标13开始截取到最后
第11行:r.charCodeAt(d)是将d转成UNICODE字符,注意此时d的值为1,这里d经过几次运算,值在变化,为了分析简单,我把每次运算的值替换为数字就是这样
r.charCodeAt(1)-0x19==r.charCodeAt(2)-0x19&&r.charCodeAt(1)-0x19==r.charCodeAt(0)
这段代码的意思是r的下标1与下标2的字符相同,下标为1的字符减去0x19就是下标0的字符
第12,13行:g最后的值为“oo”
第14行:r.substr((++d)*0x3,0x6),之前d为0,这里就是r.substr((1)*0x3,0x6),从r下标为3开始截取6个字符为g.concat("easy"),也就是“ooeasy”,这时flag为wctf{js?jiami???ooeasy}. c.test(a)是说flag的形式符合变量c(正则表达式),里面包含两个不相邻下划线“_”,所以flag为wctf{js_jiami_??ooeasy},从第11行代码知道剩下的两个字符相等,r下标为0的字符就是“_”,可以得出剩下的两字符为“xx”
最终得出flag: wctf{js_jiami_xxooeasy}