-
Автор темы
- #1
Как обычно, более удобно на Notion:
Всем привет, сегодня мы препарируем Melonity Spoofer, и, поверьте, это будет интереснее, чем звучит.
Почему Melonity Spoofer?
Честно? Просто попался под руку.
Введение
Первым шагом в анализе любого исполняемого файла является изучение его сигнатур. Это могут быть визуальные признаки (названия секций, нестандартная точка входа) или алгоритмические подходы (расчет энтропии, поиск специфических последовательностей байтов).
![1721251452141.png 1721251452141.png](https://yougame.biz/data/attachments/281/281282-dd19f914df6533202e9782fd9dbbd0b2.jpg)
И что же видим? Иначально он был написан на Python, а затем упакован в единый исполняемый файл. Это типичная практика, преследующая две цели:
Теперь, когда мы знаем, что имеем дело с PyInstaller'ом, давайте разберемся, что у него внутри:
![1721251525236.png 1721251525236.png](https://yougame.biz/data/attachments/281/281283-26ffc1d8ae9c87c8ffab5531d7ed52f7.jpg)
Ключевые вещи, на что стоит взглянуть:
Чтобы распаковать наш файл нам нужно написать скрипт, который сделает пару этапов:
Проблема шифрования
Закинув наш файл в этот скрипт, мы столкнёмся с интересной ситуацией:
Большинство файлов не смогли распаковаться, скрипт подсказывает, что они упакованы. Взглянув на исходный код распаковщика Pyinstaller, можно увидеть, что файлы шифруются с помощью AES, а ключ хранится в отдельном
Открываем папку, и замечаем его, закидываем в дизассемблер виртуальной машины пайтон, и видим заветный ключ.
![1721251756968.png 1721251756968.png](https://yougame.biz/data/attachments/281/281284-945b3f9ebdbcc7e073d83b742aeaf348.jpg)
Хотя он со странным названием “0000qwemelox”, может автор спуфера на что-то намекает… Но нам это не важно, давайте резюмируем, что у нас есть:
Получается процесс дешифрования будет примерно таким: a. Чтение зашифрованного файла b. Отделение IV от зашифрованных данных c. Дешифрование с использованием AES в режиме CTR d. Декомпрессия расшифрованных данных с помощью zlib e. Добавление стандартного заголовка .pyc файла f. Сохранение расшифрованного .pyc файла
Пример ключевой части кода:
LLM как декомпилятор
Получив полностью расшифрованные скомпилированные пайтон файлы:
Первая же идея это закинуть в декомпилятор, тех которые действительно поддерживаются всего два:
А что если использовать Language Model (LLM) для декомпиляции? Спойлер: это сработало, и вот как.
Подробнее:
Использование LLM для декомпиляции принесло удивительные результаты:
Вот фрагмент кода, восстановленного с помощью LLM:
Но нельзя исключать возможность галлюцинаций у LLM, поэтому проверяйте, но всё же впечатляет.
Теперь собрав все файлы скрипта попробуем запустить, и убеждаемся, что всё идеально функционирует:
Как бонус разбор самого спуфера
Спуфер фундаментальный. Основной функционал:
Заключение
В целом это больше небольшое пособие по PyInstaller, и пример применения LLM в реверс-инженеринге.
Мой шиза-блог ( единственный щитпост блог по реверсу!! ):
Пожалуйста, авторизуйтесь для просмотра ссылки.
Всем привет, сегодня мы препарируем Melonity Spoofer, и, поверьте, это будет интереснее, чем звучит.
Почему Melonity Spoofer?
Честно? Просто попался под руку.
Введение
Первым шагом в анализе любого исполняемого файла является изучение его сигнатур. Это могут быть визуальные признаки (названия секций, нестандартная точка входа) или алгоритмические подходы (расчет энтропии, поиск специфических последовательностей байтов).
![1721251452141.png 1721251452141.png](https://yougame.biz/data/attachments/281/281282-dd19f914df6533202e9782fd9dbbd0b2.jpg)
И что же видим? Иначально он был написан на Python, а затем упакован в единый исполняемый файл. Это типичная практика, преследующая две цели:
- Избавить пользователей от головной боли с зависимостями (как мило с их стороны).
- Обфускация: усложнение анализа кода посторонними.
Теперь, когда мы знаем, что имеем дело с PyInstaller'ом, давайте разберемся, что у него внутри:
![1721251525236.png 1721251525236.png](https://yougame.biz/data/attachments/281/281283-26ffc1d8ae9c87c8ffab5531d7ed52f7.jpg)
Ключевые вещи, на что стоит взглянуть:
- CArchive: Содержит упакованные файлы, включая Python скрипты и модули.
- Table of Contents (TOC): Список всех файлов и их метаданные.
- Cookie: Важная информация для распаковки, метаданные условно
Чтобы распаковать наш файл нам нужно написать скрипт, который сделает пару этапов:
- Поиск магического числа:
- Ищем последовательность байтов MEI\\014\\013\\012\\013\\016 с конца файла.
- Это указывает на начало данных PyInstaller.
- Чтение Cookie:
- Извлекаем информацию о версии PyInstaller, позиции TOC, длине пакета.
- Для PyInstaller 2.0: 24 байта, для 2.1+: 24 + 64 байта.
- Парсинг TOC:
- TOC содержит записи фиксированной структуры.
- Каждая запись включает: позицию, размер сжатых/несжатых данных, флаги сжатия, тип данных, имя файла.
- Извлечение файлов:
- Для каждой записи в TOC:
- Читаем данные с указанной позиции.
- Если данные сжаты (флаг == 1), распаковываем через zlib.
- Сохраняем файл, восстанавливая структуру каталогов.
- Для каждой записи в TOC:
- Постобработка:
- Для .pyc файлов восстанавливаем корректный заголовок.
- Отдельно обрабатываем PYZ-архивы (специальные архивы Python-модулей).
Пожалуйста, авторизуйтесь для просмотра ссылки.
.Проблема шифрования
Закинув наш файл в этот скрипт, мы столкнёмся с интересной ситуацией:
Код:
[!] Error: Failed to decompress /expat.pyc in PYZArchive, likely encrypted. Extracting as is
[!] Error: Failed to decompress /sax/__init__.pyc in PYZArchive, likely encrypted. Extracting as is
[!] Error: Failed to decompress /xml/sax/_exceptions.pyc in PYZArchive, likely encrypted. Extracting as is
[!] Error: Failed to decompress /xml/sax/expatreader.pyc in PYZArchive, likely encrypted. Extracting as is
[!] Error: Failed to decompress /xml/sax/handler.pyc in PYZArchive, likely encrypted. Extracting as is
[!] Error: Failed to decompress /xml/sax/saxutils.pyc in PYZArchive, likely encrypted. Extracting as is
[!] Error: Failed to decompress /xml/sax/xmlreader.pyc in PYZArchive, likely encrypted. Extracting as is
[!] Error: Failed to decompress /zipfile.pyc in PYZArchive, likely encrypted. Extracting as is
[+] Successfully extracted pyinstaller archive: MelonitySpoofer.exe
Пожалуйста, авторизуйтесь для просмотра ссылки.
, под названием “pyimod00_crypto_key”.Открываем папку, и замечаем его, закидываем в дизассемблер виртуальной машины пайтон, и видим заветный ключ.
![1721251756968.png 1721251756968.png](https://yougame.biz/data/attachments/281/281284-945b3f9ebdbcc7e073d83b742aeaf348.jpg)
Хотя он со странным названием “0000qwemelox”, может автор спуфера на что-то намекает… Но нам это не важно, давайте резюмируем, что у нас есть:
- Структура зашифрованного файла:
- Первые 16 байт: Вектор инициализации (IV)
- Остальная часть: Зашифрованные и сжатые данные
- Ключ шифрования: Фиксированный ключ: 00000000qwemelox
Получается процесс дешифрования будет примерно таким: a. Чтение зашифрованного файла b. Отделение IV от зашифрованных данных c. Дешифрование с использованием AES в режиме CTR d. Декомпрессия расшифрованных данных с помощью zlib e. Добавление стандартного заголовка .pyc файла f. Сохранение расшифрованного .pyc файла
Пример ключевой части кода:
Python:
key = b"00000000qwemelox"
header = b"\\xA7\\x0D\\x0D\\x0A\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00"
def decrypt_file(input_path: Path, output_path: Path) -> None:
with input_path.open("rb") as en_f, output_path.open("wb") as de_f:
encrypted_data = en_f.read()
iv, ciphertext = encrypted_data[:16], encrypted_data[16:]
cipher = Cipher(algorithms.AES(key), modes.CTR(iv), backend=default_backend())
decryptor = cipher.decryptor()
decrypted_data = decryptor.update(ciphertext) + decryptor.finalize()
plaintext = zlib.decompress(decrypted_data)
de_f.write(header + plaintext)
Получив полностью расшифрованные скомпилированные пайтон файлы:
![](/proxy.php?image=https%3A%2F%2Fi.imgur.com%2Fr8yYzv3.png&hash=7c3cca5a1600d6b91346719f6e7d60ce)
Первая же идея это закинуть в декомпилятор, тех которые действительно поддерживаются всего два:
- Uncompyle6: Очень медленно появляется поддержка новых версий Python, наш файл он вовсе отказывается обрабатывать из-за версии.
- Пожалуйста, авторизуйтесь для просмотра ссылки.: Активно поддерживается сообществом, написан на С++, но к сожалению декомпиляции нашей версии ( 3.11 ) написана всего лишь на 35%.
![](/proxy.php?image=https%3A%2F%2Fi.imgur.com%2F4bX8o9t.png&hash=c8869b4ae7913ef4d5d8da72fa1258ce)
А что если использовать Language Model (LLM) для декомпиляции? Спойлер: это сработало, и вот как.
![](/proxy.php?image=https%3A%2F%2Fi.imgur.com%2FBkCwiwi.png&hash=0c31e2325a23ce58117b8f614befcdb5)
Подробнее:
- Дизассемблирование:
- Используем pycdc для преобразования .pyc файлов в ассемблероподобный код.
- Пример вывода:
0 RESUME 0
2 LOAD_CONST 0: '\\\\n@echo off\\\\n\\\\n:Cleaner\\\\nset "steam=$steam"\\\\n...'
4 STORE_NAME 0: script
6 LOAD_CONST 1: None
8 RETURN_VALUE
- Предобработка:
- Удаление лишней информации (номера строк, адреса в памяти).
- Подготовка промпта:
- Создание детального промпта, объясняющего задачу LLM.
- Пример части промпта:
You are an expert Python reverse engineer. Your task is to analyze the following disassembled Python bytecode and reconstruct the original source code. Pay attention to the logic flow, variable names, and function structures. If you're unsure about certain parts, provide your best guess and mark it with a comment.
- Использование LLM (Claude API):
- Отправка подготовленного промпта и дизассемблированного кода в API.
- Использование нескольких итераций для уточнения результатов.
- Анализ вывода с помощью другого LLM:
- Проверка сгенерированного кода на синтаксические ошибки.
- Сравнение логики с дизассемблированной версией.
Использование LLM для декомпиляции принесло удивительные результаты:
- Высокая точность: LLM смогла воссоздать весь код, включая структуру функций и логику.
- Восстановление имен переменных: Удивительно, но модель часто предлагала семантически верные имена переменных и функций.
- Комментарии и документация: LLM даже добавила комментарии, объясняющие сложные части кода.
- Обработка сложных конструкций: Модель успешно восстановила циклы, условные операторы и даже некоторые паттерны проектирования.
Вот фрагмент кода, восстановленного с помощью LLM:
![](/proxy.php?image=https%3A%2F%2Fi.imgur.com%2FZaWlG6R.png&hash=9d9522712129902cb3dbbccbab195485)
Но нельзя исключать возможность галлюцинаций у LLM, поэтому проверяйте, но всё же впечатляет.
Теперь собрав все файлы скрипта попробуем запустить, и убеждаемся, что всё идеально функционирует:
![](/proxy.php?image=https%3A%2F%2Fi.imgur.com%2FFa9vmgo.png&hash=2105972c05e58e616c39c87899edb8f5)
Как бонус разбор самого спуфера
Спуфер фундаментальный. Основной функционал:
- Вывод логотипа (важнейшая функция, конечно).
- Завершение процессов Steam и Dota 2.
- Проверка прав администратора.
- Создание и выполнение batch-файла.
- Предложение перезагрузки системы.
- Очистка конфигураций Steam и Dota 2 (удаление папок и файлов).
- Удаление записей реестра, связанных со Steam.
- Генерация нового MAC-адреса.
Заключение
В целом это больше небольшое пособие по PyInstaller, и пример применения LLM в реверс-инженеринге.
Мой шиза-блог ( единственный щитпост блог по реверсу!! ):
Пожалуйста, авторизуйтесь для просмотра ссылки.
Последнее редактирование: