HackThisSite - JavaScript Mission 7

Challenge

JS Obfuscation. FTW!

Find the password:

索引名 JS Obfuscation. FTW!,难度 moderate。密码比较逻辑藏在一个运行时由十六进制字符串数组加 String.fromCharCode(...) 生成出来的 <button> 里。要先把混淆还原出来。

Solution

1
2
3
$ curl -s -b "$HTS_COOKIE" \
-H "Referer: https://www.hackthissite.org/missions/javascript/7/" \
"https://www.hackthissite.org/missions/javascript/7/" -o lvl7.html
1
var _0x4e9d=["\x66\x72\x6F\x6D\x43\x68\x61\x72\x43\x6F\x64\x65","\x77\x72\x69\x74\x65"];document[_0x4e9d[0x1]](String[_0x4e9d[0x0]](0x3c,0x62,0x75,0x74,0x74,0x6f,0x6e,0x20,0x6f,0x6e,0x63,0x6c,0x69,0x63,0x6b,0x3d,0x27,0x6a,0x61,0x76,0x61,0x73,0x63,0x72,0x69,0x70,0x74,0x3a,0x69,0x66,0x20,0x28,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x67,0x65,0x74,0x45,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x42,0x79,0x49,0x64,0x28,0x22,0x70,0x61,0x73,0x73,0x22,0x29,0x2e,0x76,0x61,0x6c,0x75,0x65,0x3d,0x3d,0x22,0x6a,0x30,0x30,0x77,0x31,0x6e,0x22,0x29,0x7b,0x61,0x6c,0x65,0x72,0x74,0x28,0x22,0x59,0x6f,0x75,0x20,0x57,0x49,0x4e,0x21,0x22,0x29,0x3b,0x77,0x69,0x6e,0x64,0x6f,0x77,0x2e,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x2b,0x3d,0x20,0x22,0x3f,0x6c,0x76,0x6c,0x5f,0x70,0x61,0x73,0x73,0x77,0x6f,0x72,0x64,0x3d,0x22,0x2b,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x67,0x65,0x74,0x45,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x42,0x79,0x49,0x64,0x28,0x22,0x70,0x61,0x73,0x73,0x22,0x29,0x2e,0x76,0x61,0x6c,0x75,0x65,0x7d,0x65,0x6c,0x73,0x65,0x20,0x7b,0x61,0x6c,0x65,0x72,0x74,0x28,0x22,0x57,0x52,0x4f,0x4e,0x47,0x21,0x20,0x54,0x72,0x79,0x20,0x61,0x67,0x61,0x69,0x6e,0x21,0x22,0x29,0x7d,0x27,0x3e,0x43,0x68,0x65,0x63,0x6b,0x20,0x50,0x61,0x73,0x73,0x77,0x6f,0x72,0x64,0x3c,0x2f,0x62,0x75,0x74,0x74,0x6f,0x6e,0x3e));
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
32
33
#!/usr/bin/env python3
"""Recover the JavaScript Mission 7 password from the obfuscated source.

The level ships two hex-string arrays and rebuilds a <button> at run time by
turning a numeric char-code list into HTML:

var _0x4e9d=["\\x66\\x72\\x6F\\x6D\\x43\\x68\\x61\\x72\\x43\\x6F\\x64\\x65",
"\\x77\\x72\\x69\\x74\\x65"];

Step 1 unescapes the \\xNN literals into identifier names
("fromCharCode","write"); step 2 turns the numeric char-code list into the
button HTML and reads the compared literal out of it -- the password.
"""
import re

src = open("lvl7.html", encoding="utf-8", errors="replace").read()

# Step 1: \xNN string literals -> identifier names
arr = re.search(r"_0x4e9d=\[(.*?)\]", src, re.S).group(1)
names = [bytes(b, "latin1").decode("unicode_escape")
for b in re.findall(r'"((?:\\x[0-9a-fA-F]{2})+)"', arr)]
print("identifiers:", names)

# Step 2: rebuild the button HTML from the String.fromCharCode() code list
call = re.search(r"String\[_0x4e9d\[0x0\]\]\(([^)]*)\)", src, re.S).group(1)
codes = [int(x, 16) for x in re.findall(r"0x([0-9a-fA-F]+)", call)]
button = "".join(chr(c) for c in codes)
print("button HTML:")
print(button)

# Step 3: the compared literal inside the button is the password
password = re.search(r'value=="([^"]+)"', button).group(1)
print("password:", password)
1
2
3
4
5
$ uv run python decode7.py
identifiers: ['fromCharCode', 'write']
button HTML:
<button onclick='javascript:if (document.getElementById("pass").value=="j00w1n"){alert("You WIN!");window.location += "?lvl_password="+document.getElementById("pass").value}else {alert("WRONG! Try again!")}'>Check Password</button>
password: j00w1n
j00w1n