哈密顿行动0x01-获取密码

关卡描述

进入第一关,是需要得到一个密码。

hmdxd01-1

关卡解答

一般这种游戏第一关都比较套路了,想知道的都在源码里。所以打开源码看一下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<SCRIPT language=JavaScript>

<!--
// 由给定的数组生成一个新的数组,其实就是在最前面添了没用的一位
function makeArray(){
this.length = makeArray.arguments.length
for (var i = 0; i < this.length; i++)
this[i + 1] = makeArray.arguments[i]
}
var Array = new makeArray('B','R','E','L','E','F','O','A','T');

// 生成密码的函数
function password() {
var pass =
(numArray[7])+(numArray[2])+(numArray[8])+(numArray[6])+(numArray[3])+(numArray[1])+(numArray[5])+(numArray[9])+(numArray[4])+(numArray[6])+(numArray[8])+(numArray[3])+(numArray[1])+(numArray[5])+(numArray[2])+(numArray[6])+(numArray[3])+(numArray[9])+(numArray[7])+(numArray[4])+(numArray[4])+(numArray[4])+(numArray[2])+(numArray[8])+(numArray[6]);

var num = 1;
var pass1 = prompt('Please Enter Your Password','');

while (num < 2) {
if (pass1 == pass) {
alert('WOW! OK, OK, this is begin ...')
break;
}

num+=1;
var pass1 =alert("wrong! idoit you are! i am strong!strong!strong!strong!strong!strong!strong!")
}
}
// -->
</SCRIPT>

到这里已经可以知道密码是如何生成的了。再接着看看下面的源码:

1
2
3
wlkji="<citlnug=JvSrp\"\r\rfnto aera({\nhslnt  aera.ruet.egh\no vri=0   hslnt;i+\rti[  ]=mkAryagmnsi\r}\na uAry=nwmkAry'''''''''''''''''';/citsrp agae\"aacit>\n\nucinmkAry)\rti.egh=mkAryagmnslnt\rfr(a   ;i<ti.egh +)\nhsi+1  aera.ruet[]\n\rvrnmra  e aera(2,4,7,6,8,5,1,3,9)<srp>";

eval(unescape("function%20RsRsRsRs%28teaabb%29%20%7Bvar%20tttmmm%3D%22%22%3Bl%3Dteaabb.length%3Bwww%3Dhhhhffff%3DMath.round%28l/2%29%3Bif%28l%3C2*www%29hhhhffff%3Dhhhhffff-1%3Bfor%28i%3D0%3Bi%3Chhhhffff%3Bi++%29tttmmm%20%3D%20tttmmm%20+%20teaabb.charAt%28i%29+%20teaabb.charAt%28i+hhhhffff%29%3Bif%28l%3C2*www%29%20tttmmm%20%3D%20tttmmm%20+%20teaabb.charAt%28l-1%29%3Bdocument.write%28tttmmm%29%3B%7DRsRsRsRs%28wlkji%29%3B"));

首先观察这个变量wlkji可以发现它很像是javascript的代码,事实上它确实是一段javascript代码,通过把一句javascript语句按照奇偶数位的字符分离得到。最开始我是通过在sublime中观察后,利用这一点半自动(几乎手动)拼出了wlkji中字符串表示的js代码:

1
2
3
4
5
6
7
8
function makeArray()
{
this.length = makeArray.arguments.length;
for (var i = 0; i < this.length; i++)
this[i + 1] = makeArray.arguments[i];
}

var numArray = new makeArray('2','4','7','6','8','5','1','3','9');

然后通过:

1
2
var pass =
(numArray[7])+(numArray[2])+(numArray[8])+(numArray[6])+(numArray[3])+(numArray[1])+(numArray[5])+(numArray[9])+(numArray[4])+(numArray[6])+(numArray[8])+(numArray[3])+(numArray[1])+(numArray[5])+(numArray[2])+(numArray[6])+(numArray[3])+(numArray[9])+(numArray[7])+(numArray[4])+(numArray[4])+(numArray[4])+(numArray[2])+(numArray[8])+(numArray[6]);

计算出密码即可。

因为对js不熟悉,所以中间的过程都是用python写的:

1
2
3
4
5
6
7
# 拼接js
def func(s1, s2):
return ''.join(list(map((lambda a, b: a + b), s1, s2)))
# 例如:
# s1 = vrnmra e aera(2,4,7,6,8,5,1,3,9)
# s2 = a uAry=nwmkAry'''''''''''''''''';
# func(s1, s2) --> var numArray = new makeArray('2','4','7','6','8','5','1','3','9');

最终得到了wlkji中的字符串表示的代码:

1
2
3
4
5
6
7
8
function makeArray()
{
this.length = makeArray.arguments.length;
for (var i = 0; i < this.length; i++)
this[i + 1] = makeArray.arguments[i];
}

var numArray = new makeArray('2','4','7','6','8','5','1','3','9');

到这里再用password函数中pass所在的表达式计算一下即可。

这一关本来的意图其实是javascript中的escape编码和eval加解密:

eval(unescape(“function%20RsRsRsRs%28teaabb%29%20%7Bvar%20tttmmm%3D%22%22%3Bl%3Dteaabb.length%3Bwww%3Dhhhhffff%3DMath.round%28l/2%29%3Bif%28l%3C2www%29hhhhffff%3Dhhhhffff-1%3Bfor%28i%3D0%3Bi%3Chhhhffff%3Bi++%29tttmmm%20%3D%20tttmmm%20+%20teaabb.charAt%28i%29+%20teaabb.charAt%28i+hhhhffff%29%3Bif%28l%3C2www%29%20tttmmm%20%3D%20tttmmm%20+%20teaabb.charAt%28l-1%29%3Bdocument.write%28tttmmm%29%3B%7DRsRsRsRs%28wlkji%29%3B”));

通过在线解密解密后得到eval执行的字符串内容为

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function RsRsRsRs(teaabb) 
{
var tttmmm="";
l=teaabb.length;
www=hhhhffff=Math.round(l/2);
if(l<2*www)
hhhhffff=hhhhffff-1;
for(i=0;i<hhhhffff;i++)
tttmmm = tttmmm + teaabb.charAt(i)+ teaabb.charAt(i+hhhhffff);
if(l<2*www)
tttmmm = tttmmm + teaabb.charAt(l-1);
document.write(tttmmm);
}

RsRsRsRs(wlkji);

只需要将wlkji带入该函数即可得到和上面手工拼接相同的代码,这段解密代码也非常容易改写成python的形式。

备注

JavaScript eval() 函数

eval() 函数计算 JavaScript 字符串,并把它作为脚本代码来执行。

如果参数是一个表达式,eval() 函数将执行表达式。如果参数是Javascript语句,eval()将执行 Javascript 语句。

语法

eval(string)

JavaScript charAt() 方法

返回特定位置的字符

1
2
3
var str = "python";
var n = str.charAt(2)
// output: 't'

JavaScript round() 方法

round() 方法可把一个数字舍入为最接近(四舍五入)的整数:

1
2
Math.round(0.5);
// output: 1