Metadata-Version: 2.4
Name: pyradamsa
Version: 1.0.0
Summary: Python bindings for radamsa fuzzing library.
Author-email: "Daniel Timofte @tim17d" <timofte.daniel@tuta.io>
License-Expression: MIT
Project-URL: Homepage, https://github.com/tsundokul/pyradamsa
Keywords: radamsa,fuzzing,libradamsa
Classifier: Development Status :: 4 - Beta
Classifier: Topic :: Security
Classifier: Operating System :: POSIX :: Linux
Classifier: Operating System :: MacOS :: MacOS X
Classifier: Programming Language :: Python :: 3
Requires-Python: >=3.2
Description-Content-Type: text/markdown
License-File: LICENSE
Dynamic: license-file

pyradamsa
==========================

`pyradamsa` provides an interface for calling libradamsa methods from within Python, allowing one to perform mutations on byte blocks (aka fuzzing). For more details see [radamsa](https://gitlab.com/akihe/radamsa) (a general-purpose fuzzer) and [libradamsa](https://github.com/andreafioraldi/libradamsa) (precompiled radamsa library).

### NOTE
The master branch uses AFL++'s libradamsa. An alternative version created by [p1-olm](https://github.com/p1-olm) is available on [radamsa-upstream](https://github.com/tsundokul/pyradamsa/tree/radamsa-upstream) branch and is based on the [original](https://gitlab.com/akihe/radamsa) libradamsa upstream.

How is the `radamsa-upstream` different than the `master` version?
- The owl VM initialization uses different seeds, so result are different when mutating same bytes with the same seed
- Future updates from libradamsa creators will show up first in `radamsa-upstream`

## Usage

Install the package using `pip` (or [build](#building) it from source)
```bash
pip install pyradamsa
```

Do some fuzzing
```python
import pyradamsa

rad = pyradamsa.Radamsa()

mydata = b'GET /auth?pass=HelloWorld HTTP1.1'
fuzzed = rad.fuzz(mydata, seed=1337)
print(fuzzed)

> b'GET /auth?pass=HelloWorld HTTP\xc0\xb1.1'

# seed is randomly set if not provided
rad.fuzz(mydata)
> b'\tG\xf3\xa0\x81\x9c\xf7dLET \xe2\x81/aut\xf3\xa0\x80\xafHTTP2.rld HTTP2.rld HTTP3.2\xe1\xa0\x8e9'
rad.fuzz(mydata)
> b'GET /auth?pass=HelloWorld HTTP1.340282366920938463463374607431768211455'
etc.

# enforce static seed on initialization
rad = pyradamsa.Radamsa(seed=0)

# max_mut enforces a maximum length for returned data
# it defaults to (data length + an offset of 4096 bytes)
fuzzed = rad.fuzz(mydata, seed=1337, max_mut=10)
> b'GET /auth?'

# the offset may be overwritten on init
rad = pyradamsa.Radamsa(mut_offset=2048)
```

## Building
Currently wheels are built from source for your architecture
```sh
# Clone the repo
git clone --recurse-submodules https://github.com/tsundokul/pyradamsa.git
cd pyradamsa

# patch memory leak when reinitializing owl vm
patch libradamsa/libradamsa.c realloc.patch

# Run tests (uv handles building the C extension automatically)
./run_tests

# Build wheel
uv build
```

## Contributing
* Fork the repo
* Check out a feature or bug branch
* Add your changes
* Update README when needed
* Submit a pull request to upstream repo
* Add description of your changes
* Ensure tests are passing
* Ensure branch is mergeable

_MIT License, 2020_ [@tim17d](https://twitter.com/tim17d)
