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

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

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

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

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

Категории

Все категории
Loading categories
ruzzy — Фаззер, управляемый покрытием, для чистого кода Ruby и C-расширений Ruby | Kitploit
Инструменты/GitHubGitHub/trailofbits/ruzzy
Динамический анализ (песочница)Анализ уязвимостейАнализ КодаФаззингАнализ Бинарных ФайловОбучение и Образование
GitHubtrailofbits/ruzzy

ruzzy

Фаззер, управляемый покрытием, для чистого кода Ruby и C-расширений Ruby

Репозиторий
123742 месяцев назадПроверено Kitploit

Популярное

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

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

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

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

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

Ruzzy

Test Gem Version

Фаззер с управлением покрытием для чистого Ruby-кода и C-расширений Ruby.

Ruzzy во многом вдохновлён Atheris от Google — фаззером для Python. Ruzzy использует libFuzzer (или LibAFL) для инструментирования покрытия и в качестве движка фаззинга. Ruzzy также поддерживает AddressSanitizer и UndefinedBehaviorSanitizer при фаззинге C-расширений. Если вы хотите узнать больше о том, что вдохновило Ruzzy, см. нашу статью: Design and Implementation of a Coverage-Guided Ruby Fuzzer.

Содержание:

  • Установка
  • Использование
    • Начало работы
    • Фаззинг чистого Ruby-кода
    • Фаззинг C-расширений Ruby
  • API
    • Ruzzy
    • FuzzedDataProvider
  • Примечания для пользователей macOS
  • Найденные ошибки
  • Разработка
    • Компиляция
    • Тестирование
    • Линтинг
    • Релиз
  • Дополнительные материалы
  • Установка

    Ruzzy поддерживает Linux (x86-64, AArch64/ARM64) и macOS (Apple Silicon). В Windows вы можете собрать Dockerfile и/или использовать окружение для разработки. Ruzzy требует свежую версию clang (проверена работа начиная с 14.0.0), желательно последний релиз. Инструкции для macOS см. в примечаниях для пользователей macOS.

    Установите Ruzzy следующей командой:

    root@kitploit:~
    MAKE="make --environment-overrides V=1" \
    CC="/path/to/clang" \
    CXX="/path/to/clang++" \
    LDSHARED="/path/to/clang -shared" \
    LDSHAREDXX="/path/to/clang++ -shared" \
        gem install ruzzy
    

    Здесь происходит много всего, поэтому разберём по частям:

    • Переменная окружения MAKE переопределяет команду make при компиляции C-расширения Ruzzy. Она указывает make учитывать последующие переменные окружения при компиляции расширения.
    • Остальные переменные окружения используются во время компиляции, чтобы гарантировать использование правильных бинарников clang. Это обеспечивает наличие новейших возможностей clang, необходимых для корректного фаззинга.

    Если при установке возникнут проблемы, выполните следующую команду, чтобы получить отладочный вывод:

    root@kitploit:~
    RUZZY_DEBUG=1 gem install --verbose ruzzy
    

    Если ваша цель фаззинга на чистом Ruby активно использует регулярные выражения, установите regexp_parser:

    root@kitploit:~
    gem install regexp_parser
    

    После установки Ruzzy автоматически использует эту возможность для сэмплирования (т.е. решения) регулярных выражений, встречающихся во время фаззинга. Это позволяет фаззеру проходить условия с регулярными выражениями и открывать дополнительное покрытие.

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

    Начало работы

    Ruzzy включает игрушечный пример для демонстрации работы. Сначала задайте следующую переменную окружения:

    root@kitploit:~
    export ASAN_OPTIONS="allocator_may_return_null=1:detect_leaks=0:use_sigaltstack=0"
    
    Понимать эти опции не обязательно, но если вам интересно, нажмите сюда.

    ASAN_OPTIONS

    1. Отказы выделения памяти распространены и имеют низкое влияние (DoS), поэтому пока пропустим их.
    2. Как и Python, интерпретатор Ruby утекает данные, так что пока игнорируем это.
    3. Ruby рекомендует отключать sigaltstack.

    Затем можно запустить пример следующей командой:

    root@kitploit:~
    LD_PRELOAD=$(ruby -e 'require "ruzzy"; print Ruzzy::ASAN_PATH') \
        ruby -e 'require "ruzzy"; Ruzzy.dummy'
    

    LD_PRELOAD требуется по тем же причинам, что и в Atheris. Однако, в отличие от ASAN_OPTIONS, вероятно, не стоит export'ить его, так как он может мешать другим программам.

    Он должен быстро привести к падению, как показано ниже:

    root@kitploit:~
    INFO: Running with entropic power schedule (0xFF, 100).
    INFO: Seed: 2527961537
    ...
    ==45==ERROR: AddressSanitizer: heap-use-after-free on address 0x50c0009bab80 at pc 0xffff99ea1b44 bp 0xffffce8a67d0 sp 0xffffce8a67c8
    ...
    SUMMARY: AddressSanitizer: heap-use-after-free /var/lib/gems/3.1.0/gems/ruzzy-0.8.0/ext/dummy/dummy.c:18:24 in _c_dummy_test_one_input
    ...
    ==45==ABORTING
    MS: 4 EraseBytes-CopyPart-CopyPart-ChangeBit-; base unit: 410e5346bca8ee150ffd507311dd85789f2e171e
    0x48,0x49,
    HI
    artifact_prefix='./'; Test unit written to ./crash-253420c1158bc6382093d409ce2e9cff5806e980
    Base64: SEk=
    

    Мы видим, что он корректно нашёл входные данные ("HI"), вызвавшие нарушение памяти. Дополнительную информацию о том, почему произошло это нарушение, см. в dummy.c.

    Вы можете повторно запустить аварийный случай следующей командой:

    root@kitploit:~
    LD_PRELOAD=$(ruby -e 'require "ruzzy"; print Ruzzy::ASAN_PATH') \
        ruby -e 'require "ruzzy"; Ruzzy.dummy' \
        ./crash-253420c1158bc6382093d409ce2e9cff5806e980
    

    Доступны следующие санитайзеры:

    • Ruzzy::ASAN_PATH для AddressSanitizer
    • Ruzzy::UBSAN_PATH для UndefinedBehaviorSanitizer

    Фаззинг чистого Ruby-кода

    Давайте в качестве примера отфаззим небольшой Ruby-скрипт. Фаззинг чистого Ruby-кода требует двух Ruby-скриптов: скрипт-трассировщик и фаззинг-обвязку (fuzzing harness). Скрипт-трассировщик необходим из-за особенности реализации интерпретатора Ruby.

    Сначала скрипт-трассировщик, назовём его test_tracer.rb:

    root@kitploit:~
    # frozen_string_literal: true
    
    require 'ruzzy'
    
    Ruzzy.trace('test_harness.rb')
    

    Затем фаззинг-обвязка, назовём её test_harness.rb:

    root@kitploit:~
    # frozen_string_literal: true
    
    require 'ruzzy'
    
    def fuzzing_target(input)
      if input.length == 4
        if input[0] == 'F'
          if input[1] == 'U'
            if input[2] == 'Z'
              if input[3] == 'Z'
                raise
              end
            end
          end
        end
      end
    end
    
    test_one_input = lambda do |data|
      fuzzing_target(data) # Your fuzzing target would go here
      return 0
    end
    
    Ruzzy.fuzz(test_one_input)
    

    Вы можете запустить этот файл и начать фаззинг следующей командой:

    root@kitploit:~
    LD_PRELOAD=$(ruby -e 'require "ruzzy"; print Ruzzy::ASAN_PATH') \
        ruby test_tracer.rb
    

    Он должен быстро привести к падению, как показано ниже:

    root@kitploit:~
    INFO: Running with entropic power schedule (0xFF, 100).
    INFO: Seed: 2311041000
    ...
    /app/ruzzy/bin/test_harness.rb:12:in `block in <top (required)>': unhandled exception
    	from /var/lib/gems/3.1.0/gems/ruzzy-0.8.0/lib/ruzzy.rb:15:in `c_fuzz'
    	from /var/lib/gems/3.1.0/gems/ruzzy-0.8.0/lib/ruzzy.rb:15:in `fuzz'
    	from /app/ruzzy/bin/test_harness.rb:35:in `<top (required)>'
    	from bin/test_tracer.rb:7:in `require_relative'
    	from bin/test_tracer.rb:7:in `<main>'
    ...
    SUMMARY: libFuzzer: fuzz target exited
    MS: 1 CopyPart-; base unit: 24b4b428cf94c21616893d6f94b30398a49d27cc
    0x46,0x55,0x5a,0x5a,
    FUZZ
    artifact_prefix='./'; Test unit written to ./crash-aea2e3923af219a8956f626558ef32f30a914ebc
    Base64: RlVaWg==
    

    Мы видим, что он корректно нашёл входные данные ("FUZZ"), вызвавшие исключение.

    Чтобы фаззить собственную цель, измените test_one_input lambda так, чтобы она вызывала вашу функцию.

    Фаззинг C-расширений Ruby

    Давайте в качестве примера отфаззим библиотеку msgpack-ruby. Сначала установите gem:

    root@kitploit:~
    MAKE="make --environment-overrides V=1" \
    CC="/path/to/clang" \
    CXX="/path/to/clang++" \
    LDSHARED="/path/to/clang -shared" \
    LDSHAREDXX="/path/to/clang++ -shared" \
    CFLAGS="-fsanitize=address,fuzzer-no-link -fno-omit-frame-pointer -fno-common -fPIC -g" \
    CXXFLAGS="-fsanitize=address,fuzzer-no-link -fno-omit-frame-pointer -fno-common -fPIC -g" \
        gem install msgpack
    

    В дополнение к переменным окружения, использованным при компиляции Ruzzy, мы задаём CFLAGS и CXXFLAGS. Эти флаги помогают в процессе фаззинга: они включают полезные функции, такие как AddressSanitizer, и улучшают информацию в стек-трейсах. Подробнее см. AddressSanitizerFlags.

    Далее нам нужна фаззинг-обвязка для msgpack. Следующий код может быть знаком тем, у кого есть опыт работы с libFuzzer:

    root@kitploit:~
    # frozen_string_literal: true
    
    require 'msgpack'
    require 'ruzzy'
    
    test_one_input = lambda do |data|
      begin
        MessagePack.unpack(data)
      rescue Exception
        # We're looking for memory corruption, not Ruby exceptions
      end
      return 0
    end
    
    Ruzzy.fuzz(test_one_input)
    

    Назовём этот файл fuzz_msgpack.rb. Вы можете запустить его и начать фаззинг следующей командой:

    root@kitploit:~
    LD_PRELOAD=$(ruby -e 'require "ruzzy"; print Ruzzy::ASAN_PATH') \
        ruby fuzz_msgpack.rb
    

    Опции libFuzzer можно передавать Ruby-скрипту следующим образом:

    root@kitploit:~
    LD_PRELOAD=$(ruby -e 'require "ruzzy"; print Ruzzy::ASAN_PATH') \
        ruby fuzz_msgpack.rb /path/to/corpus
    

    Подробнее см. опции libFuzzer.

    Чтобы фаззить собственную цель, измените test_one_input lambda так, чтобы она вызывала вашу функцию.

    API

    Ruzzy

    Модуль Ruzzy предоставляет точки входа верхнего уровня.

    МетодОписание
    Ruzzy.fuzz(test_one_input, args = DEFAULT_ARGS)Фаззит test_one_input (proc/lambda, принимающий сырые байты).
    Ruzzy.trace(harness_script)Оборачивает harness_script инструментированием покрытия ветвей Ruby, затем подключает его через require. Требуется для фаззинга чистого Ruby.
    Ruzzy.dummyФаззит встроенную игрушечную обвязку (демо heap-use-after-free).
    Ruzzy.dummy_test_one_input(data)Сама игрушечная обвязка.
    КонстантаОписание
    Ruzzy::ASAN_PATHПуть к обёртке ASan + фаззера. Используйте с LD_PRELOAD (Linux) / DYLD_INSERT_LIBRARIES (macOS).
    Ruzzy::UBSAN_PATHАналогично, для UBSan.
    Ruzzy::EXT_PATHПуть к каталогу сборки ext/cruzzy.
    Ruzzy::DEFAULT_ARGSАргументы по умолчанию, передаваемые фаззеру.

    FuzzedDataProvider

    Ruzzy::FuzzedDataProvider разделяет сырые байты фаззера на типизированные значения Ruby.

    root@kitploit:~
    test_one_input = lambda do |data|
      fdp = Ruzzy::FuzzedDataProvider.new(data)
      name = fdp.consume_random_length_string(50)
      age = fdp.consume_int_in_range(0, 150)
      score = fdp.consume_float_in_range(0.0, 100.0)
      role = fdp.pick_value_in_list(['admin', 'user', 'guest'])
      User.new(name: name, age: age, score: score, role: role).validate!
    end
    
    Ruzzy.fuzz(test_one_input)
    
    МетодОписаниеВозвращаемое значение
    remaining_bytesКоличество ещё не потреблённых байтовInteger
    consume_bytes(count)Потребляет до count сырых байтовбинарная String
    consume_random_length_string(max_length)Потребляет строку переменной длины; завершается на \ + не-\ байтеString
    consume_remaining_bytesПотребляет все оставшиеся байтыбинарная String
    consume_remaining_as_stringПсевдоним для consume_remaining_bytesбинарная String
    consume_uint(count)Беззнаковое целое из count байтовInteger
    consume_int(count)Знаковое целое (в дополнительном коде) из count байтовInteger
    consume_int_in_range(min, max)Целое, равномерно распределённое в диапазоне [min, max]Integer
    consume_boolЛогическое значение из одного байта (младший бит)true/false
    consume_floatЧисло с плавающей запятой, покрывающее весь диапазон doubleFloat
    consume_float_in_range(min, max)Число с плавающей запятой в диапазоне [min, max]Float
    consume_probabilityЧисло с плавающей запятой в диапазоне [0.0, 1.0]Float
    pick_value_in_list(list)

    Когда данные исчерпаны, все методы возвращают значения по умолчанию (0, "", false, min).

    Примечания для пользователей macOS

    Ruzzy на macOS требует LLVM, установленный через Homebrew (Apple Clang не включает libFuzzer), и несистемный Ruby (системный Ruby в /usr/bin/ruby защищён SIP, из-за чего переменные окружения DYLD_* удаляются до запуска Ruby).

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

    root@kitploit:~
    brew install llvm ruby
    

    Подойдёт любой несистемный Ruby (brew, rbenv, asdf), но для менеджеров версий на основе шим см. предостережения ниже.

    Установка

    Используйте пути к Clang из Homebrew и подходящие для macOS флаги компоновщика:

    root@kitploit:~
    MAKE="make --environment-overrides V=1" \
    CC="$(brew --prefix llvm)/bin/clang" \
    CXX="$(brew --prefix llvm)/bin/clang++" \
    LDSHARED="$(brew --prefix llvm)/bin/clang -dynamic -bundle -undefined dynamic_lookup" \
    LDSHAREDXX="$(brew --prefix llvm)/bin/clang++ -dynamic -bundle -undefined dynamic_lookup" \
        gem install ruzzy
    

    Запуск

    Используйте DYLD_INSERT_LIBRARIES вместо LD_PRELOAD:

    root@kitploit:~
    DYLD_INSERT_LIBRARIES=$(ruby -e 'require "ruzzy"; print Ruzzy::ASAN_PATH') \
        ruby -e 'require "ruzzy"; Ruzzy.dummy'
    

    Ruzzy::ASAN_PATH и Ruzzy::UBSAN_PATH на macOS указывают на файлы .dylib.

    Предостережения

    • Шимы менеджеров версий (asdf, rbenv) удаляют переменные окружения DYLD_*. Эти шимы используют #!/usr/bin/env bash, а /usr/bin/env защищён SIP, поэтому macOS удаляет DYLD_INSERT_LIBRARIES до запуска Ruby. Либо используйте Homebrew Ruby (у которого нет шима), либо вызывайте абсолютный путь к установленному бинарнику Ruby:
      root@kitploit:~
      DYLD_INSERT_LIBRARIES=$(/path/to/ruby -e 'require "ruzzy"; print Ruzzy::ASAN_PATH') \
          /path/to/ruby your_fuzzer.rb
      
    • Нужен свежий LLVM. В некоторых старых версиях Homebrew LLVM (особенно 19.x) есть баг: при использовании DYLD_INSERT_LIBRARIES с dylib ASan процесс зависает во время запуска. Если Ruzzy зависает при старте, обновите Homebrew LLVM (brew upgrade llvm).

    Найденные ошибки

    Ошибки, найденные с помощью Ruzzy:

    • gem toml: #76
    • gem toml-rb: #150
    • gem ox: #351, #410
    • Сбой сборщика мусора в Ruby Marshal: #20941
    • Расхождение XML-парсеров: REXML vs. Nokogiri
    • gem redcarpet: #813

    Разработка

    Разработку можно вести локально или с помощью Dockerfile, предоставленного в этом репозитории.

    Вы можете собрать Docker-образ Ruzzy следующей командой:

    root@kitploit:~
    docker build --tag ruzzy .
    

    Затем вы можете войти в контейнер с помощью следующей команды:

    root@kitploit:~
    docker run -it -v $(pwd):/app/ruzzy --entrypoint /bin/bash ruzzy
    

    Компиляция

    Для компиляции C-расширений Ruzzy мы используем rake-compiler.

    Вы можете скомпилировать C-расширения внутри контейнера следующей командой:

    root@kitploit:~
    rake compile
    

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

    Для тестирования Ruby-кода мы используем модульные тесты rake.

    Вы можете запустить тесты внутри контейнера следующей командой:

    root@kitploit:~
    LD_PRELOAD=$(ruby -e 'require "ruzzy"; print Ruzzy::ASAN_PATH') \
        rake test
    

    Линтинг

    Для линтинга Ruby-кода мы используем rubocop.

    Вы можете запустить rubocop внутри контейнера следующей командой:

    root@kitploit:~
    rubocop
    

    Релиз

    Ruzzy автоматически публикуется на RubyGems при пуше нового git-тега.

    Чтобы выпустить новую версию, выполните следующие команды:

    root@kitploit:~
    git tag vX.X.X
    
    root@kitploit:~
    git push --tags
    

    Дополнительные материалы

    • C-расширения Ruby
      • https://guides.rubygems.org/gems-with-extensions/
      • https://www.rubyguides.com/2018/03/write-ruby-c-extension/
      • https://rubyreferences.github.io/rubyref/advanced/extensions.html
      • https://silverhammermba.github.io/emberb/c/
      • https://ruby-doc.org/3.3.0/extension_rdoc.html
      • https://ruby-doc.org/3.3.0/stdlibs/mkmf/MakeMakefile.html
      • https://github.com/flavorjones/ruby-c-extensions-explained
      • https://github.com/ruby/ruby/blob/v3_3_0/lib/mkmf.rb
    • Фаззинг Ruby
      • https://github.com/twistlock/kisaten
      • https://github.com/richo/afl-ruby
      • https://github.com/krypt/FuzzBert
      • https://z2-2z.github.io/2024/jan/16/fuzzing-ruby-c-extensions-with-coverage-and-asan.html
      • https://bsidessf2018.sched.com/event/E6jC/fuzzing-ruby-and-c-extensions
    • Atheris
      • https://github.com/google/atheris/blob/master/native_extension_fuzzing.md
      • https://security.googleblog.com/2020/12/how-atheris-python-fuzzer-works.html
      • https://github.com/google/atheris/blob/2.3.0/setup.py
      • https://github.com/google/atheris/blob/2.3.0/src/native/core.cc
      • https://github.com/google/atheris/blob/2.3.0/src/native/tracer.cc
      • https://github.com/google/atheris/blob/2.3.0/src/native/counters.cc
      • https://github.com/google/atheris/blob/2.3.0/src/instrument_bytecode.py
    • Покрытие кода
      • https://calabi-yau.space/blog/sanitizer-coverage-interface.html
      • https://carstein.github.io/2020/05/21/writing-simple-fuzzer-4.html
      • https://h0mbre.github.io/Fuzzing-Like-A-Caveman-5/
      • https://github.com/mirrorer/afl/blob/master/docs/technical_details.txt
      • https://lcamtuf.coredump.cx/afl/historical_notes.txt
      • https://www.code-intelligence.com/blog/the-magic-behind-feedback-based-fuzzing
      • https://blog.includesecurity.com/2024/04/coverage-guided-fuzzing-extending-instrumentation/
      • https://git.sr.ht/~myrrc/ba-thesis/blob/master/thesis.pdf
      • https://www.politesi.polimi.it/bitstream/10589/173614/3/2021_04_Frighetto.pdf
      • https://wcventure.github.io/FuzzingPaper/Paper/SP18_ColLAFL.pdf
      • https://www.ndss-symposium.org/wp-content/uploads/2020/02/24422.pdf
      • https://mboehme.github.io/paper/ICSE22.pdf
      • https://www.usenix.org/system/files/raid2019-wang-jinghan.pdf
    Скачать инструмент
    Случайный элемент из list
    элемент