Skip to content

qu-crypt/rfox

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

rfox

Unified rfcat-py3 helper for sub-GHz RF work. One CLI, one interactive menu, one capture format. Built on top of rfcat / rflib so it works with any YARDStickOne, RfCat-compatible CC1111 dongle, or DonsDongle.

./rfox                                      # interactive menu
./rfox decode --hex aabbccdd -m manchester  # direct CLI

⚠️ Legal & ethics — read this first

rfox is a dual-use security research tool. Several of its commands — notably jam, scanjam, rolljam, brute, and fuzz — actively transmit RF energy and can interfere with, disable, or attempt to gain unauthorised access to wireless systems. In most jurisdictions this is illegal unless you own the target equipment or have explicit, written authorisation to test it.

You are responsible for understanding and complying with the law in your country. As a non-exhaustive starting point:

  • United States — 47 U.S.C. § 333 prohibits "wilful or malicious
    interference" with any radio communication. The FCC enforces this and has fined private individuals six-figure amounts for jamming. The Computer Fraud and Abuse Act (CFAA) covers unauthorised access to electronic systems.
  • United Kingdom — the Wireless Telegraphy Act 2006 makes unlicensed intentional interference an offence; the Computer Misuse Act 1990 covers unauthorised access.
  • European Union — RED (2014/53/EU) and national transposition acts regulate spectrum use; most member states have similar criminal prohibitions on jamming.
  • Australia, Canada, Japan, … — similar regimes exist almost everywhere.

Use rfox only for:

  • security research on equipment you own;
  • formally authorised penetration testing engagements (with a written scope-of-work / authorisation letter from the asset owner);
  • CTF challenges and educational exercises in shielded enclosures (RF isolation chamber, Faraday cage / bag) where transmissions cannot leak into licensed bands;
  • compliance and interoperability testing in a controlled lab environment.

Do not use rfox to:

  • attack, disrupt, or interfere with infrastructure, vehicles, premises, devices, or services that are not yours, or for which you do not hold written authorisation;
  • jam, intercept, or replay communications belonging to other people;
  • bypass access controls (gates, garage doors, vehicles, alarms, locks) on property you do not own;
  • target safety-critical, life-safety, public-safety, or aviation systems under any circumstances.

By using this software, you acknowledge that you alone are responsible for ensuring your use is lawful and authorised. The authors and contributors provide rfox without warranty of any kind (see LICENSE) and are not liable for any direct or indirect harm, legal action, regulatory penalty, equipment damage, or data loss arising from its use or misuse.

If any of this is unclear, stop and consult a qualified lawyer in your jurisdiction before using the offensive commands.


Why rfox

rfcat ships a powerful Python library (rflib) and an interactive shell, but day-to-day RF work tends to be the same handful of recipes — capture a key fob, replay it, sweep a band, decode some Manchester, find the rolling counter — repeated with slightly different parameters. The community RfCatHelpers project showed how useful those recipes are as standalone scripts, but each one re-implements the same dongle init, defines its own incompatible CLI, and uses its own ad-hoc capture format.

rfox consolidates that workflow into:

  • one tool with consistent flags everywhere (-f is always Hz, -r is always bps, -m is always one of OOK / 2FSK / GFSK / MSK / 4FSK);
  • an interactive menu for when you don't remember the flags — it walks you through every option with the default shown;
  • one capture file format (libpcap, DLT_USER0, RFCT pseudo-header) so anything you capture in one mode can be replayed, decoded, diffed, or CRC-checked by any other command;
  • named profiles (~/.rfcat/profiles.json) and built-in presets for common protocols, so you stop re-typing six flags for every command.

The interactive menu and the CLI share a single dispatcher, so they can never drift apart — adding a new command exposes it in both modes automatically.


Installation

rfox is a standalone tool that depends on rfcat-py3 for the underlying rflib library.

pip install rfox

Optional dependencies:

pip install 'rfox[specan]'      # enables `rfox specan` (PySide6)

For development:

git clone https://github.com/qu-crypt/rfox.git
cd rfox
python3 -m venv .venv && source .venv/bin/activate
pip install -e .

System libraries:

  • libusb-1.0 (Linux: apt install libusb-1.0-0, macOS: brew install libusb, Windows: see the rfcat README)
  • non-root USB access on Linux requires the udev rules from the rfcat-py3 repo's etc/udev/

Verify:

./rfox --help
./rfox devices         # lists attached dongles

Quick start

Five things you'll almost certainly want to do:

# 1. Sweep a band looking for activity
./rfox sweep --start 433e6 --stop 434e6 --step 50e3 --ascii-bar

# 2. Capture five presses of a 433 MHz remote into a pcap
./rfox replay capture --preset ev1527 -n 5 -o /tmp/garage.pcap

# 3. Replay them
./rfox replay replay --input /tmp/garage.pcap --use-capture-cfg

# 4. Find the rolling-counter byte (or rule it out)
./rfox diff --input /tmp/garage.pcap

# 5. Identify the protocol's checksum
./rfox crc --input /tmp/garage.pcap

No dongle? The analysis subcommands work entirely on captures or hex strings:

./rfox decode --hex aabbccdd -m auto
./rfox find-sync --hex aaaaaad391deadbeef
./rfox crc --hex 12345612fd
./rfox diff --hex aabbcc00 --hex aabbcc01 --hex aabbcc02

Command reference

group command what it does needs hw
dongle devices list connected RfCat dongles
specan open the PySide6 spectrum analyser
RX scan RX loop, hex-print frames, optional pcap log
sweep RSSI sweep across --start..--stop, optional CSV
logger headless RX → append every frame to a pcap
TX transmit binary string → OOK (raw or PWM-encoded)
tx-hex raw bytes given as hex on the CLI
jam one frequency for N seconds ⚠️
scanjam two dongles: scan + reactive-jam ⚠️ ✓✓
brute iterate a key space and transmit each value ⚠️
fuzz bit/byte-mutate a seed frame, retransmit ⚠️
capture/replay replay capture record N frames to a pcap
replay replay replay a pcap
rolljam jam → capture 1 → unjam → capture 2 → replay 1 ⚠️ ✓✓
analysis decode manchester/diff-manchester/PWM/raw decoders
find-sync candidate sync words in a capture
find-repeats repeating bit patterns
crc try CRC-8/CRC-16 polynomials over capture tails
diff bit-by-bit diff (find rolling-counter fields)
decode-wav OOK decoder for WAV recordings
workflow profile {save,show,list,delete} named radio configs
preset {list,show} built-in protocol presets

Commands marked ⚠️ are the ones you should only use on equipment you own or are formally authorised to test. See the disclaimer above.

✓✓ means the command requires two dongles.

Each command also has full --help:

./rfox replay capture --help
./rfox find-sync --help

Capture file format

Every capture/replay command shares one libpcap file (magic 0xa1b2c3d4, link type DLT_USER0 = 147). Each packet payload starts with a 24-byte RFCT pseudo-header recording the radio configuration at capture time, followed by the raw on-air bytes:

struct rfct_pseudo_hdr {        // little-endian
    uint8_t  magic[4];          // "RFCT"
    uint8_t  version;           // 1
    uint8_t  modulation;        // 0=OOK 1=2FSK 2=GFSK 3=MSK 4=4FSK
    uint32_t freq_hz;
    uint32_t drate_bps;
    uint32_t chanbw_hz;
    int16_t  rssi_dbm10;        // dBm * 10, signed
    uint16_t sync_word;         // 0 if none
    uint8_t  payload[];
};

Read with the dataclass-based reader:

from rflib.rfox import pcap

for frame in pcap.read("garage.pcap"):
    print(frame.ts, frame.cfg.summary(), frame.payload.hex())

Or open it in Wireshark / tshark — frames will appear as data under USER0. A future Lua dissector could decode the pseudo-header field by field, but the raw bytes are usable today with any pcap parser.


Profiles & presets

Save a configuration once, reuse it forever:

./rfox profile save mygate -f 433.92e6 -r 2400 -m OOK --chanbw 325000
./rfox replay replay --input cap.pcap --profile mygate

Or jump straight to a built-in:

./rfox preset list
./rfox scan --preset ev1527
./rfox tx-hex --preset keyfob315 --hex aabbcc

CLI flags override the profile/preset, so --preset ev1527 --freq 433.95e6 works.

Built-in presets:

name freq drate mod typical use
ev1527 433.92 MHz 2400 OOK generic 433 MHz remotes
pt2262 433.92 MHz 1200 OOK older garage / gate openers
keeloq 433.92 MHz 2000 OOK rolling-code keyfobs
keyfob315 315 MHz 2400 OOK US automotive key fobs
srd868 868.35 MHz 4800 2FSK EU short-range devices
ism915 915 MHz 38 400 2FSK US ISM band
tpms433 433.92 MHz 19 200 2FSK tyre-pressure sensors

Adding a new command

Drop a module under rflib/rfox/commands/, expose three functions:

HELP = "one-line description shown in --help and the menu"

def add_args(parser):
    """Attach argparse args. Use _common.add_radio_args / add_dongle_args."""

def prompt(args):                # optional
    """Walk the user through args interactively."""

def run(args):
    """Do the work. Return an exit code."""

Register it in rflib/rfox/commands/__init__.py. The CLI dispatcher and the interactive menu both pick it up automatically.

Use _common.cfg_from_args(args) to honour --preset / --profile before merging in CLI overrides — that's how every existing command keeps its behaviour consistent.


Tests

python -m unittest tests.test_rfox

The pcap roundtrip, presets, profiles, and analysis subcommands (decode, find-sync, find-repeats, crc, diff, decode-wav) are covered without hardware. The hardware-using TX commands are smoke-tested by patching open_dongle to return FakeRfCat.


Versioning & stability

rfox is versioned independently of rfcat. Anything in rflib.rfox.commands is part of the public CLI; flag names and the pcap pseudo-header layout are stable within a major version. Anything under rflib.rfox (other than the public command modules) is internal and may change without notice.


Contributing

Pull requests welcome. Please:

  1. Open an issue first for non-trivial changes.
  2. Add a test under tests/test_rfox.py that exercises your code without hardware (use FakeRfCat for TX commands).
  3. Match the existing argparse flag style (-f/--freq is Hz, -r/--drate is bps, etc.).
  4. Don't add commands that are exclusively useful for unauthorised attacks.

By contributing, you agree your contribution is licensed under the MIT License (see LICENSE).


License

rfox's own source — the entry script, the rflib/rfox/ package, and tests/test_rfox.py — is released under the MIT License. See LICENSE.

It builds on top of rfcat-py3, which is distributed under the MIT License.


Acknowledgements

  • @atlas0fd00m for the original rfcat and rflib.
  • @qu-crypt for the Python 3 port (rfcat-py3) and dongle firmware.
  • @AndrewMohawk — the original RfCatHelpers project that mapped out the most useful day-to-day recipes and motivated this tool.
  • The Ubertooth, GNU Radio, and HackRF communities for decades of prior art in sub-GHz tooling.

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages