Skip to content
KitploitKITPLOIT
HerramientasExploitsBlog
Log in
Enviar
HerramientasExploitsBlog
Enviar

¡Herramientas de Hacking, PenTest y Ciberseguridad para tu Arsenal de Seguridad!

Kitploit es un directorio de herramientas de hacking, ciberseguridad y pentesting. Descubre las últimas actualizaciones de proyectos para encontrar vulnerabilidades, analizar sistemas, automatizar pruebas y fortalecer tu seguridad.

··Feeds·Contacto·Privacidad·© 2026 Kitploit

Directorio de Herramientas

Categorías

Ver todas las categorías
Loading categories
ruzzy — Un fuzzer guiado por cobertura para código Ruby puro y extensiones C de Ruby | Kitploit
Herramientas/GitHubGitHub/trailofbits/ruzzy
Análisis Dinámico (Sandboxing)Análisis de VulnerabilidadesAnálisis de CódigoFuzzingAnálisis de BinariosAprendizaje y Educación
GitHubtrailofbits/ruzzy

ruzzy

Un fuzzer guiado por cobertura para código Ruby puro y extensiones C de Ruby

Ver Repositorio
123712hace 3 mesesRevisado por Kitploit

Más Populares

Ver todos →

Descubre las herramientas más usadas por nuestra comunidad.

Explora todas las herramientas

Explora nuestra colección de herramientas

Ver todas las herramientas →
Compartir
# Ruzzy

[![Test](https://github.com/trailofbits/ruzzy/actions/workflows/test.yml/badge.svg)](https://github.com/trailofbits/ruzzy/actions/workflows/test.yml)
[![Gem Version](https://img.shields.io/gem/v/ruzzy)](https://rubygems.org/gems/ruzzy)

Un fuzzer guiado por cobertura para código Ruby puro y [extensiones C](https://ruby-doc.org/3.3.0/extension_rdoc.html) de Ruby.

Ruzzy está fuertemente inspirado en [Atheris](https://github.com/google/atheris), un fuzzer de Python. Ruzzy utiliza [libFuzzer](https://llvm.org/docs/LibFuzzer.html) (o [LibAFL](https://github.com/trailofbits/ruzzy/blob/main/Dockerfile.LibAFL)) para su instrumentación de cobertura y su motor de fuzzing. Ruzzy también es compatible con [AddressSanitizer](https://clang.llvm.org/docs/AddressSanitizer.html) y [UndefinedBehaviorSanitizer](https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html) al fuzzear extensiones C. Si desea obtener más información sobre la inspiración detrás de Ruzzy, consulte nuestro artículo: [Design and Implementation of a Coverage-Guided Ruby Fuzzer](https://dl.acm.org/doi/10.1145/3675741.3675749).

Tabla de contenidos:

- [Instalación](#installing)
- [Uso](#using)
  - [Primeros pasos](#getting-started)
  - [Fuzzing de código Ruby puro](#fuzzing-pure-ruby-code)
  - [Fuzzing de extensiones C de Ruby](#fuzzing-ruby-c-extensions)
- [API](#api)
  - [Ruzzy](#ruzzy)
  - [FuzzedDataProvider](#fuzzeddataprovider)
- [Notas para usuarios de macOS](#notes-for-macos-users)
- [Casos de éxito](#trophy-case)
- [Desarrollo](#developing)
  - [Compilación](#compiling)
  - [Pruebas](#testing)
  - [Linting](#linting)
  - [Publicación](#releasing)
- [Lecturas adicionales](#further-reading)

# Instalación

Ruzzy es compatible con Linux (x86-64, AArch64/ARM64) y macOS (Apple Silicon). En Windows, puede compilar el [`Dockerfile`](https://github.com/trailofbits/ruzzy/blob/main/Dockerfile) y/o utilizar el [entorno de desarrollo](#developing). Ruzzy requiere una versión reciente de `clang` (probada hasta `14.0.0`), preferiblemente la [última versión](https://github.com/llvm/llvm-project/releases). Para la configuración específica de macOS, consulte las [notas para usuarios de macOS](#notes-for-macos-users).

Instale Ruzzy con el siguiente comando:

```bash
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
```

Hay mucho en juego aquí, así que vamos a desglosarlo:

- La variable de entorno `MAKE` sobrescribe el comando `make` al compilar la extensión C de Ruzzy. Esto le indica a `make` que respete las variables de entorno posteriores al compilar la extensión.
- El resto de las variables de entorno se utilizan durante la compilación para asegurarnos de que estamos usando los binarios `clang` adecuados. Esto garantiza que tengamos las funciones más recientes de `clang`, necesarias para un fuzzing adecuado.

Si tiene problemas con la instalación, puede ejecutar el siguiente comando para obtener información de depuración:

```bash
RUZZY_DEBUG=1 gem install --verbose ruzzy
```

Si su objetivo de fuzzing en Ruby puro hace un uso intensivo de regexps, instale [`regexp_parser`](https://github.com/ammar/regexp_parser):

```
gem install regexp_parser
```

Una vez instalado, Ruzzy utilizará automáticamente esta funcionalidad para muestrear (es decir, resolver) las regexps que encuentre durante el fuzzing. Esto permite que el fuzzer avance más allá de las condiciones de regexp y desbloquee cobertura adicional.

# Uso

## Primeros pasos

Ruzzy incluye un [ejemplo de juguete](https://llvm.org/docs/LibFuzzer.html#toy-example) para demostrar cómo funciona. Primero, configure la siguiente variable de entorno:

```bash
export ASAN_OPTIONS="allocator_may_return_null=1:detect_leaks=0:use_sigaltstack=0"
```

<details>
<summary>Comprender estas opciones no es necesario, pero si tiene curiosidad, haga clic aquí.</summary>

### `ASAN_OPTIONS`

1. Los fallos de asignación de memoria son comunes y de bajo impacto (DoS), así que omitámoslos por ahora.
1. Al igual que Python, el intérprete de Ruby [pierde memoria](https://github.com/google/atheris/blob/master/native_extension_fuzzing.md#leak-detection), así que ignóralos por ahora.
1. Ruby recomienda [deshabilitar sigaltstack](https://github.com/ruby/ruby/blob/master/doc/contributing/building_ruby.md#building-with-address-sanitizer).

</details>

Puede ejecutar el ejemplo con el siguiente comando:

```bash
LD_PRELOAD=$(ruby -e 'require "ruzzy"; print Ruzzy::ASAN_PATH') \
    ruby -e 'require "ruzzy"; Ruzzy.dummy'
```

_`LD_PRELOAD` es necesario por las mismas razones [que en Atheris](https://github.com/google/atheris/blob/master/native_extension_fuzzing.md#option-a-sanitizerlibfuzzer-preloads). Sin embargo, a diferencia de `ASAN_OPTIONS`, probablemente no quiera `exportarlo`, ya que puede interferir con otros programas._

Debería producir rápidamente un fallo como el siguiente:

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

Podemos ver que encontró correctamente la entrada (`"HI"`) que produjo una violación de memoria. Para más información, consulte [`dummy.c`](https://github.com/trailofbits/ruzzy/blob/main/ext/dummy/dummy.c) para ver por qué ocurrió esta violación.

Puede volver a ejecutar el caso de fallo con el siguiente comando:

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

Los siguientes sanitizadores están disponibles:

- `Ruzzy::ASAN_PATH` para [AddressSanitizer](https://clang.llvm.org/docs/AddressSanitizer.html)
- `Ruzzy::UBSAN_PATH` para [UndefinedBehaviorSanitizer](https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html)

## Fuzzing de código Ruby puro

Fuzzeemos un pequeño script de Ruby como ejemplo. El fuzzing de código Ruby puro requiere dos scripts de Ruby: un script de trazado (tracer) y un harness de fuzzing. El script de trazado es necesario debido a un detalle de implementación del intérprete de Ruby.

Primero, el script de trazado, llamémoslo `test_tracer.rb`:

```ruby
# frozen_string_literal: true

require 'ruzzy'

Ruzzy.trace('test_harness.rb')
```

A continuación, el harness de fuzzing, llamémoslo `test_harness.rb`:

```ruby
# 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)
```

Puede ejecutar este archivo y comenzar a fuzzear con el siguiente comando:

```bash
LD_PRELOAD=$(ruby -e 'require "ruzzy"; print Ruzzy::ASAN_PATH') \
    ruby test_tracer.rb
```

Debería producir rápidamente un fallo como el siguiente:

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

Podemos ver que encontró correctamente la entrada (`"FUZZ"`) que produjo una excepción.

Para fuzzear su propio objetivo, modifique el `lambda` `test_one_input` para que llame a su función objetivo.

## Fuzzing de extensiones C de Ruby

Fuzzeemos la biblioteca [`msgpack-ruby`](https://github.com/msgpack/msgpack-ruby) como ejemplo. Primero, instale la gema:

```bash
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
```

Además de las variables de entorno utilizadas al compilar Ruzzy, estamos especificando `CFLAGS` y `CXXFLAGS`. Estas banderas ayudan en el proceso de fuzzing. Habilitan funcionalidades útiles como un address sanitizer y una mejor información de stack trace. Para más información, consulte [AddressSanitizerFlags](https://github.com/google/sanitizers/wiki/AddressSanitizerFlags).

A continuación, necesitamos un harness de fuzzing para `msgpack`. Lo siguiente puede resultar familiar para quienes tienen [experiencia con libFuzzer](https://llvm.org/docs/LibFuzzer.html#fuzz-target):

```ruby
# 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)
```

Llamemos a este archivo `fuzz_msgpack.rb`. Puede ejecutar este archivo y comenzar a fuzzear con el siguiente comando:

```bash
LD_PRELOAD=$(ruby -e 'require "ruzzy"; print Ruzzy::ASAN_PATH') \
    ruby fuzz_msgpack.rb
```

Las opciones de libFuzzer se pueden pasar al script de Ruby de la siguiente manera:

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

Consulte [opciones de libFuzzer](https://llvm.org/docs/LibFuzzer.html#options) para obtener más información.

Para fuzzear su propio objetivo, modifique el `lambda` `test_one_input` para que llame a su función objetivo.

# API

## Ruzzy

El módulo `Ruzzy` expone los puntos de entrada de nivel superior.

| Método | Descripción |
|--------|-------------|
| `Ruzzy.fuzz(test_one_input, args = DEFAULT_ARGS)` | Fuzzea `test_one_input` (un `proc`/`lambda` que recibe bytes sin procesar). |
| `Ruzzy.trace(harness_script)` | Envuelve `harness_script` con instrumentación de cobertura de ramas de Ruby y luego hace `require` del mismo. Necesario para fuzzing de Ruby puro. |
| `Ruzzy.dummy` | Fuzzea el harness de juguete incluido (demo de heap-use-after-free). |
| `Ruzzy.dummy_test_one_input(data)` | El propio harness de juguete. |

| Constante | Descripción |
|----------|-------------|
| `Ruzzy::ASAN_PATH` | Ruta al wrapper de ASan + fuzzer. Úsela con `LD_PRELOAD` (Linux) / `DYLD_INSERT_LIBRARIES` (macOS). |
| `Ruzzy::UBSAN_PATH` | Igual, para UBSan. |
| `Ruzzy::EXT_PATH` | Ruta al directorio de compilación `ext/cruzzy`. |
| `Ruzzy::DEFAULT_ARGS` | Argumentos predeterminados pasados al fuzzer. |

## FuzzedDataProvider

`Ruzzy::FuzzedDataProvider` [divide](https://github.com/google/fuzzing/blob/master/docs/split-inputs.md) los bytes sin procesar del fuzzer en valores Ruby tipados.

```ruby
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)
```

| Método | Descripción | Retorna |
|--------|-------------|---------|
| `remaining_bytes` | Número de bytes no consumidos restantes | `Integer` |
| `consume_bytes(count)` | Consume hasta `count` bytes sin procesar | `String` binario |
| `consume_random_length_string(max_length)` | Consume una cadena de longitud variable; termina en `\` + byte distinto de `\` | `String` |
| `consume_remaining_bytes` | Consume todos los bytes restantes | `String` binario |
| `consume_remaining_as_string` | Alias de `consume_remaining_bytes` | `String` binario |
| `consume_uint(count)` | Entero sin signo a partir de `count` bytes | `Integer` |
| `consume_int(count)` | Entero con signo (complemento a dos) a partir de `count` bytes | `Integer` |
| `consume_int_in_range(min, max)` | Entero distribuido uniformemente en [`min`, `max`] | `Integer` |
| `consume_bool` | Booleano a partir de un byte (LSB) | `true`/`false` |
| `consume_float` | Flotante que abarca todo el rango de double | `Float` |
| `consume_float_in_range(min, max)` | Flotante en [`min`, `max`] | `Float` |
| `consume_probability` | Flotante en [0.0, 1.0] | `Float` |
| `pick_value_in_list(list)` | Elemento aleatorio de `list` | elemento |

Todos los métodos devuelven valores predeterminados (`0`, `""`, `false`, `min`) cuando los datos se agotan.

# Notas para usuarios de macOS

Ruzzy en macOS requiere LLVM instalado mediante Homebrew (Apple Clang no incluye libFuzzer) y un Ruby que no sea el del sistema (el Ruby del sistema en `/usr/bin/ruby` está protegido por SIP, lo que elimina las variables de entorno `DYLD_*` antes de que Ruby se inicie).

## Requisitos previos

```bash
brew install llvm ruby
```

Cualquier Ruby que no sea el del sistema funciona (`brew`, `rbenv`, `asdf`), pero consulte las [limitaciones](#caveats) a continuación para los gestores de versiones basados en shims.

## Instalación

Utilice las rutas de Clang de Homebrew y las banderas de enlazado apropiadas para macOS:

```bash
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
```

## Ejecución

Use `DYLD_INSERT_LIBRARIES` en lugar de `LD_PRELOAD`:

```bash
DYLD_INSERT_LIBRARIES=$(ruby -e 'require "ruzzy"; print Ruzzy::ASAN_PATH') \
    ruby -e 'require "ruzzy"; Ruzzy.dummy'
```

`Ruzzy::ASAN_PATH` y `Ruzzy::UBSAN_PATH` se resuelven a archivos `.dylib` en macOS.

## Limitaciones

- **Los shims de gestores de versiones (`asdf`, `rbenv`) eliminan las variables de entorno `DYLD_*`.** Estos shims usan `#!/usr/bin/env bash` y `/usr/bin/env` está protegido por SIP, por lo que macOS elimina `DYLD_INSERT_LIBRARIES` antes de que Ruby se inicie. Utilice el Ruby de Homebrew (que no tiene shim) o invoque la ruta absoluta al binario de Ruby instalado:
  ```bash
  DYLD_INSERT_LIBRARIES=$(/path/to/ruby -e 'require "ruzzy"; print Ruzzy::ASAN_PATH') \
      /path/to/ruby your_fuzzer.rb
  ```
- **Se requiere LLVM reciente.** Algunas versiones antiguas de Homebrew LLVM (particularmente 19.x) tienen un error por el cual `DYLD_INSERT_LIBRARIES` con la dylib de ASan bloquea el proceso durante el arranque. Si Ruzzy se bloquea al iniciar, actualice Homebrew LLVM (`brew upgrade llvm`).

# Casos de éxito

Errores encontrados usando Ruzzy:

- gema `toml`: [#76](https://github.com/jm/toml/issues/76)
- gema `toml-rb`: [#150](https://github.com/emancu/toml-rb/issues/150)
- gema `ox`: [#351](https://github.com/ohler55/ox/issues/351), [#410](https://github.com/ohler55/ox/issues/410)
- Fallo del recolector de basura de Ruby `Marshal`: [#20941](https://bugs.ruby-lang.org/issues/20941)
- Diferencial de analizadores XML: [REXML vs. Nokogiri](https://github.blog/security/sign-in-as-anyone-bypassing-saml-sso-authentication-with-parser-differentials/)
- gema `redcarpet`: [#813](https://github.com/vmg/redcarpet/issues/813)

# Desarrollo

El desarrollo se puede realizar localmente o usando el `Dockerfile` proporcionado en este repositorio.

Puede construir la imagen Docker de Ruzzy con el siguiente comando:

```bash
docker build --tag ruzzy .
```

Luego, puede acceder al contenedor con el siguiente comando:

```
docker run -it -v $(pwd):/app/ruzzy --entrypoint /bin/bash ruzzy
```

## Compilación

Usamos [`rake-compiler`](https://github.com/rake-compiler/rake-compiler) para compilar las extensiones C de Ruzzy.

Puede compilar las extensiones C dentro del contenedor con el siguiente comando:

```bash
rake compile
```

## Pruebas

Usamos pruebas unitarias de `rake` para probar el código Ruby.

Puede ejecutar las pruebas dentro del contenedor con el siguiente comando:

```bash
LD_PRELOAD=$(ruby -e 'require "ruzzy"; print Ruzzy::ASAN_PATH') \
    rake test
```

## Linting

Usamos `rubocop` para hacer linting del código Ruby.

Puede ejecutar `rubocop` dentro del contenedor con el siguiente comando:

```bash
rubocop
```

## Publicación

Ruzzy se [publica](https://github.com/trailofbits/ruzzy/actions/workflows/release.yml) automáticamente en [RubyGems](https://rubygems.org/gems/ruzzy) cuando se empuja una nueva etiqueta git.

Para publicar una nueva versión, ejecute los siguientes comandos:

```bash
git tag vX.X.X
```

```bash
git push --tags
```

# Lecturas adicionales

- Extensiones C de 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 de 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
- Cobertura
  - 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
Descargar herramienta