Skip to main content

Ruminant is a recursive metadata extraction and file dissection tool.

What does it do?

Ruminant takes a file as an input and spits out a huge json object that contains all the (meta)data it extracted from the file. This is done recursively, e.g. by running ruminant again on each file inside a ZIP file or on the thumbnail inside a JPEG file.

Why the name?

To quote Wikipedia: Ruminants are herbivorous grazing or browsing artiodactyls [...]. The process of rechewing the cud to further break down plant matter and stimulate digestion is called rumination. The word "ruminant" comes from the Latin ruminare, which means "to chew over again".

This tool behaves similarly as extracted blobs themselves can be "chewed over again" (the main entrypoint is literally called chew()) in order to recursively extract metadata.

What can it process?

Ruminant is still in early alpha but it can already process the following file types:

  • Android AVB vbmeta partitions
  • Android boot images
  • FLAC
  • ID3v2 (e.g. wrapping MP3 files)
  • MP3
  • MIDI
  • GZip
  • BZip2
  • Zstd
  • Zlib
  • XZ
  • ZIP
    • embedded Android APK signatures
    • ZipCrypto encryption, no AES though
  • RIFF
    • WebP
    • WAV
    • AVI
    • DjVu
  • Tar
  • Ar
  • CPIO
  • HTTP framed streams like MJPEG
  • Java Jmod
  • UF2
  • DVD MPEG sequences
  • Grub 2 modules
  • Android backups
    • no encryption yet
  • Cab
  • IWA
  • PcapNG
    • IPv4/IPv6/LLDP/ARP
    • UDP/TCP/ICMP/IGMP/ICMPv6
    • DNS
      • A/OPT/SOA/AAAA/MX/TXT/CAA/DNSKEY/RRSIG/HTTPS/NS/SSHFP/OPENPGPKEY/SRV/DS/NSEC3
  • NCSD (Nintendo 3DS)
  • NCCH (Nintendo 3DS)
  • SMDH (Nintendo 3DS)
  • DARC (Nintendo 3DS)
  • DER (binary)
  • PEM
  • PGP (binary or armored)
  • KeePass KDBX
    • including AES and ChaCha20 decryption, no Twofish though
  • Age
  • LUKS 1/2
    • encryption for LUKS2 when used with aes-xts-plain64 and supplied MK
  • SSH signatures
  • EFI signature lists
  • PDF
  • WASM
  • Java classes
    • including full disassembly
  • ELF
  • PE/EXE/EFI
  • SPIR-V shaders
  • Python bytecode
    • no disassembly due to unstable nature of bytecode
  • Intel microcode
    • including signature extraction
  • a.out
  • MBR/GPT partition tables
  • BTRFS send streams
  • TrueType fonts
  • Adobe Photoshop IRB chunks
  • ICC profiles
  • JPEG
  • PNG
  • TIFF
    • EXIF metadata is just a TIFF file
  • GIF
  • Google HDR+ MakerNotes
    • I reverse engineered that btw :D
  • PSD (Adobe Photoshop)
  • DICOM
  • OpenEXR
  • ICO
  • Qoi
  • BitTorrent files
  • Sqlite3 databases
  • Minecraft NBT
  • Minecraft MCA chunk regions
  • Git related files (blob, tree, commit)
  • OpenTimestamps proof files
  • Java serialization data
  • Safetensors models
  • GGUF models
  • Apple binary property lists
    • text based ones are just XML
  • OpenStreetMap protobufs
  • STL models
  • AppleDouble
  • Microsoft printer settings
    • you may find them in XLSX files
  • Mindustry schematics
  • UTF-8 text files
    • including detection and parsing for base64, JSON and XML
  • Empty files (duh)
  • Zero filled files (also duh)
  • ISOBMFF
    • MP4/MOV/HEIC/HEIF/AVIF/JPEG2000
  • EBML/Matroska/MKV/WebM
  • Ogg/Ogv
  • MPEG-TS
  • ASF/WMA/WMV
  • Duck IVF
  • Dirac data units
  • JVT-NAL H.264
  • GRUB2 fonts
  • DVD .VOB files/MPEG-PS

Video codecs

Ruminant can extract and parse data units of specific codecs from specific containers.

Legend

❌: not yet supported

🚧: partially supported

✅: fully supported (or at least as much as I want it to be)

empty means the container doesn't support it

Codec MP4 MKV MPEG-TS Duck IVF HEIF MPEG-PS AVI
MPEG-2 🚧 🚧 🚧 🚧 🚧
H.264 ✅ ✅ ✅ ✅ ✅ ✅
H.265 🚧 🚧 🚧 🚧 🚧
H.266 🚧 🚧 🚧 🚧
AV1 ✅ ✅ ✅ ✅ ✅
AV2 🚧 🚧 🚧 ❌
Dirac ✅ ✅ ✅ ✅
ProRes ✅ ❌
Vorbis 🚧 🚧 ❌
Theora 🚧 ❌
AC-3 ✅ ✅ ✅ ✅ ✅
MP2 ✅ ✅ ✅ ✅
MP3 ✅ ✅ ✅ ✅
AAC ❌ ❌ ✅ ❌
FLAC 🚧 🚧 ❌
Opus 🚧 🚧
TX3G ✅
METT ✅
DVBSUB ✅ ✅
Teletext ✅

How do I install it?

Run pip3 install ruminant\[full\] if you want C acceleration or pip3 install ruminant if you want pure Python.

How do I use it?

The most basic usage would be ruminant <file> in order to process the file and output all metadata.

Each time a blob is passed to chew(), it gets assigned a new unique ID that is stored in the "blob-id" field in its JSON object. These blobs can be extracted with ruminant <file> --extract <ID> <file name>. The --extract option can also be shortened to -e and can be repeated multiple times.

Not specifying a file means that it reads from -, which is the standard input. You can also explicitly pass - as the file.

The --walk or -w option enables a binwalk-like mode where ruminant tries to parse a file and increments the start offset by one until it can correctly parse something. This is done until the end of the file.

This is a valid complex command: ruminant -e 2 foo.jpeg - --extract 5 bar.bin -e 0 all.zip

(Yes, you could abuse ruminant to copy files by running function cp() { ruminant --extract 0 $2 $1 } in bash and then using the function as cp.)

You can also specify --extract-all in order to extract all blobs to the "blobs" directory. Specifying a directory as the file makes ruminant walk that directory recursively. Adding --progress shows a progress bar (this requires tqdm). Adding --progress-names adds file names to the progress bar.

Specifying --url makes ruminant treat the file name as a URL and makes it try to fetch the file from it. It uses the user agent of a recent Chrome to not be blocked.

Adding --strip-url makes ruminant change some parts of known URLs to preserve metadata. It can, for example, detect that a file is being hosted by Wordpress based on the "/wp-content/" start of the path and can then remove the "-x" part of the file name to preserve its original size and avoid reencoding of the file.

The user agent can be overridden by setting the RUMINANT_USER_AGENT environment variable with the desired agent.

Adding -p <ID> <VALUE> adds a parameter with a value. This can for example be used to specify decoding ranges or cryptographic keys. One example would be to run ruminant on an encrypted ZIP file which contains the following JSON object:

"key": {
  "name": "47fafe9b1ce795e5ece32c5e",
  "found": false
}

The key can then be specified by adding -p 47fafe9b1ce795e5ece32c5e foobar to the command.

Adding --slim removes all unnecessary whitespace from the output.

Adding --shallow prevents recursive parsing.

Running ruminant on a directory processes all files in the directory. Adding --filename-regex <REGEX> makes it only process files that match the regex.

Adding --print-modules prints all registered modules and exits.

Adding --self-test runs a test suite and exits.

Adding --version prints the version and exits.

Ruminant can't parse xyz

Feel free to send me a sample so I can add a parser for it :)

Metadata

Release files for ruminant 0.0.41

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for ruminant 0.0.41
File Size Uploaded
ruminant-0.0.41.tar.gz 321.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for ruminant 0.0.41
File Interpreter ABI Platform
ruminant-0.0.41-py3-none-any.whl Python 3 none any Details

Total release size: 645.9 kB

Release files / ruminant-0.0.41.tar.gz

Download URL ruminant-0.0.41.tar.gz
Size 321.0 kB
Tags Source
SHA-256 checksum
How to use checksums
da8834d0b4542bded62ac5cdfa84cb24def48fc922b3c05a0cdfbf20327400bc
BLAKE2b-256 checksum
How to use checksums
d813cae67f5b8daa10c6d1ff7be1a35acf4ce39999a63519f6e77508cd95feb0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.13

Release files / ruminant-0.0.41-py3-none-any.whl

Download URL ruminant-0.0.41-py3-none-any.whl
Size 324.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
48f435036c7f792101555e25be2e358db9b4b8a7f0a639a7e07f3e98a70dedcf
BLAKE2b-256 checksum
How to use checksums
c86bfe0b7b4aae1647474304a2d1b0b0528740d8c5b6c2ef75d726490b6571e6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.13

Release history Release notifications | RSS feed

This release

0.0.41 This release

2 release files

0.0.39

2 release files

0.0.37

2 release files

0.0.35

2 release files

0.0.34

2 release files

0.0.33

2 release files

0.0.32

2 release files

0.0.31

2 release files

0.0.19

2 release files

0.0.16

2 release files

0.0.15

2 release files

0.0.14

2 release files

0.0.13

2 release files

0.0.12

2 release files

0.0.9

2 release files

0.0.8

2 release files

0.0.7

2 release files

0.0.6

2 release files

0.0.5

2 release files

0.0.4

2 release files

0.0.3

2 release files

0.0.2

2 release files

0.0.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page