Metadata-Version: 2.4
Name: rfox
Version: 1.0.1
Summary: Unified rfcat helper for sub-GHz RF work
Home-page: https://github.com/qu-crypt/rfox
Author: qu-crypt
Author-email: qucrypt@0x3f.dev
Keywords: radio,subghz,rfcat,sdr,hacking,reverse engineering
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Information Technology
Classifier: Topic :: Communications
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Requires-Python: >=3.8
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: rfcat-py3
Provides-Extra: specan
Requires-Dist: PySide6>=6.4; extra == "specan"
Dynamic: author
Dynamic: author-email
Dynamic: classifier
Dynamic: description
Dynamic: description-content-type
Dynamic: home-page
Dynamic: keywords
Dynamic: license-file
Dynamic: provides-extra
Dynamic: requires-dist
Dynamic: requires-python
Dynamic: summary

# rfox

> Unified [rfcat-py3](https://github.com/qu-crypt/rfcat) 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.

```bash
./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`](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](https://github.com/AndrewMohawk/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](https://github.com/qu-crypt/rfcat) for the underlying `rflib` library.

```bash
pip install rfox
```

Optional dependencies:

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

For development:

```bash
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](https://github.com/qu-crypt/rfcat) repo's `etc/udev/`

Verify:

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

---

## Quick start

Five things you'll almost certainly want to do:

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

```bash
./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`:

```bash
./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:

```python
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:

```bash
./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:

```bash
./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:

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

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

---

## 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`](LICENSE).

It builds on top of [rfcat-py3](https://github.com/qu-crypt/rfcat),
which is distributed under the MIT License.

---

## Acknowledgements

- [@atlas0fd00m](https://github.com/atlas0fd00m) for the original rfcat and rflib.
- [@qu-crypt](https://github.com/qu-crypt) for the Python 3 port ([rfcat-py3](https://github.com/qu-crypt/rfcat)) and dongle firmware.
- [@AndrewMohawk](https://github.com/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.
