IDF-CTF-天罗地网-不难不易的js加密

题目:就是这里 → http://ctf.idf.cn/game/web/28

点击链接,弹出一个输入框。要求输入flag。

查看源代码,发现一个script脚本。

然后复制到站长工具js混淆加密压缩那里解密。

http://tool.chinaz.com/js.aspx

得到解密后的代码:

var a = prompt("\u8f93\u5165\u4f60\u7684\x66\x6c\x61\x67\u5427\uff0c\u5c11\u5e74\uff01", "");
var b = "\x66\x33\x33\x37\x33\x65\x33\x36\x63\x36\x37\x37\x37\x35\x30\x37\x37\x39\x66\x35\x64\x30\x34\x66\x66\x37\x38\x38\x35\x62\x33\x65";
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) == "\x6a\x73" && $.md5(f.substr(0x0 / d, d + 0x3)) == "\x64\x30\x31\x35\x34\x64\x35\x30\x34\x38\x62\x35\x61\x35\x65\x62\x31\x30\x65\x66\x31\x36\x34\x36\x34\x30\x30\x37\x31\x39\x66\x31") {
        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("\x65\x61\x73\x79") && c.test(a)) {
                d = String(0x1) + String(a.length)
            }
        }
    }
};
if (a.substr(0x4, 0x1) != String.fromCharCode(d) || a.substr(0x4, 0x1) == "\x7a") {
    alert("\u989d\uff0c\u518d\u53bb\u60f3\u60f3\u3002\u3002")
} else {
    alert("\u606d\u559c\u606d\u559c\uff01")
}

将代码中的unicode码和ascii码全部转换为字符,将16进制数转换为10进制数。

转换方法:直接在浏览器控制台输入即可转换。

转换后的代码如下:

var a = prompt("输入你的flag吧,少年!", "");
var b = "f3373e36c677750779f5d04ff7885b3e";
var c = /.+_.+_.+/gi;
var d = 0;
var e = a.substr(8, 5);
if ($.md5(e) == b.replace(/7/ig, ++d).replace(/8/ig, d * 2)) {
    var f = a.substr(0 / d, 7);
    if (f.substr(5, 2) == "js" && $.md5(f.substr(0 / d, d + 3)) == "d0154d5048b5a5eb10ef1646400719f1") {
        r = a.substr(13);
        if (r.charCodeAt(d) - 25 == r.charCodeAt(++d) - 25 && r.charCodeAt(--d) - 25 == r.charCodeAt(--d)) {
            var g = String.fromCharCode(79);
            g = g.toLowerCase() + g.toLowerCase();
            if (r.substr((++d) * 3, 6) == g.concat("easy") && c.test(a)) {
                d = String(1) + String(a.length)
            }
        }
    }
};
if (a.substr(4, 1) != String.fromCharCode(d) || a.substr(4, 1) == "z") {
    alert("额,再去想想。。")
} else {
    alert("恭喜恭喜!")
}
好,那么现在看起来就舒服多了,开始解密吧,一般情况下,解密都是从最后一句往前逆推,可是这里的代码不行,需要正向解密,就是从头到尾
一句一句的去分析。

在分析的过程中,为了方便观察过程,加上注释以及将一些有关算数的表达式直接计算出结果替换原来的表达式。

大概浏览一下可得知字符串a是我们要求的答案。
第一句是输入字符串变量a,接着给出b,c,d三个变量。
看到第一个if语句,判断的是e变量经过md5加密后和b变量经过正则替换后是否相等。

在控制台下输入即可看到结果:

可看到b变量替换后的结果为:f3313e36c611150119f5d04ff1225b3e
此时d=1
去cmd5网站解密得到:jiami
那么现在就得知,e = a.substr(8, 5)=“jiami”
字符串a从第八位开始的五位是"jiami"

做好注释:

var e = a.substr(0x8, 0x5);  //e="jiami"
if ($.md5(e) == b.replace(/7/ig, ++d).replace(/8/ig, d * 0x2)) {  //f3313e36c611150119f5d04ff1225b3e="jiami"
接着,var f = a.substr(0 / d, 7);
因为d=1,所以这里是var f = a.substr(0, 7);
由此可知 f 的长度为7

看第二个if语句:

if (f.substr(5, 2) == "js" && $.md5(f.substr(0 / d, d + 3)) == "d0154d5048b5a5eb10ef1646400719f1") 

等价于

if (f.substr(5, 2) == "js" && $.md5(f.substr(0,4)) == "d0154d5048b5a5eb10ef1646400719f1") 
到cmd5解密可得d0154d5048b5a5eb10ef1646400719f1=“wctf”

由此可知 f = "wctf?js" , 其中?为未知字符,不过做了这么多题,这个问号很明显就是"{",因为idf的题目的答案都是
"wctf{........}"这样的格式的。

那么现在就得知 a 从第0位到第12位为"wctf?js?jiami"。
r = a.substr(13);

r 是 a 从第13位开始到最后1位的字符串。

接着是第三个if语句:

if (r.charCodeAt(d) - 25 == r.charCodeAt(++d) - 25 && r.charCodeAt(--d) - 25 == r.charCodeAt(--d)) 

等价于

if (r.charCodeAt(1) - 25 == r.charCodeAt(2) - 25 && r.charCodeAt(1) - 25 == r.charCodeAt(0)) 
由此可知,r 的第0位的ascii码(10进制)比第1位的ascii码小25,第1位和第2位是相同的字符。
var g = String.fromCharCode(79);g = g.toLowerCase() + g.toLowerCase();

在控制台下运行的结果:

那么这两句就等价于:

var g="oo";

接着是第4个if语句:

if (r.substr(3,6) == g.concat("easy") && c.test(a))
可知g.concat("easy")="ooeasy",r 从第3为开始的6个字符是"ooeasy"
此时我们得知 r = “???ooeasy.........”(后面有若干位未知)

那么现在我们得知 a = "wctf?js?jiami???ooeasy........."(后面的若干位未知)

test() 方法用于检测一个字符串是否匹配某个模式。
从c.test(a)可知,a 的格式必为"??_??_??"
d= String(0x1) + String(a.length)
这时我们并不知道 a 的长度,所以无法知道 d 的值。
继续往下看。

第5个if语句:

if (a.substr(4,1) != String.fromCharCode(d) || a.substr(4,1) == "z")
由此得知 a 的第4位不是"z",而且 d 代表的字符。

好了,现在我们看看掌握的信息。

现在解得的 a 为"wctf?js?jiami???oosasy................."(后面还有若干位未知)

前面提到过idf题目的答案都是固定格式的,"wctf{..........}",那么我们就猜测 a 的第4位是"{",查看"{"的ascii码为 123,那么
我们假设d=“123”

由 d= String(0x1) + String(a.length)得知,a.length=23

那么我们数一数"wctf{js?jiami???ooeasy........"中确定的共有多少位,数了一下从w开始到y结束共有22位

可以确定 a =“wctf{js?jiami???ooeasy?”

根据格式我们猜测最后一位是"}"

那么 a = “wctf{js?jiami???ooeasy}”

由前面的test方法可知 a 的格式为??_??_?? ,那么我们继续猜测 a = "wctf{js_jiami_??ooeasy}"

前面已知, r 的第0位的ascii码比第1位小25,第1位和第2位是相同的字符此时,r 的第0位为"_",查看其ascii码是95,那么第1位
的ascii码是95+25=120,字符是“x”

到这里,a 的值我们已经全部猜解完了,a = “wctf{js_jiami_xxooeasy}”

经过注释之后的代码:

var a = prompt("输入你的flag吧,少年!", "");
var b = "f3373e36c677750779f5d04ff7885b3e";
var c = /.+_.+_.+/gi;
var d = 0;
var e = a.substr(8, 5);  //e="jiami"

if ($.md5(e) == b.replace(/7/ig, ++d).replace(/8/ig, d * 2)) {  //f3313e36c611150119f5d04ff1225b3e="jiami"
    var f = a.substr(0,7); //f="wctf*js"
    if (f.substr(5,2) == "js" && $.md5(f.substr(0,4)) == "d0154d5048b5a5eb10ef1646400719f1") {
        r = a.substr(13);   //len(r)=23-13=10
        n=r.charCodeAt(1) - 25;
        if (r.charCodeAt(1) - 25 == r.charCodeAt(2) - 25 && r.charCodeAt(1) - 25 == r.charCodeAt(0)) {
            var g="oo";    //r="_xxooeasy}"
            if (r.substr(3,6) == g.concat("easy") && c.test(a)) {
                d = String(1) + String(a.length)   //d="123"   a.length=23
            }
        }
    }
};
if (a.substr(4,1) != String.fromCharCode(d) || a.substr(4,1) == "z") {
    alert("额,再去想想。。")
} else {
    alert("恭喜恭喜!")
}               //a="wctf{js_jiami_xxooeasy}";

现在看看我们猜得对不对吧。

结果正确。

收获:解密并不都是从尾到头逆推,还可以是从头到尾的正向解密。在本题中是正向和逆向的结合分析,锻炼了分析的能力。

时间: 2024-10-13 21:20:58

IDF-CTF-天罗地网-不难不易的js加密的相关文章

IDF-CTF-不难不易的js加密 答题笔记

题目链接: http://ctf.idf.cn/index.php?g=game&m=article&a=index&id=28知识点:js加密,js代码分析,md5解密,Unicode/Ascii码,正则表达式 就是这里 → http://ctf.idf.cn/game/web/28 思路:点开链接后弹出一个窗口,要求输入flag,按F12可以看到窗口是用一段加密的js代码实现的,将这段js代码复制到站长工具中进行解密,得到解密后的js代码,然后将其中的Unicode码及Asci

简谈-Python爬虫破解JS加密的Cookie

通过Fiddler抓包比较,基本可以确定是JavaScript生成加密Cookie导致原来的请求返回521. 发现问题: 打开Fiddler软件,用浏览器打开目标站点(http://www.kuaidaili.com/proxylist/2/) .可以发现浏览器对这个页面加载了两次,第一次返回521,第二次才正常返回数据.很多没有写过网站或是爬虫经验不足的童鞋,可能就会觉得奇怪为什么会这样?为什么浏览器可能正常返回数据而代码却不行? 仔细观察两次返回的结果可以发现: 1.第二次请求比第一次请求的

js加密php解密(CryptoJS)碰到的坑

今天做了一个功能,需要js传密码到php文件,对js密码 进行判断,为想为这个传输过程进行解密,参考了网上的一个方法(这个方法我只是使用了,并没有太深了解0.0) 首先要引入3个js文件 (在网上可搜索到) <script src="../public/js/aes.js"></script><script src="../public/js/md5.js"></script><script src="

昆仑游戏[JS加密修改]

昆仑游戏:http://www.kunlun.com/index.html JS加密修改 BigTools=window.BigTools;//重点 RSAKeyPair=window.RSAKeyPair;//重点调用functiongetToken 下面是匿名函数 (function(ab) { var ad = 2; var I = 16; var o = I; var Q = 1 << 16; var e = Q >>> 1; var M = Q * Q; var T

js加密的密文让PHP解密(AES算法)

JS加密代码如下 <script src="http://crypto-js.googlecode.com/svn/tags/3.0.2/build/rollups/aes.js"></script> <script src="http://crypto-js.googlecode.com/svn/tags/3.0.2/build/rollups/md5.js"></script> <script src=&qu

web主题公园版权信息破解:script.js加密文件

很多人会使用web主题公园网站的免费worldpress主题,但它的主题又都被加了版权信息,故意让人找不到版权信息的修改位置. 你如果去footer.php里面删除版权信息(技术支持:web主题公园),网站不能正常运行了且会提示:"请勿删除版权信息!务必保留页脚css类.f_bq,方可显示正常." 破解方法: 1.找到js目录下的script.js加密文件 打开script.js文件的内容为: eval(function(p,a,c,k,e,d){e=function(c){retur

RSA前台js加密,后台C#解密

一.需求: 为了安全,项目中前台登陆用的密码需要加密传到后台,后台c#解密登陆密码. 二.解决方案 采用非对称加密算法RSA来达到目的,前台登陆页面一加载便发送一次ajax请求获取后台产生的公钥,用于前台加密,用户点击登陆时出发加密过程并提交加密的数据到后台,后台C#语言采用已封装好的RSA算法工具进行密码解密. 以下为c#RSA算法加密代码: private static RSAParameters rsap = new RSAParameters() { Modulus = Convert.

RSA加密前端JS加密,后端asp.net解密,报异常

参考引用:http://www.ohdave.com/rsa/的JS加密库 前端JS加密代码: function GetChangeStr() { debugger; var pwdStr = document.getElementById("txtPassWordStr").value; var uidStr= $("#<%=txtUserStr.ClientID%>").val(); if (!pwdStr || pwdStr.length == 0

实现使用3des在页面js加密,后台java解密

/** *secretKey密钥需与java的3des的secretKey相同 *在我的代码实现中secretKey是在后台生产,放入到redis的,每一次进入页面都会新生产一个.大家也可以把这个值写死在这里 */ secretKey = "0123456789abcd0123456789"; //varStr需要加密的字符串 //enStr是已加密的字符串 var enStr=DES3.encrypt(secretKey,varStr); 后台java解密实现: //secretKe