题目描述:
小宁发现了一个网页,但却一直输不对密码。(Flag格式为 Cyberpeace{xxxxxxxxx} )
直接看源码,只有个js脚本,flag就是破解它
function dechiffre(pass_enc) {
var pass = "70,65,85,88,32,80,65,83,83,87,79,82,68,32,72,65,72,65";
var tab = pass_enc.split(',');
var tab2 = pass.split(',');
var i, j, k, l = 0, m, n, o, p = "";
i = 0;
j = tab.length;
k = j + (l) + (n = 0);
n = tab2.length;
for (i = (o = 0); i < (k = j = n); i++) {
o = tab[i - l];
p += String.fromCharCode((o = tab2[i]));
if (i == 5) break;
}
for (i = (o = 0); i < (k = j = n); i++) {
o = tab[i - l];
if (i > 5 && i < k - 1)
p += String.fromCharCode((o = tab2[i]));
}
p += String.fromCharCode(tab2[17]);
pass = p;
return pass;
}
String["fromCharCode"](dechiffre("\x35\x35\x2c\x35\x36\x2c\x35\x34\x2c\x37\x39\x2c\x31\x31\x35\x2c\x36\x39\x2c\x31\x31\x34\x2c\x31\x31\x36\x2c\x31\x30\x37\x2c\x34\x39\x2c\x35\x30"));
h = window.prompt('Enter password'); //返回输入的内容
alert(dechiffre(h));
WP
化简
直接看就是个函数,以及下面window.prompt('Enter password')
就是让我们输入的,我们的输入会被返回到h,然后对h调用这个函数,至于String那个先不管
于是先看代码,这代码故意恶心人,很多没用的中间变量,单纯的语法问题,把它化简理解一下
值得一提的是,其中的两个for循环经过化简后,o = tab[i]屁用没有(所以函数输入完全没用),实际有用的可以看出是排除了tab2[n-1],所以直接修改pass并进行合并for循环。另外最后for外面那个tab2[17]其实刚好就是原来的tab2[n-1],所以整个就是遍历pass变成的数组罢了
for (i = 0; i < 6; i++) {
o = tab[i];
p += String.fromCharCode((o = tab2[i]));
}
//tab2[n-1]不在里面,仅此而已,可以从pass那里删掉组成一个for循环看着舒服点
for (i = 6; i < n-1; i++) {
o = tab[i];
p += String.fromCharCode((o = tab2[i]));
}
p += String.fromCharCode(tab2[17]);
最终化简完的效果如下,极其简单!(作者这代码是打算参加那什么最难看懂的代码比赛吗,服了)
function dechiffre(pass_enc) { //没用的输入
//整个函数就是把pass变成列表一个个输入
var pass = "70,65,85,88,32,80,65,83,83,87,79,82,68,32,72,65,72,65";
var tab2 = pass.split(',');
var i, p = "";
for (i = 0; i < tab2.length; i++) {
p += String.fromCharCode(tab2[i]);
//静态 String.fromCharCode() 方法返回由指定的 UTF-16 代码单元序列创建的字符串。
}
return p;
}
String["fromCharCode"](dechiffre("\x35\x35\x2c\x35\x36\x2c\x35\x34\x2c\x37\x39\x2c\x31\x31\x35\x2c\x36\x39\x2c\x31\x31\x34\x2c\x31\x31\x36\x2c\x31\x30\x37\x2c\x34\x39\x2c\x35\x30"));
h = window.prompt('Enter password'); //返回输入的内容
alert(dechiffre(h));
String.fromCharCode 方法
这里有必要解释下 String.fromCharCode 方法
静态 String.fromCharCode()
方法返回由指定的 UTF-16 代码单元序列创建的字符串。
由此可知这个函数的作用就是
把pass那一串翻译出来,最后得到。。。
console.log(dechiffre("这一串乱七八糟的随便搞"));
// FAUX PASSWORD HAHA 翻译:假的密码哈哈(淦)
h = window.prompt('Enter password'); //返回输入的内容
alert(dechiffre(h)); //屁用没有,alert值(怪不得题目是一直输不对密码呢)
???ntnnd所以这个函数屁用都没有,返回的是个固定值,还没用。
真正关键
所以,真正有用的就是下面这句了:
String["fromCharCode"]("FAUX PASSWORD HAHA");
或者说这题本质是道密码题,flag在这个密码里面:
\x35\x35\x2c\x35\x36\x2c\x35\x34\x2c\x37\x39\x2c\x31\x31\x35\x2c\x36\x39\x2c\x31\x31\x34\x2c\x31\x31\x36\x2c\x31\x30\x37\x2c\x34\x39\x2c\x35\x30
String["fromCharCode"]这种形式
先来研究下String["fromCharCode"]是什么操作
可见这个表示的其实就是对象的静态方法,本质和String.fromCharCode()一样,所以不用考虑这个了
所以flag就是这串密码!
\x35\x35\x2c\x35\x36\x2c\x35\x34\x2c\x37\x39\x2c\x31\x31\x35\x2c\x36\x39\x2c\x31\x31\x34\x2c\x31\x31\x36\x2c\x31\x30\x37\x2c\x34\x39\x2c\x35\x30
复制去网上随便一搜就有了,说一下原理
\x这个x一般就代表十六进制了,把它转成十进制,得到:
55,56,54,79,115,69,114,116,107,49,50
再用ASCII转换或者String.fromCharCode()
(其实这就是ASCII解码)
得到:
786OsErtk12
再由题目flag形式构建flag
Cyberpeace{786OsErtk12}
官方WP部分
2.进行代码审计,发现不论输入什么都会跳到假密码,真密码位于 fromCharCode 。
3.先将字符串用python处理一下,得到数组[55,56,54,79,115,69,114,116,107,49,50],exp如下。
s="\x35\x35\x2c\x35\x36\x2c\x35\x34\x2c\x37\x39\x2c\x31\x31\x35\x2c\x36\x39\x2c\x31\x31\x34\x2c\x31\x31\x36\x2c\x31\x30\x37\x2c\x34\x39\x2c\x35\x30"
print (s)
4.将得到的数字分别进行ascii处理,可得到字符串786OsErtk12,exp如下。
a = [55,56,54,79,115,69,114,116,107,49,50]
c = ""
for i in a:
b = chr(i)
c = c + b
print(c)
5.规范flag格式,可得到Cyberpeace{786OsErtk12}
用户huang8huang的WP
从js函数出发(无视了十六进制的解码过程)
就逻辑上可见它只是将内容为逗号分隔的数字的字符串转成相应编码的字符串。
将代码修改,用下方的可疑字符串代替函数中的常量,得到的整个网页代码是:
<html>
<head>
<title>JS</title>
<script type="text/javascript">
function dechiffre() {
var pass = "\x35\x35\x2c\x35\x36\x2c\x35\x34\x2c\x37\x39\x2c\x31\x31\x35\x2c\x36\x39\x2c\x31\x31\x34\x2c\x31\x31\x36\x2c\x31\x30\x37\x2c\x34\x39\x2c\x35\x30";
var tab2 = pass.split(',');
var i;
var p = "";
for (i = 0; i < tab2.length; i++) {
p += String.fromCharCode(tab2[i]);
}
return p;
}
alert(dechiffre());
</script>
</head>
<body></body>
</html>
保存为以HTML后缀的文件再用浏览器打开即可见结果。
总结
这尼玛就不是web题,这整个function就是迷惑人的,而且代码及其复杂没用,尤其是弄了半天出来的结果,有被嘲讽到。
其次没有留意alert的东西,还自己去破解js。
-
下次看到这么明显的密码可以尝试直接破解一下。
-
其次这种输入可以先确定一下是否有用,如果是这种没用的输入,只要一确定就没必要搞了,浪费时间。
语法知识点
String.fromCharCode 方法
静态 String.fromCharCode()
方法返回由指定的 UTF-16 代码单元序列创建的字符串。
String["fromCharCode"]()字典形式
String["fromCharCode"]()字典形式,从String类中取fromCharCode方法,本质和静态 String.fromCharCode()
方法一模一样,表现形式不同而已
\x35这种形式表十六进制
\x35这种形式表十六进制,这里\x代表十六进制,应化成十进制再操作。
且一般十进制后用ASCII尝试
- Python print函数可以直接输出实际值,即自动解码
- JavaScript也可以忽略编码直接操作