IDF/Web/不难不易的js加密

题目链接

源代码

打开题目链接,什么提示都没有就要求输入flag,自然要查看网页源代码,复制源代码后用Sublime打开,因为……有高亮才好看(^-^)
这里写图片描述
咦,看不懂,原来是被加密了的,接下来解密吧。

解码

用Firefox的firebug来解密(火狐有2个最强的,一个是firebug,按f12,另一个是hackbar,按f9):将源代码的eval改成alert,然后在控制台运行一下,得到如下解码:
这里写图片描述

可解出来的代码还是有阻碍,再将输出框中的代码复制,粘贴到控制台的运行框里进行“源代码美化”,把Unicode码及Ascii码转换为相应的字符(火狐还是强大!)

这里写图片描述

分析代码

将最终解密出来的代码用Sublime打开(高亮看着舒服=.=)
这里写图片描述

———js基础———

substr():
js函数,字符串截取,下标从0开始
s=”0123456789”
s.substr(7) 结果为”789” 参数为1个时,从index处一直截取到最后
s.substr(1,3) 结果为”123” 第2个参数为截取的长度;

js的replace可以写 正则表达式:
/7/gi
js的正则是以/开始,也是以/结束
g是全局匹配,i是忽略大小写
/7/gi其实就是匹配7这个字符;

字符串.charCodeAt(index)
取第index的字符,同样从0开始

——–代码分析——–

第①~⑤行:
关键字var,即声明了五个变量(没有var:全局变量);
其中 a为弹出的输入框所输入的值;
e为a字符串的第8截取5个长度,也就是长度为5;

第⑥行:

if$.md5(e) == b.replace(/7/gi, ++d).replace(/8/gi, d * 2)){

$.md5(e) :对e做md5运算;
b.replace(/7/gi, ++d):也就是把b字符串里7这个字符替换为++d后的值,这里一开始
var d = 0;所以就是7替换为1(先++),同理,8替换为2;
原来的b:f3373e36c677750779f5d04ff7885b3e;
换后的b:f3313e36c611150119f5d04ff1225b3e;
得到换了之后的值,在线对其md5解密得到字符串:jiami,即变量e=jiami,又因为第⑤行:var e = a.substr(8, 5),也就是变量a的格式为xxxxxxxxjiami……….

第⑦~⑧行:

 var f = a.substr(0 / d, 7);
 if (f.substr(5, 2) == 'js' && $.md5(f.substr(0 / d, d + 3)) == 'd0154d5048b5a5eb10ef1646400719f1') {

1).这里d经过上面的++后,是1,而0/1也是0,所以f是字符串a的第0开始,截取7个长度,也就是开头7个字符;f.substr(5, 2) == ‘js’,即f最后2个字符是js;

2).f.substr(0 / d, d + 3)也就是 f.substr(0,4) 也就是前4位,后面的md5值 去网上搜一下就是 wctf,所以变量f也就是变量a的前七位是:wctfxjs(其中x未知);

3).这里有一个关键,一般ctf题的flag是xctf{},所以前7位确定为:wctf{js;

第⑨~⑩行:

 r = a.substr(13);
    if (r.charCodeAt(d) - 25 == r.charCodeAt(++d) - 25 && r.charCodeAt(--d) - 25 == r.charCodeAt(--d)) {

1).substr()带一个参数,所以变量r也就是变量a的第13(从0开始计数)到最后;

2).if这里比较混淆, if (xx && yy): 先看xx
r.charCodeAt(d) - 25 == r.charCodeAt(++d) - 25
即:r.charCodeAt(d) == r.charCodeAt(++d)

3).上面d是为1,js赋值是比较简单,从左到右去看即可,
r.charCodeAt(1) == r.charCodeAt(2)
d被更新为2
r是a的第13位开始到最后,并且r的第1位和第2位一样;

4).r.charCodeAt(–d) - 25 == r.charCodeAt(–d)
即r.charCodeAt(1) - 25 == r.charCodeAt(0)
也就是r的第1位的ascii值-25就是r的第0位,这里d被更新为0;

第⑪~⑲行:

 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') {


1).String.fromCharCode(79);
就是79变为’O’,见上图
toLowerCase()变为小写o
g为2个小写o相加,也就是oo
g.concat(‘easy’),连接,就变成 ooeasy;

2).r.substr((++d) * 3, 6)
d刚才是0,现在是1
也就是r.substr(3,6),即r的第3位起是ooeasy;

3).var c = /.+.+.+/gi;
c.test(a)
c也是一个正则
.test(a) 也就是在测试a字符串是否满足c这个正则
其实就是说a字符串里要有2个下划线,就可以满足;
结合以上,联想一下格式,a应该大概就是:wctf{js_jiami_xxxxx}

4).d = String(1) + String(a.length)
a.substr(4, 1) != String.fromCharCode(d)
a.substr(4, 1)为a的第4位,也就是’{’
所以d必须是’{‘的ascii码,也就是123(见上图)
String(1) + String(a.length)
即a的长度为23(js的+是可以拼接字符串,而且js是弱类型,可以把字符串的数字隐式转换为数字型的)

梳理:
其实答案已经出来了,稍微整理就是:
wctf{js_jiami_xxooeasy} (刚好23位)

r是a的第13位开始
然后r的第1位和第2位一样

也就是r的第1位的ascii值-25就是r的第0位(原a的第13位,也就是’_’)见上图

所以第14、15位都是x

r的第3位(原a的第16位)起是ooeasy

答案:wctf{js_jiami_xxooeasy}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值