Skip to content
KitploitKITPLOIT
ИнструментыБлог
Отправить
ИнструментыБлог
Отправить

Инструменты для хакинга, пентеста и кибербезопасности — ваш арсенал защиты!

Kitploit — это каталог инструментов для хакинга, кибербезопасности и пентестинга. Находите последние обновления проектов для поиска уязвимостей, анализа систем, автоматизации тестирования и усиления вашей безопасности.

··Ленты·Контакты·Конфиденциальность·© 2026 Kitploit

Каталог инструментов

Категории

Все категории
Loading categories
clr — Проверка времен жизни и других уточняющих типов | Kitploit
Инструменты/GitHubGitHub/ityonemo/clr
Статический анализАнализ уязвимостейАнализ КодаФаззингАнализ Бинарных ФайловОбучение и Образование
GitHubityonemo/clr

clr

Проверка времен жизни и других уточняющих типов

Репозиторий
277221 дней назадПроверено Kitploit

Популярное

Смотреть все →

Откройте для себя самые используемые инструменты нашего сообщества.

Изучить все инструменты

Просмотрите нашу коллекцию инструментов

Смотреть все инструменты →
Поделиться

CLR

Проверка

времени жизни и других

уточняющих типов

для Zig

Видео: https://www.youtube.com/watch?v=mf0WzTOe-40 Спонсорство: https://buymeacoffee.com/dnautics

обсуждение на hn: https://news.ycombinator.com/item?id=42923829

обсуждение на lobste.rs: https://lobste.rs/s/9sitsj/clr_checker_for_lifetimes_other

видео с демонстрацией: https://www.youtube.com/watch?v=ZY_Z-aGbYm8

Обзор

Этот проект создаёт транспилятор Zig для компилятора Zig, который преобразует AIR (абстрактное промежуточное представление) в исходный код Zig, выполняющий статический анализ во время компиляции. Сгенерированный анализатор выявляет проблемы безопасности памяти, такие как использование до присваивания, использование после освобождения, утечки указателей на стек, а также специфические для Zig UB, такие как утверждения о ненулевости, нарушения размеченных объединений или неправильное использование fieldParentPtr.

Цель — обеспечить гарантии безопасности памяти на уровне Rust в Zig с помощью статического анализа AIR, без изменения самого языка.

CLR зависит от форкнутой версии компилятора Zig (включённой как подмодуль в zig/), которая добавляет поддержку маршрутизации AIR во внешние плагины. При вызове с -ofmt=air -fair-out=<plugin.so> компилятор загружает указанную разделяемую библиотеку и передаёт ей сгенерированный AIR для обработки.

Безопасно-ориентированная архитектура

CLR предназначен для продвижения программ к шаблонам жизненного цикла, которые являются явными и локально проверяемыми, а не просто для распознавания каждого технически корректного Zig-программы. Когда возможны два представления, CLR предпочитает то, которое делает состояние ресурса видимым в типе и структуре потока управления.

Например, избегайте условного закрытия не-опционального файлового дескриптора:

root@kitploit:~
const file = try std.fs.cwd().openFile(path, .{});
if (should_close) {
    file.close(); // Плохо: после этой ветки file неоднозначно открыт.
}

Предпочтительнее представлять условное владение с помощью опционального типа:

root@kitploit:~
var file: ?std.fs.File = null;
if (should_open) {
    file = try std.fs.cwd().openFile(path, .{});
}

if (file) |open_file| {
    open_file.close();
}

Условное закрытие не-опционального дескриптора оставляет его жизненный цикл неоднозначным после ветки. Предполагаемая политика CLR — отклонять такой шаблон, а не нести постоянное состояние «возможно закрыто».

Тот же принцип применим к выделенным указателям. Не освобождайте память через производный указатель:

root@kitploit:~
const allocation = try allocator.alloc(u8, size);
const payload = allocation[header_size..];
allocator.free(payload); // Плохо: payload — это не базовый адрес выделения.

Держите указатель на базовый адрес выделения доступным для освобождения, а производные указатели используйте только для доступа:

root@kitploit:~
const allocation = try allocator.alloc(u8, size);
defer allocator.free(allocation);

const payload = allocation[header_size..];
use(payload);

Освобождение указателя на поле, подмассива или указателя, полученного арифметикой, отклоняется, если документированное внутреннее правило не восстанавливает происхождение от базового выделения.

Эти политики по умолчанию строги, поскольку они создают код с более простыми и легко проверяемыми жизненными циклами ресурсов. В будущем механизм unsafe аннотаций позволит отдельным GID или операциям отказываться от отдельных анализов. Это поддержит код, который намеренно принимает более слабые проверки в обмен на производительность, не ослабляя модель по умолчанию для остальной программы.

Состояние

Это активная переработка исходного прототипа на Elixir в Zig. Реализация на Zig загружается как плагин компилятора и анализирует AIR напрямую.

На данный момент реализовано:

  • Отслеживание неопределённых значений (использование до присваивания, отслеживание на уровне полей для структур)
  • Анализ безопасности памяти (использование после освобождения, двойное освобождение, утечки памяти, несоответствие аллокаторов, утечки стека)
  • Полное покрытие интерфейса std.mem.Allocator:
    • create/destroy — выделение одного элемента
    • alloc/free — выделение среза (включая alignedAlloc, allocSentinel и т.д.)
    • realloc/remap — перевыделение среза с отслеживанием освобождения старого среза
    • dupe/dupeZ — дублирование среза
    • Обнаружение несоответствия аллокаторов (освобождение не тем аллокатором, create/destroy против alloc/free)
    • Сложные типы аллокаторов (GPA, ArenaAllocator, FixedBufferAllocator)
  • Отслеживание жизненного цикла ArenaAllocator:
    • init// — полный жизненный цикл арены

Запланировано (подробнее см. LIMITATIONS.md):

  • async/await
  • Безопасность псевдонимов (обнаружение конфликтующих изменяемых ссылок)
  • Уточнения указателей из нескольких источников для слитого или косвенного происхождения указателей
  • Анализ псевдонимов дескрипторов за пределами текущих шаблонов распространения fd
  • Более полные межпроцедурные/глобальные сводки мутаций
  • Распознавание понижения приведения выравнивания
  • Безопасность мьютексов (сопряжение lock/unlock, обнаружение взаимоблокировок)
  • Пользовательская способность приведения (определяемые пользователем правила уточнения)

Предварительные требования

  • Zig 0.15.2 (системная установка с поддержкой LLVM)
  • Linux (в настоящее время только Linux из-за прямого использования системных вызовов)
  • BATS (для интеграционных тестов): sudo apt install bats

Сборка

Поставляемый компилятор Zig и плагин libclr должны быть собраны с одинаковыми уровнями оптимизации. Несовпадение уровней оптимизации приведёт к segfault.

root@kitploit:~
# Сборка пользовательского компилятора Zig с ReleaseFast (только в первый раз или после изменений подмодуля)
cd zig && zig build --zig-lib-dir lib -Doptimize=ReleaseFast && cd ..

# Сборка плагина CLR с соответствующей оптимизацией
zig build -Doptimize=ReleaseFast

Для разработки/отладки используйте ReleaseSafe или Debug для обоих:

root@kitploit:~
# ReleaseSafe (с проверками безопасности, немного медленнее)
cd zig && zig build --zig-lib-dir lib -Doptimize=ReleaseSafe && cd ..
zig build -Doptimize=ReleaseSafe

# Debug (полная отладочная информация, самый медленный)
cd zig && zig build --zig-lib-dir lib && cd ..
zig build

Использование

root@kitploit:~
# Компиляция Zig-файла с помощью бэкенда AIR
zig/zig-out/bin/zig build-exe -fair-out=zig-out/lib/libclr.so -ofmt=air -femit-bin=output.air.zig your_file.zig

# Запуск сгенерированного анализатора
zig run --dep clr -Mroot=output.air.zig -Mclr=lib/lib.zig

Вывод идёт в stderr.

Тестирование

root@kitploit:~
# Модульные тесты (codegen/DLL)
zig build test

# Модульные тесты (библиотека времени выполнения)
zig test lib/lib.zig

# Отдельный интеграционный тестовый файл
bats test/integration/fd.bats

# Интеграционные тесты (требуется BATS)
# По умолчанию ReleaseFast; можно переопределить через OPTIMIZE=ReleaseSafe или OPTIMIZE=Debug
./run_integration.sh

# Ручной тест отдельного файла
./run_one.sh test/cases/undefined/use_before_assign.zig

Примечание: Интеграционные тесты пересобирают libclr с указанным уровнем оптимизации (по умолчанию: ReleaseFast). Убедитесь, что ваш поставляемый компилятор Zig собран с таким же уровнем оптимизации.

Структура проекта

root@kitploit:~
clr/
├── src/                     # Код DLL/плагина (генерирует .air.zig)
│   ├── clr.zig              # Главная точка входа плагина CLR
│   ├── codegen.zig          # Генерирует исходный код .air.zig из инструкций AIR
│   └── allocator.zig        # Аллокаторная обёртка, безопасная для DLL
├── lib/                     # Библиотека анализа времени выполнения
│   ├── lib.zig              # Точка входа библиотеки
│   ├── tag.zig              # AnyTag union, Type, обработчики тегов, диспетчеризация splat
│   ├── Inst.zig             # Результаты инструкций и межпроцедурный анализ
│   ├── Refinements.zig      # Уточняющие типы (указатель, структура, опционал и т.д.)
│   ├── Analyte.zig          # Контейнер состояния анализа
│   ├── Context.zig          # Контекст выполнения (метаданные, отчёт об ошибках)
│   └── analysis/            # Модули анализа
│       ├── undefined_safety.zig  # Отслеживание использования до присваивания
│       ├── memory_safety.zig     # Отслеживание выделения/освобождения
│       ├── null_safety.zig       # Проверка распаковывания опционала
│       ├── variant_safety.zig    # Доступ к полям размеченного объединения
│       └── fd_safety.zig         # Отслеживание файловых дескрипторов
├── test/
│   ├── integration/         # Интеграционные тесты BATS
│   │   ├── test_helper.bash
│   │   └── *.bats
│   └── cases/               # Входные файлы тестов (.zig)
├── zig/                     # Подмодуль компилятора Zig (инструментированный форк)
├── build.zig                # Конфигурация сборки
└── build.zig.zon            # Зависимости пакета

Общая идея

диаграмма

Zig — это famously «небезопасный» язык. Управление памятью осуществляется вручную, что открывает возможность ошибок реализации. Хотя Zig снижает проблемы безопасности относительно C за счёт устранения выхода за границы массива и разыменования нулевого указателя в коде с проверками безопасности, он всё ещё менее безопасен, чем Rust, который устраняет использование после освобождения, двойное освобождение и гонки данных с помощью статического анализа.

Вдохновлённый проектом MIRI от Rust, CLR выполняет статический анализ промежуточного представления AIR в Zig для достижения более высокой степени безопасности, чем предоставляет Zig «из коробки». В отличие от MIRI, который интерпретирует MIR Rust в изолированной псевдо-среде выполнения, CLR транспилирует AIR в исходный код Zig, который статически выполняет анализ. Обратите внимание, что сгенерированный воздушный код Zig в принципе может быть выполнен во время компиляции, но, пропуская его через промежуточный Zig, мы получаем легко понимаемый и отлаживаемый логический поток. Амбициозный человек мог бы использовать этот общий подход для создания другого целевого вывода, например, языка для доказательства теорем, или реорганизовать его, чтобы он работал полностью внутри компилятора Zig!

Ключевая идея: если для проектов на Rust, ориентированных на безопасность, всё равно нужен MIRI, почему бы не выбрать более простой язык и не выполнять анализ в стиле MIRI, чтобы получить проверку заимствований и другие уточняющие типы? Этот проект показывает, что такое будущее реально для Zig.

Конвейер компиляции Zig:

  1. Код Zig / AST
  2. Zig ZIR (нетипизированное, пофайловое промежуточное представление)
  3. Zig AIR (типизированное, пофункциональное IR, реализованное для полиморфных функций)
  4. Целевые платформы компилятора

AIR — идеальный уровень для анализа, поскольку он типизирован, интерпретируем как «минимально жизнеспособный» список обобщённых инструкций программирования и позволяет расширять типы с помощью метаданных уточнения.

Подробнее о том, как работает AIR в Zig, см. в блоге Mitchell Hashimoto: https://mitchellh.com/zig/sema

Лицензия

Лицензия MIT — подробнее см. LICENSE.

Скачать инструмент
deinit
allocator
  • Выделения арены освобождаются при deinit (нет ложных положительных срабатываний утечек)
  • Обнаружение использования после deinit, двойного deinit, выделения после deinit
  • Несоответствие между разными аллокаторами (арена против page_allocator)
  • Отслеживание производных указателей (невозможно освободить указатели на поля, подмассивы — только корневые выделения)
  • Безопасность арифметики указателей (блокировка ptr_add/ptr_sub на указателях на один элемент)
  • Безопасность нулевых значений (обнаружение непроверенного распаковывания опционала)
  • Безопасность вариантов (доступ к неактивным полям объединения, неоднозначный вариант после веток)
  • Безопасность FieldParentPtr (обнаружение неверного восстановления контейнера из указателя на поле)
  • Межпроцедурный анализ (отслеживание значений через вызовы функций с помощью аргументов-указателей)
  • Отслеживание указателей на функции (косвенные вызовы направляются к возможным целям)
  • Отслеживание полей структур и объединений (поля-указатели, вложенные типы)
  • Отслеживание срезов (выделение/освобождение с регионами, порождение подмассивов)
  • Поддержка Error Union (выражения try, обёртка/развёртка полезной нагрузки)
  • Поддержка Switch (слияние из N путей с отслеживанием вариантов)
  • Поддержка помеченного switch/устройства Даффа
  • Отслеживание исходного местоположения и имени переменной для сообщений об ошибках
  • Ветвление/поток управления со слиянием состояний
  • Анализ циклов (for, while, for-else, while-else с итерацией фиксированной точки)
  • Отслеживание глобальных переменных (неопределённость, варианты и безопасность памяти)
  • Рекурсивные типы данных (связные списки, деревья, рекурсивные объединения)
  • Сокращения на границе stdlib для распространённых шаблонов, таких как std.process.args, std.mem.asBytes, std.HashMap, и API аллокаторов/файлов
  • Привилегированные уточнения std.HashMap с канонической идентичностью метаданных/ключей/значений при put, get, getPtr и итерации по значениям
  • Безопасность файловых дескрипторов:
    • Отслеживание posix.open/close/dup/dup2/socket/accept/epoll_create/pipe
    • Обнаружение использования после close (чтение/запись/dup на закрытом fd)
    • Обнаружение двойного close
    • Обнаружение утечек fd при выходе из функции и финализации модуля
    • Отслеживание локальных дескрипторов с выходом из области видимости, чтобы псевдонимы, остающиеся живыми, предотвращали преждевременные сообщения об утечках
    • Распространение возвращаемых значений и агрегатов для охваченных шаблонов дескрипторов
    • Обнаружение неопределённых аргументов fd (close/read/write с неопределённым fd)