# SECCON 2020 Online CTF - Capsule & Beginner's Capsule - Author's Writeup
## Author
@hakatashi 
## Challenge Summary
The task is quite obvious from the appearence of the given website.
![](https://i.imgur.com/6WZBHgQ.png)
You can arbitrarily change the code below the given header and the task is to get the value stored in ESNext's [Private Class Field](https://v8.dev/features/class-fields#private-class-fields). *Decapsulation.*
```jsconst fs = require('fs');const {enableSeccompFilter} = require('./lib.js');
class Flag {  #flag;  constructor(flag) {    this.#flag = flag;  }}
const flag = new Flag(fs.readFileSync('flag.txt').toString());fs.unlinkSync('flag.txt');
enableSeccompFilter();
// input goes here```
`enableSeccompFilter` function is just for preventing dumb solution to read out `/proc/self/mem` so you don't have to care about it.
## Capsule: Intended Solution
You can access [V8's inspector API](https://chromedevtools.github.io/devtools-protocol/) from [Node.js](https://nodejs.org/api/inspector.html) and get hidden property like this.
Note that you must put `flag` variable to the global scope to inspect.
```jsglobal.flag = flag;const inspector = require('inspector');const session = new inspector.Session();session.connect();session.post('Runtime.evaluate', {expression: 'flag'}, (e, d) => { session.post('Runtime.getProperties', {objectId: d.result.objectId}, (e, d) => {    console.log(d.privateProperties[0].value.value);  });});```
(I didn't know it, but this is mentioned [here](https://github.com/nodejs/node/issues/27404#issuecomment-569924796))
## Capsule: Unintended Solution
You can inject fake `require` function using [function hoisting](https://developer.mozilla.org/en-US/docs/Glossary/Hoisting) and read `flag.txt` before it is removed.
```jsfunction require() {  const fs = process.mainModule.require('fs');  console.log(fs.readFileSync('flag.txt').toString());}```
So basic... :man-facepalming:
## Capsule: Unintended Solution
We expected Node.js cannot directly read memory without `/proc/self/mem`, but actually it is possible using [v8.getHeapSnapshot](https://nodejs.org/api/v8.html#v8_v8_getheapsnapshot).
```jsconst v8 = require('v8');const memory = v8.getHeapSnapshot().read();const index = memory.indexOf('SEC' + 'CON');const len = memory.slice(index).indexOf('}');const flagBuffer = memory.slice(index, index + len + 1);console.log(flagBuffer.toString());```
