WeChall - Brainfucked

Brainfucked (Javascript) by gizmore 不是 Brainfuck,是 JSFuck——只用 []()!+ 六字符构造 JavaScript

Challenge

题面给一个巨大的 sourcecode.php(~100KB),看起来是 Brainfuck 但实际上是 JSFuck——一种只用 []()!+ 六个字符编码 JavaScript 的技术。它利用 JavaScript 的类型转换(如 []+{}"[object Object]")来构造任意字符串和代码。

源码在 sourcecode.php,直接在浏览器里 eval 这坨代码不安全——它会弹出 alert 并重定向到 Google。

Solution

核心方法是离线 sandbox 执行 JSFuck 代码,观察其行为:

1
curl -s -b 'WC=...' 'https://www.wechall.net/en/challenge/brainfucked/sourcecode.php' > jsfuck.txt

用 Node.js 搭建一个 mock browser 环境(拦截 alertdocument.location 等):

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
34
35
36
37
38
39
40
41
42
const vm = require("vm");
const fs = require("fs");
const code = fs.readFileSync("jsfuck.txt", "utf8").trim();

let capturedAlerts = [];
let locationHref = "";

const sandbox = {
alert: (...args) => capturedAlerts.push(...args),
document: {
title: "",
location: {
set href(v) {
locationHref = v;
},
},
},
location: {
set href(v) {
locationHref = v;
},
},
Array,
String,
Number,
Boolean,
Object,
Function,
RegExp,
Math,
Date,
JSON,
setTimeout: () => 0,
setInterval: () => 0,
console: { log() {}, warn() {}, error() {} },
};

vm.createContext(sandbox);
vm.runInContext(code, sandbox, { timeout: 30000 });

console.log("Alerts:", capturedAlerts);
console.log("Redirect:", locationHref);

执行后会输出:

1
2
Alerts: [ 18 ]
Redirect: https://www.google.co.uk

这对应解码后的代码:

1
2
3
4
var s = "UnfudgedDebugStuff";
s = s.length; // 此时 s = 18
alert(s); // 弹 18
document.location.href = "https://www.google.co.uk";

关键陷阱:

  • alert 显示的是 18(字符串长度),但这不是答案。
  • 答案是原始字符串 UnfudgedDebugStuff,不是它的长度。
  • 页面会重定向到 Google,所以不要在浏览器里直接 eval。
  • JSFuck 和 Brainfuck 完全不同——Brainfuck 用 <>+-.,[],JSFuck 用 []()!+
UnfudgedDebugStuff