Skip to content
KitploitKITPLOIT
StrumentiBlog
Invia
StrumentiBlog
Invia

Strumenti di Hacking, PenTest e Cybersecurity per il tuo Arsenale di Sicurezza!

Kitploit è una directory di strumenti di hacking, cybersecurity e pentesting. Scopri gli ultimi aggiornamenti dei progetti per trovare vulnerabilità, analizzare sistemi, automatizzare i test e rafforzare la tua sicurezza.

··Feed·Contatto·Privacy·© 2026 Kitploit

Directory degli strumenti

Categorie

Vedi tutte le categorie
Loading categories
ruzzy — Un fuzzer guidato dalla copertura per codice Ruby puro ed estensioni C di Ruby. | Kitploit
Strumenti/GitHubGitHub/trailofbits/ruzzy
Analisi Dinamica (Sandboxing)Analisi delle VulnerabilitàAnalisi del CodiceFuzzingAnalisi di BinariApprendimento e Formazione
GitHubtrailofbits/ruzzy

ruzzy

Un fuzzer guidato dalla copertura per codice Ruby puro ed estensioni C di Ruby.

Vedi Repository
123742 mesi faRevisionato da Kitploit

Più Popolari

Vedi tutti →

Scopri gli strumenti più utilizzati dalla nostra community.

Esplora tutti gli strumenti

Sfoglia la nostra collezione di strumenti

Vedi tutti gli strumenti →
Condividi

Ruzzy

Test Gem Version

Un fuzzer guidato dalla copertura per codice Ruby puro ed estensioni C di Ruby.

Ruzzy è fortemente ispirato ad Atheris di Google, un fuzzer per Python. Ruzzy usa libFuzzer (o LibAFL) per la strumentazione della copertura e il motore di fuzzing. Ruzzy supporta anche AddressSanitizer e UndefinedBehaviorSanitizer quando si esegue il fuzzing di estensioni C. Se vuoi saperne di più sull'ispirazione alla base di Ruzzy, consulta il nostro articolo: Design and Implementation of a Coverage-Guided Ruby Fuzzer.

Indice dei contenuti:

  • Installazione
  • Utilizzo
    • Per iniziare
    • Fuzzing di codice Ruby puro
    • Fuzzing di estensioni C di Ruby
  • API
    • Ruzzy
    • FuzzedDataProvider
  • Note per gli utenti macOS
  • Bacheca dei trofei
  • Sviluppo
Scarica lo strumento
  • Compilazione
  • Test
  • Linting
  • Rilascio
  • Ulteriori letture
  • Installazione

    Ruzzy supporta Linux (x86-64, AArch64/ARM64) e macOS (Apple Silicon). Su Windows, puoi creare il Dockerfile e/o usare l'ambiente di sviluppo. Ruzzy richiede una versione recente di clang (testata fino alla 14.0.0), preferibilmente l'ultima release. Per la configurazione specifica di macOS, vedi note per gli utenti macOS.

    Installa Ruzzy con il seguente comando:

    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
    

    C'è molto da spiegare qui, quindi analizziamolo:

    • La variabile d'ambiente MAKE sovrascrive il comando make durante la compilazione dell'estensione C di Ruzzy. Questo dice a make di rispettare le successive variabili d'ambiente durante la compilazione dell'estensione.
    • Il resto delle variabili d'ambiente viene usato durante la compilazione per garantire l'uso dei binari clang corretti. Questo assicura di avere le funzionalità più recenti di clang, necessarie per un corretto fuzzing.

    Se riscontri problemi durante l'installazione, puoi eseguire il seguente comando per ottenere un output di debug:

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

    Se il tuo target di fuzzing in Ruby puro fa un uso intensivo delle regexp, installa regexp_parser:

    root@kitploit:~
    gem install regexp_parser
    

    Una volta installato, Ruzzy userà automaticamente questa funzionalità per campionare (cioè risolvere) le regexp che incontra durante il fuzzing. Questo permette al fuzzer di superare le condizioni basate su regexp e sbloccare ulteriore copertura.

    Utilizzo

    Per iniziare

    Ruzzy include un esempio giocattolo per dimostrare come funziona. Per prima cosa, imposta la seguente variabile d'ambiente:

    root@kitploit:~
    export ASAN_OPTIONS="allocator_may_return_null=1:detect_leaks=0:use_sigaltstack=0"
    
    Capire queste opzioni non è necessario, ma se sei curioso clicca qui.

    ASAN_OPTIONS

    1. I fallimenti di allocazione della memoria sono comuni e a basso impatto (DoS), quindi saltali per ora.
    2. Come Python, l'interprete Ruby disperde dati, quindi ignora questi per ora.
    3. Ruby raccomanda di disabilitare sigaltstack.

    Puoi quindi eseguire l'esempio con il seguente comando:

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

    LD_PRELOAD è richiesto per gli stessi motivi di Atheris. Tuttavia, a differenza di ASAN_OPTIONS, probabilmente non vorrai esportarlo con export poiché potrebbe interferire con altri programmi.

    Dovrebbe produrre rapidamente un crash come il seguente:

    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=
    

    Possiamo vedere che ha trovato correttamente l'input ("HI") che ha prodotto una violazione di memoria. Per maggiori informazioni, vedi dummy.c per capire perché si è verificata questa violazione.

    Puoi rieseguire il caso di crash con il seguente comando:

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

    I seguenti sanitizer sono disponibili:

    • Ruzzy::ASAN_PATH per AddressSanitizer
    • Ruzzy::UBSAN_PATH per UndefinedBehaviorSanitizer

    Fuzzing di codice Ruby puro

    Facciamo il fuzzing di un piccolo script Ruby come esempio. Il fuzzing di codice Ruby puro richiede due script Ruby: uno script tracer e un harness di fuzzing. Lo script tracer è necessario a causa di un dettaglio implementativo dell'interprete Ruby.

    Prima, lo script tracer, chiamiamolo test_tracer.rb:

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

    Poi, l'harness di fuzzing, chiamiamolo 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)
    

    Puoi eseguire questo file e iniziare il fuzzing con il seguente comando:

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

    Dovrebbe produrre rapidamente un crash come il seguente:

    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==
    

    Possiamo vedere che ha trovato correttamente l'input ("FUZZ") che ha prodotto un'eccezione.

    Per fare il fuzzing del tuo target, modifica la lambda test_one_input per chiamare la tua funzione target.

    Fuzzing di estensioni C di Ruby

    Facciamo il fuzzing della libreria msgpack-ruby come esempio. Per prima cosa, installa la gemma:

    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
    

    Oltre alle variabili d'ambiente usate per compilare Ruzzy, specifichiamo CFLAGS e CXXFLAGS. Questi flag aiutano nel processo di fuzzing. Abilitano funzionalità utili come l'address sanitizer e migliori informazioni sullo stack trace. Per maggiori informazioni vedi AddressSanitizerFlags.

    Successivamente, abbiamo bisogno di un harness di fuzzing per msgpack. Quanto segue potrebbe essere familiare a chi ha esperienza con 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)
    

    Chiamiamo questo file fuzz_msgpack.rb. Puoi eseguire questo file e iniziare il fuzzing con il seguente comando:

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

    Le opzioni di libFuzzer possono essere passate allo script Ruby in questo modo:

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

    Vedi opzioni di libFuzzer per maggiori informazioni.

    Per fare il fuzzing del tuo target, modifica la lambda test_one_input per chiamare la tua funzione target.

    API

    Ruzzy

    Il modulo Ruzzy espone i punti di ingresso di livello superiore.

    MetodoDescrizione
    Ruzzy.fuzz(test_one_input, args = DEFAULT_ARGS)Esegue il fuzzing di test_one_input (una proc/lambda che accetta byte grezzi).
    Ruzzy.trace(harness_script)Avvolge harness_script con la strumentazione di copertura dei rami di Ruby, quindi lo carica con require. Necessario per il fuzzing di puro Ruby.
    Ruzzy.dummyEsegue il fuzzing dell'harness giocattolo incluso (demo di heap-use-after-free).
    Ruzzy.dummy_test_one_input(data)L'harness giocattolo stesso.
    CostanteDescrizione
    Ruzzy::ASAN_PATHPercorso del wrapper ASan + fuzzer. Da usare con LD_PRELOAD (Linux) / DYLD_INSERT_LIBRARIES (macOS).
    Ruzzy::UBSAN_PATHIdem, per UBSan.
    Ruzzy::EXT_PATHPercorso della directory di build di ext/cruzzy.
    Ruzzy::DEFAULT_ARGSArgomenti predefiniti passati al fuzzer.

    FuzzedDataProvider

    Ruzzy::FuzzedDataProvider divide i byte grezzi del fuzzer in valori Ruby tipizzati.

    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)
    
    MetodoDescrizioneRestituisce
    remaining_bytesNumero di byte non consumati rimanentiInteger
    consume_bytes(count)Consuma fino a count byte grezziString binaria
    consume_random_length_string(max_length)Consuma una stringa a lunghezza variabile; termina su \ + byte diverso da \String
    consume_remaining_bytesConsuma tutti i byte rimanentiString binaria
    consume_remaining_as_stringAlias di consume_remaining_bytesString binaria
    consume_uint(count)Intero senza segno da count byteInteger
    consume_int(count)Intero con segno (complemento a due) da count byteInteger
    consume_int_in_range(min, max)Intero distribuito uniformemente in [min, max]Integer
    consume_boolBooleano da un byte (LSB)true/false
    consume_floatFloat che copre l'intero intervallo del doubleFloat
    consume_float_in_range(min, max)Float in [min, max]Float
    consume_probabilityFloat in [0.0, 1.0]Float
    pick_value_in_list(list)Elemento casuale da listelemento

    Tutti i metodi restituiscono valori predefiniti (0, "", false, min) quando i dati sono esauriti.

    Note per gli utenti macOS

    Ruzzy su macOS richiede LLVM installato tramite Homebrew (Apple Clang non include libFuzzer) e un Ruby non di sistema (il Ruby di sistema in /usr/bin/ruby è protetto da SIP, che rimuove le variabili d'ambiente DYLD_* prima che Ruby venga avviato).

    Prerequisiti

    root@kitploit:~
    brew install llvm ruby
    

    Qualsiasi Ruby non di sistema funziona (brew, rbenv, asdf), ma vedi le avvertenze qui sotto per i gestori di versioni basati su shim.

    Installazione

    Usa i percorsi di Clang di Homebrew e i flag di linker appropriati per 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
    

    Esecuzione

    Usa DYLD_INSERT_LIBRARIES invece di LD_PRELOAD:

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

    Ruzzy::ASAN_PATH e Ruzzy::UBSAN_PATH puntano a file .dylib su macOS.

    Avvertenze

    • Gli shim dei gestori di versioni (asdf, rbenv) rimuovono le variabili d'ambiente DYLD_*. Questi shim usano #!/usr/bin/env bash e /usr/bin/env è protetto da SIP, quindi macOS rimuove DYLD_INSERT_LIBRARIES prima che Ruby venga avviato. Usa Ruby di Homebrew (che non ha shim) oppure invoca il percorso assoluto del binario Ruby installato:
      root@kitploit:~
      DYLD_INSERT_LIBRARIES=$(/path/to/ruby -e 'require "ruzzy"; print Ruzzy::ASAN_PATH') \
          /path/to/ruby your_fuzzer.rb
      
    • È richiesto un LLVM recente. Alcune versioni meno recenti di LLVM di Homebrew (in particolare 19.x) hanno un bug per cui l'iniezione tramite DYLD_INSERT_LIBRARIES della dylib ASan blocca il processo durante l'avvio. Se Ruzzy si blocca all'avvio, aggiorna LLVM di Homebrew (brew upgrade llvm).

    Bacheca dei trofei

    Bug trovati usando Ruzzy:

    • gemma toml: #76
    • gemma toml-rb: #150
    • gemma ox: #351, #410
    • Crash del garbage collector di Ruby Marshal: #20941
    • Differenziale del parser XML: REXML vs. Nokogiri
    • gemma redcarpet: #813

    Sviluppo

    Lo sviluppo può essere fatto localmente, oppure usando il Dockerfile fornito in questo repository.

    Puoi creare l'immagine Docker di Ruzzy con il seguente comando:

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

    Poi, puoi entrare nella shell del container usando il seguente comando:

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

    Compilazione

    Usiamo rake-compiler per compilare le estensioni C di Ruzzy.

    Puoi compilare le estensioni C all'interno del container con il seguente comando:

    root@kitploit:~
    rake compile
    

    Test

    Usiamo i test unitari rake per testare il codice Ruby.

    Puoi eseguire i test all'interno del container con il seguente comando:

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

    Linting

    Usiamo rubocop per il linting del codice Ruby.

    Puoi eseguire rubocop all'interno del container con il seguente comando:

    root@kitploit:~
    rubocop
    

    Rilascio

    Ruzzy viene rilasciato automaticamente su RubyGems quando viene pushato un nuovo tag git.

    Per rilasciare una nuova versione esegui i seguenti comandi:

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

    Ulteriori letture

    • Estensioni C di 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
    • Fuzzing di 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
    • Copertura
      • 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