DEV Community ๐Ÿ‘ฉโ€๐Ÿ’ป๐Ÿ‘จโ€๐Ÿ’ป

DEV Community ๐Ÿ‘ฉโ€๐Ÿ’ป๐Ÿ‘จโ€๐Ÿ’ป is a community of 964,423 amazing developers

We're a place where coders share, stay up-to-date and grow their careers.

Create account Log in
Luka Vidakoviฤ‡
Luka Vidakoviฤ‡

Posted on • Originally published at lvidakovic.com

Javascript ghosts

This posts follows the one about call stack obfuscation. Itโ€™s just a proof of concept to further cover the tracks of execution in the browser.

Itโ€™s possible to cut off relation of executed code with the script that brought it into execution environment! This may sound abstract. Put in another way, you can hide the script source from the debugger. Itโ€™s pretty simple to do:

const head = document.querySelector('head')
const evilScript = document.createElement('script')
evilScript.text = `
  const malicious = () => { throw new Error() }
  malicious()
`
head.append(evilScript)
head.removeChild(evilScript)
Enter fullscreen mode Exit fullscreen mode

This nifty piece of code creates a script, sets itโ€™s โ€˜codeโ€™, adds it to the head of the document an immediately removes it from the DOM. The code inside the added script will run malicious code for which the origin will seem to be javascript virtual machine(VM) and not originating script tag or external script(if used).

What happens here is that scriptโ€™s code is pushed to the browserโ€™s memory and starts executing. In the meantime the DOM reference to the script is removed. This seems to unlink the code that will be executed from itโ€™s origin, at least in the debuggerโ€™s eyes:

VM84:2 Uncaught Error
    at malicious (<anonymous>:2:35)
    at <anonymous>:3:3
    at <anonymous>:7:6
Enter fullscreen mode Exit fullscreen mode

Following the stack trace leads to anonymous virtual machine script.

Top comments (0)

Visualizing Promises and Async/Await ๐Ÿคฏ

async await

โ˜๏ธ Check out this all-time classic DEV post