Проект представляет собой кроссплатформенное решение для массового анализа файлов.
Консольное приложение передает параметры в библиотеку scanner_lib, которая:
- читает файлы бинарно;
- определяет формат каждого файла;
- извлекает метаданные и техническую информацию;
- рассчитывает хеши и энтропию;
- сохраняет результат анализа в отдельный JSON файл.
В дальнейшем планируется графическое приложение на Qt, использующее ту же библиотеку, а также поддержку загрузки собственных структур для обработки на оснвое правил yara.
На данном этапе версия программы не является релизной, поэтому могут быть характерны неточности в выдачи результата.
-
Кроссплатформенность
Поддержка операционных систем Windows, Linux и MacOS (C++20, CMake). -
Расчет криптографических хешей и энтропии
Использование OpenSSL для вычисления хешей (например, MD5, SHA-1, SHA-256)
и Shannon энтропии содержимого. -
Чтение поддерживаемых форматов Чтение поддерживаемых форматов файлов с возможностью добавления своего формата путём перекомпиляции библиотеки
-
Формат результата
Для каждого файла создается отдельный JSON файл с общей и форматозависимой информацией.
- Многопоточная обработка
Использование трех стадий конвейера обработки с очередью:- Поток чтения файла.
- Поток анализа и определения формата.
- Поток записи результата в JSON.
- Быстрая работа анализа структуры файлов и запись результата в json формат
sudo apt update
sudo apt install cmake g++ libssl-dev nlohmann-json3-dev
git clone https://github.com/Mraxzist/BinScan.git
cd BinScan
mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Release
cmake --build . --config Releasebrew install cmake openssl nlohmann-json
git clone https://github.com/Mraxzist/BinScan.git
cd BinScan
mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Release -DOPENSSL_ROOT_DIR=$(brew --prefix openssl)
cmake --build . --config ReleaseОткрыть x64 Native Tools Command Prompt for VS 2022 и выполнить:
git clone https://github.com/Mraxzist/BinScan.git
cd BinScan
mkdir build && cd build
cmake -S . -B build -G "Visual Studio 17 2022"
cmake --build build --config Releasegit clone https://github.com/Mraxzist/BinScan.git
cd BinScan
mkdir build && cd build
cmake -S . -B build
cmake --build build --config Release.\build\bin\Release\ProjectMassScanFiles.exe --input ".\example" --output ".\result" --threads 3 --queue 4096 --lib "C:\Forensic\scanner_lib.dll"
В данном примере задаются:
--input - каталог с файлами для анализа;
--output - каталог для сохранения JSON-отчетов;
--threads - режим работы в три потока (чтение, анализ, запись);
--queue - емкость внутренней очереди;
--compact-json - вывод JSON в компактном виде. Необязателен;
--lib - явное указание пути к динамической библиотеке scanner_lib. По умолчанию поиск библиотеки ведётся в текущем расположении исполняемого файла.
Если количество потоков и размер очередей зашиты в код, а не задаются параметрами, это усложняет адаптацию под разные машины (от слабых ноутбуков до серверов).
При большом количестве форматов логика расширения через статическую компоновку начинает мешать: нельзя легко собирать "урезанные" сборки (например, только PE+ELF без Android), нельзя подключать свои внутренние парсеры без пересборки scanner_lib и редактирования логики кода.
Быстрая работа приложения обеспечивается сочетанием архитектурных решений и оптимизаций на уровне реализации.
-
Конвейерная обработка в несколько потоков
Внутриscanner_libреализован трехстадийный конвейер:- поток чтения файлов;
- поток анализа и детектирования формата;
- поток записи JSON.
Стадии работают параллельно и связаны через блокирующие очереди. Это позволяет:
- не блокировать анализ во время чтения и записи на диск;
- эффективно использовать многоядерные процессоры;
- обрабатывать большое количество файлов в режиме массового сканирования.
-
Загрузка логики в виде отдельной библиотеки
Основная логика вынесена в динамическую библиотекуscanner_lib(.dll/.so), которая подгружается приложением:- консольное и графическое приложение остаются тонкими оболочками, передающими параметры сканирования;
- при многократных запусках в составе долгоживущего процесса (GUI) снижается накладной расход на повторную инициализацию логики.
-
Эффективная работа с памятью и вводом-выводом
- файлы читаются бинарно крупными блоками;
- данные передаются между стадиями через структуры и буферы без лишнего копирования (использование современных возможностей C++20);
- формат определяется по сигнатурам и заголовкам без полного разбора всего содержимого, что уменьшает объем работы для неподходящих или поврежденных файлов.
В совокупности эти решения позволяют использовать scanner_lib как высокопроизводительное ядро для массового анализа файлов в консольных утилитах, графических приложениях и внешних инструментах при исследовании структуры файлов.
На текущий момент реализована обработка следующих типов файлов (по сигнатуре и структуре):
-
Исполняемые форматы:
- PE (Windows)
- ELF (Linux, Unix)
- Mach-O (macOS)
-
Архивы и контейнеры:
- ZIP
- торрент файлы (torrent)
- APK (Android пакеты)
- MSI (установочные пакеты Windows)
-
Документные форматы:
- DOC и связанные OLE форматы
- XLS
- PPT
- MSG (формат почтовых сообщений)
- EML
-
Графические форматы:
- JPG (в том числе извлечение EXIF по возможности)
- PNG
-
В разработке чтения:
- Образы Android (boot, recovery, init и другие из
android_boot_recovery_init_info.cpp) - Другие PK-основные форматы через классификатор
pk_classifier
(например, форматы семейства Office на базе ZIP, APK и т.п.). Список форматов постепенно расширяется.
- Образы Android (boot, recovery, init и другие из
Проект включает два основных компонента:
-
Консольное приложение
Исполняемый файлProjectMassScanFiles:- разбирает параметры командной строки;
- загружает динамическую библиотеку
scanner_lib
(scanner_lib.dllдля Windows,scanner_lib.soдля Linux); - передает в библиотеку настройки сканирования;
- выводит ход обработки (при необходимости).
-
Библиотека
scanner_lib
Содержит основную логику сканирования:- Анализаторы форматов (
analyzersиparsers). - Общие функции вычисления хешей и энтропии (
hash_entropy.hpp). - Реализация конвейера с очередью (
pipeline/blocking_queue.hpp). - Запись результатов в JSON (
writers/json_writer.*). - Точки входа для вызова из приложения (
scanner_lib.cpp).
- Анализаторы форматов (
BinScan/
├─ CMakeLists.txt
├─ LICENSE
├─ logo.png
├─ ProjectMassScanFiles.cpp
├─ README.md
│
├─ scanner_lib/
│ └─ nlohmann/
│ └─ json.hpp
│
└─ src/
├─ analyzers/
│ ├─ parsers/
│ │ ├─ android_boot_recovery_init_info.cpp
│ │ ├─ android.hpp
│ │ ├─ apk_info.cpp
│ │ ├─ doc_info.cpp
│ │ ├─ elf_info.cpp
│ │ ├─ eml_info.cpp
│ │ ├─ jpg_info.cpp
│ │ ├─ mach_o_info.cpp
│ │ ├─ msg_info.cpp
│ │ ├─ msi_info.cpp
│ │ ├─ ole_common.hpp
│ │ ├─ parsers.hpp
│ │ ├─ pdf_info.cpp
│ │ ├─ pe_info.cpp
│ │ ├─ pk_classifier.cpp
│ │ ├─ pk_classifier.hpp
│ │ ├─ png_info.cpp
│ │ ├─ ppt_info.cpp
│ │ ├─ torrent_info.cpp
│ │ ├─ xls_info.cpp
│ │ └─ zip_info.cpp
│ │
│ ├─ detector.cpp
│ ├─ detector.hpp
│ └─ hash_entropy.hpp
│
├─ pipeline/
│ └─ blocking_queue.hpp
│
├─ writers/
│ ├─ json_writer.cpp
│ └─ json_writer.hpp
│
├─ scanner_lib.cpp
├─ utf8_console.cpp
└─ utf8_console.hpp
Внутри scanner_lib реализован трехстадийный конвейер обработки файлов.
Все стадии изолированы друг от друга и взаимодействуют через потокобезопасные очереди (pipeline/blocking_queue.hpp), что обеспечивает масштабируемость и кроссплатформенность.
-
Поток чтения файлов:
- обходит указанную директорию;
- формирует задания на обработку для каждого файла;
- читает содержимое файла в буфер байтов;
- передает структуру с путем и содержимым файла в очередь на анализ.
-
Поток анализа и детектирования формата:
- извлекает задание из очереди чтения;
- определяет тип файла с помощью
analyzers/detector.*иparsers/pk_classifier.*; - выбирает соответствующий парсер формата из
analyzers/parsers; - извлекает структуру файла и метаданные;
- рассчитывает хеши и энтропию (
hash_entropy.hpp); - формирует объект
jsonс общими и форматозависимыми полями; - отправляет результат в очередь на запись.
-
Поток записи JSON:
- извлекает результат анализа;
- передает данные в
writers/json_writer.*; - сохраняет их в выходную директорию в виде отдельного JSON файла.
Такое разделение на стадии позволяет параллельно выполнять операции ввода-вывода, анализа и записи, что особенно важно при массовом сканировании больших наборов файлов.
Файл pipeline/blocking_queue.hpp реализует обобщенную блокирующую очередь:
- очередь параметризуется типом элементов (например, задачей чтения или структурой результата анализа);
- обеспечивает безопасный доступ из нескольких потоков;
- поддерживает операции
pushиpopс блокировкой; - предоставляет механизм корректного завершения конвейера (сигнал о прекращении подачи задач).
Очереди используются для связи между:
- потоком чтения и потоком анализа;
- потоком анализа и потоком записи.
Модуль analyzers отвечает за определение формата и детальный разбор файлов.
- Определяет тип файла по сигнатурам, заголовкам и структуре.
- Не опирается только на расширение, что позволяет корректно обрабатывать переименованные и подозрительные файлы.
- Использует вспомогательные функции и общие константы для проверки "магических" чисел и структурных признаков.
Каждый формат имеет отдельный парсер, реализованный в соответствующем файле:
pe_info.cpp- анализ PE файлов:- общая информация о заголовке;
- список секций;
- таблицы импорта и экспорта;
- дополнительные поля при необходимости.
elf_info.cpp- анализ ELF файлов:- заголовок ELF;
- секции и сегменты;
- динамическая информация и т. д.
mach_o_info.cpp- анализ Mach-O:- архитектура;
- load commands;
- секции и сегменты.
pdf_info.cpp- анализ PDF:- базовая структура;
- версия;
- количество объектов;
- наличие скриптов и вложенных файлов при необходимости.
doc_info.cpp,xls_info.cpp,ppt_info.cpp,ole_common.hpp- анализ OLE и связанных форматов.zip_info.cpp,apk_info.cpp,torrent_info.cpp,msi_info.cpp- анализ архивов и контейнеров.jpg_info.cpp,png_info.cpp- анализ графических форматов, при возможности извлечение метаданных.android_boot_recovery_init_info.cpp,android.hpp- анализ специализированных образов Android.
Файл parsers.hpp содержит общие объявления и интерфейсы для вызова парсеров, что упрощает добавление новых форматов.
Модуль writers отвечает за сериализацию и сохранение результатов анализа.
- Принимает на вход структуру с результатами анализа файла.
- Формирует итоговый JSON документ:
- общие поля (путь, имя, размер, формат, хеши, энтропия);
- форматозависимый раздел (
"pe","elf","pdf","zip"и т. д.).
- Сохраняет JSON в указанную выходную директорию.
- Может поддерживать два режима:
- человекочитаемый формат (с отступами);
- компактный формат (без лишних пробелов и переносов строк).
Добавление нового формата в scanner_lib выполняется по единому шаблону. Это упрощает поддержку и делает архитектуру библиотеки предсказуемой.
- Определить сигнатуры и структурные признаки формата.
- Внести изменения в
analyzers/detector.*:- добавить проверку "магических" чисел (например, первые байты файла);
- при необходимости добавить дополнительные проверки структуры (заголовки, смещения, размеры).
- При наличии контейнера на базе ZIP/PK (например, новый офисный формат) или общего используемого формата, при необходимости задействовать требуемый классификатор для первичной классификации содержимого и простоты в чтении и добавлении поддержки новых форматов.
Цель этого шага - чтобы конвейер уверенно определял тип файла, не полагаясь только на расширение.
Логика проверки магических чисел заключена в:
nlohmann::json analyze_file(const std::filesystem::path&,
const std::vector<std::uint8_t>& data,
std::string& detected_type,
std::string& err)
-
Создать новый файл в
analyzers/parsers, например:myformat_info.cpp- для условного форматаmyformat.
-
Реализовать в нем функции разбора, которые:
- принимают на вход буфер байтов и общую структуру контекста файла;
- анализируют заголовки, таблицы, секции, объекты и метаданные;
- формируют структуру данных, которая затем будет преобразована в JSON.
-
Описать форматозависимый раздел JSON:
- выделить логически целостные части (заголовок, секции, записи, метаданные);
- избегать избыточности и дублирования полей, уже присутствующих на верхнем уровне;
- использовать читаемые и стабильные имена полей.
Примерно так же устроены существующие парсеры:
pe_info.cpp- PE;elf_info.cpp- ELF;mach_o_info.cpp- Mach-O;pdf_info.cpp- PDF;doc_info.cpp,xls_info.cpp,ppt_info.cpp,ole_common.hpp- OLE и связанные форматы;zip_info.cpp,apk_info.cpp,torrent_info.cpp,msi_info.cpp- архивы и контейнеры;jpg_info.cpp,png_info.cpp- графические форматы;android_boot_recovery_init_info.cpp,android.hpp- образы Android.
-
Внести изменения в
parsers.hpp(и при необходимости в соответствующую реализацию), чтобы:- новый формат был включен в общий интерфейс парсеров;
- конвейер мог по идентификатору формата вызвать нужную функцию разбора.
-
При необходимости расширить перечисления или константы, описывающие список поддерживаемых форматов.
Это обеспечивает единообразный способ вызова парсеров из потока анализа.
При добавлении нового формата важно убедиться, что:
- парсер не хранит разделяемое состояние между вызовами;
- все данные, связанные с конкретным файлом, локальны для стека или передаются по значению либо через умные указатели;
- не используются глобальные переменные без синхронизации.
Если для формата необходимо использовать общие ресурсы (например, кэш справочных таблиц), то:
- либо эти ресурсы должны быть неизменяемыми после инициализации;
- либо доступ к ним должен быть защищен (мьютекс,
std::call_onceи другие механизмы синхронизации).
Рекомендуется для каждого нового формата:
- подготовить набор тестовых файлов (валидных и поврежденных);
- проверить корректное определение формата детектором;
- убедиться, что парсер:
- корректно обрабатывает типовые файлы;
- устойчив к поврежденным и неполным данным;
- не приводит к исключениям и выходу за границы буфера.
Библиотека scanner_lib проектируется как общий компонент для:
- консольного приложения массового сканирования;
- будущего графического интерфейса;
- собственных реализаций механизмов использования библиотеки.
| Автор | Репозиторий |
|---|---|
| Niels Lohmann | Библиотека для работы с json форматами |
