GPU-accelerated ARC4 key recovery for DMR Enhanced Privacy voice communications.
FSP.DMRCrack performs exhaustive 40-bit RC4 key search against captured DMR Enhanced Privacy voice frames. On Windows it ships as a native GUI application with DSD-FME integration. On Linux it runs as a headless CLI tool.
Use on systems you own or have explicit written permission to test. Unauthorized interception of radio communications is illegal in most jurisdictions.
DMR Enhanced Privacy (EP) is the encryption layer built into MOTOTRBO, Hytera, and other DMR Tier II/III radios. It uses ARC4 (RC4) with a 40-bit (5-byte) key. At roughly one trillion candidates that keyspace is tractable on a modern GPU in a few hours.
FSP.DMRCrack exploits the structure of AMBE voice coding: valid speech produces predictable inter-frame parameter distributions, so the correct key stands out as a significance (Z-score) spike well above the noise floor. The tool reports a plain CONFIRMED / UNVERIFIED / no-key verdict rather than a raw number, so a statistical latch is never mistaken for a recovery. It runs the same pipeline as DSD-FME's own decoder, so what the tool finds actually decrypts the audio.
Intended users: licensed radio operators auditing their own systems, security researchers, and CTF participants.
| Requirement | Details |
|---|---|
| OS | Windows 10/11, 64-bit |
| GPU | NVIDIA sm_75+ (GTX 16xx / RTX 20xx through RTX 50xx). Native SASS for Turing/Ampere/Ada/Blackwell (RTX 50-series); a PTX fallback JIT-covers other archs. CPU fallback available but expect days instead of hours — a GPU is strongly recommended. |
| Runtime | None — DSD-FME and all Cygwin DLLs are bundled by the installer |
| Python | 3.8+ (optional, for verify_decrypt.py and diag_decrypt.py) |
| CUDA Toolkit | 12.x (build-time only; 12.8+ needed to emit native RTX 50-series SASS) |
| Visual Studio | 2022 with Desktop C++ workload (build-time only). VS 2026 works too, but install the MSVC v143 toolset — nvcc rejects the v145 (VS 2026) compiler; _vsenv.bat selects v143 automatically. |
| Requirement | Details |
|---|---|
| OS | Any x86-64 Linux distribution |
| GPU | Any OpenCL 1.2+ GPU (NVIDIA / AMD / Intel) via -DUSE_OPENCL=ON — or NVIDIA sm_75+ with CUDA 12.x — or AMD RDNA/CDNA with ROCm 6.x (-DUSE_HIP=ON). Runs CPU-only when no GPU is present. |
| Build tools | CMake ≥ 3.21, GCC/Clang. OpenCL: opencl-headers + an ICD loader. CUDA: Toolkit 12.x. HIP: ROCm 6.x. |
| Python | 3.8+ (optional) |
- Download
FSP.DMRCrack-Setup.exefrom Releases. - Run the installer (requires Windows 10/11 x64, admin rights).
- Launch FSP.DMRCrack from the Start menu or desktop shortcut.
Everything is included: the GPU brute-force engine, the DSD-FME demodulator, and all required Cygwin runtime DLLs.
Clone the repo and build with build.bat (requires CUDA Toolkit + Visual Studio). dsd-fme.exe and the Cygwin DLLs are already in tools/. If they are missing (e.g. on a clean CI checkout), run tools\get_runtime.bat to fetch them. See Building from source below.
The portable OpenCL back-end has free build deps and runs on NVIDIA, AMD and Intel GPUs (and CPU-only when no GPU is present):
sudo apt-get install -y cmake build-essential opencl-headers ocl-icd-opencl-dev
cmake -S . -B build -DUSE_OPENCL=ON -DNO_GUI=ON -DCMAKE_BUILD_TYPE=Release
cmake --build build --parallel
# binary at bin/dmrcrackSee Building from source for the CUDA and ROCm/HIP back-ends.
- Record a WAV file of the DMR RF signal (discriminator audio, 48 kHz mono recommended).
- Open FSP.DMRCrack and select the WAV file in the Capture section.
- Click Demodulate — DSD-FME runs automatically, extracts encrypted voice payloads, and writes a
.binfile. - Click Start in the Brute-force section to begin the GPU search.
- Monitor progress: keys/sec graph, best-score evolution, ETA.
- The correct key produces a sharp score spike well above the noise floor.
- Click Listen to re-run DSD-FME with the recovered key, decrypt the capture to a plain WAV, and play it back.
The GUI can also drive an RTL-SDR directly: click Live capture, enter a
frequency, and FSP.DMRCrack runs DSD-FME unattended, watches for encrypted voice,
and once it has accumulated enough frames it saves a .bin and auto-starts the
crack. This path is newly added and not yet validated on hardware — treat it
as experimental and verify against a signal you are authorized to test. The
offline file workflow above remains the supported path.
If you already have a .bin payload file (e.g., generated by DSD-FME + dsdfme_dsp_to_bin.py):
- Select the
.binfile in the BRUTEFORCE section. - Configure the key range (default: full 40-bit space
0000000000–FFFFFFFFFF). - Click Start.
The headless binary (bin/dmrcrack) takes the .bin file via --bin and runs
the same engine as the GUI:
# Full 40-bit brute-force (auto-detects MOTOTRBO / Hytera / legacy mode)
dmrcrack --bin capture.bin
# Score a single candidate key and exit
dmrcrack --bin capture.bin --key <KEY_HEX>
# Dictionary attack: try a list of hex keys first (one per line, '#' comments)
dmrcrack --bin capture.bin --wordlist keys.txt --potfile found.pot
# Measure throughput on this machine (~5 s) and exit
dmrcrack --bin capture.bin --benchmark
# Machine-readable result
dmrcrack --bin capture.bin --key <KEY_HEX> --jsonRecovered keys can be appended to a potfile (basename:key:score) with
--potfile, and any mode can emit a JSON result with --json. Run
dmrcrack --help for the full option list. A bash-completion script is
installed by the Debian package and by cmake --install.
One payload per line, hex-encoded (33 bytes = 66 hex characters). Optional metadata after ;:
AABBCCDDEEFF112233...;ALG=21;KID=0F;MI=12345678
| Tag | Meaning |
|---|---|
ALG=21 |
MOTOTRBO RC4 Enhanced Privacy — uses KMI9 pipeline (key9 = key5 || MI[4]) |
ALG=02 |
Hytera Enhanced Privacy — RC4 KSA with key5, keystream XOR'd with KIV derived from key5+MI |
KID=XX |
Key ID |
MI=... |
Message Indicator, hex — 32-bit (8 chars) for MOTOTRBO, 40-bit (10 chars) for Hytera |
The pipeline is auto-selected at scan start based on the ALG distribution of loaded lines. If ≥ 90 % carry ALG=02 + MI, the Hytera EP kernel is used. If ≥ 90 % carry ALG=21/ALG=01 + MI, the MOTOTRBO KMI9 kernel is used. Otherwise the legacy 5-byte key mode runs.
Converts DSD-FME -Q DSP output + stderr log into a .bin payload file with correct per-frame MI assignment.
python tools\dsdfme_dsp_to_bin.py --dsp RC4.dsdsp.txt --out RC4.bin --log RC4.dslog.txtValidates a candidate key against a .bin file and prints Z-score metrics.
python tools\verify_decrypt.py --bin RC4.bin --key <YOUR_KEY_HEX>Expected output for a correct key on 126 payloads: Z ≈ 335 (bit-frequency), Z ≈ 38 (Hamming).
For each key candidate, the GPU kernel (CUDA, HIP or OpenCL — same algorithm) runs the complete DSD-FME/mbelib pipeline per burst:
- Build
key9 = key5 || MI[4] - RC4 KSA with 9-byte key; discard
256 + burst_pos × 21bytes of keystream - For each sub-frame (0, 1, 2):
- De-interleave 33-byte payload →
ambe_fr[4][24] - mbelib demodulate (PRNG XOR on row 1)
- Extract 49 AMBE bits → pack to 7 bytes
- RC4 decrypt → unpack 24 bits
- De-interleave 33-byte payload →
- Score = Σ(24 − Hamming distance) across consecutive sub-frame pairs
Valid speech has slowly-varying AMBE parameters (HD ≈ 0–4). Random keys produce HD ≈ 12. At 126 payloads the correct key achieves Z ≈ 48.5 sigma (C/CPU path).
Between superframes (every 6 bursts), MI advances by 32 LFSR steps: taps {31,3,1}.
Hytera EP uses a different key schedule: RC4 KSA with the 5-byte key only (no MI in the KSA, no keystream discard), then the keystream octets are XOR'd with a key-IV (kiv) where kiv[i] = key5[i] XOR MI[i] over all 5 bytes (40-bit big-endian MI), matching DSD-FME's hytera_enhanced_rc4_setup. One keystream is built per superframe and consumed as a bitstream at 49 bits per AMBE frame — and, unlike MOTOTRBO/P25, Hytera does not skip the trailing 7 bits, so AMBE frame f = burst_pos·3 + sf reads keystream bits [f·49 … f·49+48] (MSB-first, not byte-aligned). The keystream is single-sourced in include/hytera_ks.h (verified byte-for-byte against DSD-FME's rc4_block_output + bitstream model over thousands of random vectors, and end-to-end against a planted-key synthetic capture). Hytera's inter-superframe MI advances with its own 5-byte LFSR (taps 12 24 48 22 14), so a single decoded PI header now tags a whole capture. The scoring algorithm is identical to MOTOTRBO (inter-frame Hamming + bit-frequency chi-squared). A dedicated bruteforce_kernel_hytera kernel handles these payloads with zero overhead on MOTOTRBO paths; the MI-independent RC4 keystream is built once per key and re-masked per superframe. Hytera EP is signalled under two algids — ALG=0x02 and ALG=0x26 — both recognised.
Measured on an RTX 3050 Ti laptop GPU (CUDA back-end, full pipeline with the noise-tolerant early-reject):
| Cipher | Throughput | Full 2⁴⁰ scan |
|---|---|---|
| MOTOTRBO (KMI9) | ~38 M keys/s | ~8 h |
| Hytera EP | ~10 M keys/s | ~30 h |
Throughput scales with the GPU, so faster cards finish proportionally sooner;
these are the only figures verified so far, and other hardware has not been
benchmarked. The early-reject rejects wrong keys within one superframe using a
noise-tolerant floor (24·n + 8·√n): it keeps even a heavily degraded correct
key while pruning the bulk of the keyspace — trading raw speed for the ability to
recover keys from real, noisy over-the-air captures. Native sm_120 SASS is
emitted for the RTX 50-series (Blackwell); a PTX fallback JIT-covers other archs.
The portable OpenCL back-end trades throughput for vendor-neutrality
(NVIDIA / AMD / Intel) — it omits the CUDA ILP-2 shared-memory kernel — so it is
slower than native CUDA on the same card. When no GPU device is present it falls
back to the multi-threaded CPU scorer. Narrow the key range (--start / --end)
whenever you can to cut search time.
Because a wrong or dictionary key can still post a high raw score, the tool does
not report the top-scoring key as "the key" on its own. It re-scores the best
candidate into a capture-size-normalized significance Z = (r − 24)·√n / √12
(where r is the mean per-burst inter-frame agreement over n bursts) and gives
a verdict: CONFIRMED (Z ≥ 12, a genuine recovery), UNVERIFIED (7 ≤ Z < 12,
weak — confirm with DSD-FME), or no confirmed key below that. A dictionary
latch inflates the chi² term but cannot fake inter-frame agreement, so its Z stays
near zero and it is never presented as a recovery.
- Other ciphers. Supported: DMR Enhanced Privacy RC4 (MOTOTRBO ALG=0x21 and Hytera Enhanced Privacy ALG=0x02), both with a 40-bit key. Not supported: AES-256 (Motorola DMR-AES / Hytera HP), Tytera DMRA, or any non-RC4 cipher.
- Captures without MI metadata. The strict pipeline needs the Message Indicator extracted from each superframe. Without it the legacy statistical scorer runs, which is much less reliable.
- Bad audio. If DSD-FME can't cleanly demodulate the WAV, the search will run but won't find the key.
- Production live SDR ingest. The offline file workflow (record to WAV, then feed it in) is the supported path. Direct RTL-SDR live capture exists in the GUI but is experimental and not yet hardware-validated.
- Targeting third-party systems. This is for authorized auditing of systems you own or have written permission to test. See
LICENSE.
Requires CMake >= 3.21 and GCC/Clang. Pick a GPU back-end:
Portable OpenCL (recommended — NVIDIA / AMD / Intel). This is what the
Debian/Kali package builds. Only needs opencl-headers and an ICD loader
(ocl-icd-opencl-dev); falls back to the multi-threaded CPU engine when no
OpenCL device is found.
cmake -S . -B build -DUSE_OPENCL=ON -DNO_GUI=ON -DCMAKE_BUILD_TYPE=Release
cmake --build build --parallelNVIDIA CUDA (peak throughput on NVIDIA; requires CUDA Toolkit 12.x). This is
the default back-end when no -DUSE_* flag is given:
cmake -S . -B build -DNO_GUI=ON -DCMAKE_BUILD_TYPE=Release
cmake --build build --parallelAMD ROCm / HIP (requires ROCm 6.x):
cmake -S . -B build -DUSE_HIP=ON -DNO_GUI=ON -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_HIP_COMPILER=/opt/rocm/bin/amdclang++ -DCMAKE_PREFIX_PATH=/opt/rocm
cmake --build build --parallelGPU targets default to common RDNA/CDNA architectures; override with
-DCMAKE_HIP_ARCHITECTURES="gfx1100;gfx1030".
Output: bin/dmrcrack. The three GPU back-ends are mutually exclusive
(priority HIP > OpenCL > CUDA).
Open an x64 Native Tools Command Prompt for VS and run:
build.batOutput: bin\dmrcrack.exe. The script auto-detects Visual Studio via vswhere.exe (preferring the CUDA-supported v143 toolset even on VS 2026). Targets sm_75/86/89/120 natively — including the RTX 50-series (Blackwell) — with a compute_89 PTX fallback for other GPUs (JIT-compiled on first run).
build_cli.bat # → bin\dmrcrack-cli.exe (NVIDIA CUDA, default)
build_cli.bat opencl # → bin\dmrcrack-cli-cl.exe (portable OpenCL)
build_cli.bat cpu # → bin\dmrcrack-cli-cpu.exe (CPU-only, no toolkit)build_tests.bat # build all host tests (or: strict | canonical | hytera | silence | dsp)- Install Inno Setup
- Open
installer\FSP.DMRCrack.iss - Build
FSP.DMRCrack/
src/
main.c WinMain entry point (Windows GUI)
gui.c Win32 GUI, dark theme, progress graphs
cli.c Headless CLI entry point (Linux / NO_GUI builds)
bruteforce.cu CUDA/HIP GPU kernels + CPU fallback
bruteforce_cl.cpp OpenCL host engine (-DUSE_OPENCL) + CPU fallback
dmrcrack.cl OpenCL kernels (ported 1:1 from bruteforce.cu)
bruteforce.c CPU-only build path (used by test tools)
rc4.c RC4 KSA + PRGA, host-side
payload_io.c .bin loader/saver, ALG/KID/MI metadata parser
lang.c / lang_en.c / lang_es.c i18n string tables
updater.c WinSparkle auto-update integration
include/
platform.h Win32/POSIX abstraction (threads, atomics, timing)
gpu_compat.h CUDA/HIP compatibility shim
bruteforce.h Engine API and BruteforceEngine struct
lang.h / version.h / payload_io.h / updater.h
src/
test_strict_score.c Per-burst scoring validation against known key
test_bench.cu GPU kernel throughput micro-benchmark
tools/
dsd-fme.exe DSD-FME demodulator (Cygwin DLLs required alongside)
dsdfme_dsp_to_bin.py DSD-FME DSP output → .bin converter
verify_decrypt.py Key validation with Z-score output
diag_decrypt.py Decryption pipeline diagnostic
debian/ Debian packaging (control, rules, changelog, copyright)
completions/
dmrcrack.bash bash completion (installed as bash-completion/completions/dmrcrack)
man/
dmrcrack.1 Man page
installer/
FSP.DMRCrack.iss Inno Setup script
CMakeLists.txt Cross-platform build (Linux + Windows)
build.bat Windows batch build (auto-detects VS + CUDA)
Dockerfile Multi-stage OpenCL build on a Debian/Kali base
bin/ Compiled output (not tracked in git)
PRs are welcome. The issue tracker has tagged issues if you want somewhere to start:
good first issue— well-scoped tasks: magic-number cleanup, i18n audit, test coveragehelp wanted— bigger items that need more familiarity with the codebase
Build setup, code style, and PR guidelines are in CONTRIBUTING.md.
FSP.DMRCrack is a security-auditing and research tool. It exists so that radio operators, security researchers, and CTF participants can assess the strength of DMR Enhanced Privacy on systems they own or are explicitly authorized in writing to test.
By downloading, building, or running this software you agree that:
- You will use it only against radio communications you own or have explicit, documented permission to audit.
- Unauthorized interception, decryption, or disclosure of radio communications is illegal in most jurisdictions (e.g. the U.S. Wiretap Act / 47 U.S.C. § 605, the U.K. Investigatory Powers Act, and equivalent laws worldwide) and may carry serious criminal and civil penalties.
- All responsibility and liability for how you use this tool rests entirely with you. The authors and contributors accept no liability for misuse or for any damage, loss, or legal consequence arising from its use.
- The software is provided "as is", without warranty of any kind, as set out in the GPLv3.
If you are not certain you are legally authorized to analyze a given transmission, do not use this tool on it. When in doubt, don't.
FSP.DMRCrack is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License version 3 as published by the Free Software Foundation. See LICENSE for the full text.
DSD-FME (required companion tool, distributed in tools/) is licensed under ISC + GPLv2. See NOTICE. The Cygwin runtime DLLs bundled alongside DSD-FME are LGPL-licensed.