DICOM recon toolkit — SCU clients, SCP server, and security assessment utilities
Project description
dicomrecon
A Python toolkit for interacting with and testing DICOM services. Provides SCU clients (C-ECHO, C-STORE, C-FIND, C-MOVE, C-GET), a configurable multi-service SCP server, and a suite of security and compliance testing utilities built on pynetdicom.
Use only on systems you own or have explicit written authorisation to test.
Installation
pip install dicomrecon
Python 3.12+ is required.
Compatibility note (2026-03-31): Python 3.13 is supported for pure-Python usage (data generation, fuzzing, SCP/SCU configuration). However, pynetdicom ≥ 2.1.0 has known issues with the networking layer under Python 3.13 that can cause hangs or unexpected association failures during live DICOM operations (C-ECHO, C-STORE, C-FIND, etc.). Python 3.12 is recommended for all network-dependent workflows until pynetdicom publishes a 3.13-verified release.
CLI quick-start
# Verify connectivity
dicomrecon ping PACS01@192.168.1.10:11112
# Query for all studies
dicomrecon find 192.168.1.10:11112
# Send a DICOM file
dicomrecon store 192.168.1.10:11112 scan.dcm
# Run a local SCP server
dicomrecon scp --port 11112 --store-dir ./received
# Discover DICOM services on a subnet
dicomrecon discover 192.168.1.0/24
All commands support --help for full option listings.
Commands
Standard DICOM
| Command | Description |
|---|---|
ping |
C-ECHO — verify AE connectivity |
store |
C-STORE — send DICOM files to a Storage SCP |
find |
C-FIND — query a PACS or Modality Worklist |
move |
C-MOVE — request a PACS to push instances to an AE |
get |
C-GET — retrieve instances directly from a PACS |
scp |
Run a multi-service DICOM SCP server |
Security / Compliance Testing
| Command | Description |
|---|---|
discover |
Scan a subnet for DICOM services via C-ECHO probing |
aetbrute |
Brute-force called/calling AE title acceptance |
dump |
Hierarchical C-FIND walk: Patient → Study → Series → Image |
exfil |
Enumerate all studies and retrieve via C-GET |
fuzz |
C-STORE fuzzer — send malformed datasets and log responses |
simulate |
Rogue SCP pre-loaded with synthetic patient data |
storereject |
SCP that rejects C-STORE with configurable status codes |
wlpoison |
Modality Worklist SCP serving poisoned worklist items |
Target syntax
[CALLED_AET@]host[:port]
Examples:
192.168.1.10
192.168.1.10:11112
PACS01@192.168.1.10
PACS01@192.168.1.10:11112
Port defaults to 104. Called AE title defaults to ANY-SCP.
Python API
from dicomrecon.target import parse_target
from dicomrecon.scu.echo import c_echo
from dicomrecon.scu.find import c_find
from dicomrecon.scp.server import DicomSCP
target = parse_target("PACS01@192.168.1.10:11112", calling_aet="MYTOOL")
# C-ECHO
ok = c_echo(target)
# C-FIND
results = c_find(target, level="study", filters={"PatientID": "12345"})
for ds in results:
print(ds.StudyInstanceUID, ds.StudyDate)
# Run an SCP
scp = DicomSCP(ae_title="TESTSCP", port=11112)
scp.enable_worklist = True
scp.load_worklist("worklist.json")
scp.start() # blocks; Ctrl-C to stop
Synthetic data & fuzzing
from dicomrecon.pentest.generator import generate_dataset, make_worklist
from dicomrecon.pentest.fuzzer import generate_fuzz_cases
# 10 patients × 2 studies × 2 series × 3 instances
instances = generate_dataset(n_patients=10, modalities=["US", "CT"])
# Synthetic Modality Worklist items
worklist = make_worklist(20, modalities=["US"])
# ~100 malformed DICOM datasets for C-STORE fuzzing
cases = generate_fuzz_cases()
for case in cases:
print(case._fuzz_label)
Development
git clone https://github.com/Ben-ODea/dicomrecon.git
cd dicomrecon
python -m venv .venv && source .venv/bin/activate
pip install -e .
pytest tests/
License
Copyright 2026 Ben-ODea
Licensed under the Apache License, Version 2.0. See LICENSE for the full text.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file dicomrecon-0.1.0.tar.gz.
File metadata
- Download URL: dicomrecon-0.1.0.tar.gz
- Upload date:
- Size: 49.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
993cf3f3a91a9d615986bb6ccd5a76e74335a8ca3bcae323cc5983e7a38ff15c
|
|
| MD5 |
b6d300a650536ba58c146616d2713676
|
|
| BLAKE2b-256 |
ff6de758a55ebbb26adce4fc05584f3cc51746aa7dbdfbe265d59b5797a662c2
|
File details
Details for the file dicomrecon-0.1.0-py3-none-any.whl.
File metadata
- Download URL: dicomrecon-0.1.0-py3-none-any.whl
- Upload date:
- Size: 61.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6d863cb76fa1ea1bede8d6d1ba08f1219951b9073b4bac5d013591246f8d28cd
|
|
| MD5 |
a5e4d193c16f294e3ccef88397224afd
|
|
| BLAKE2b-256 |
5e9a9b122c7332cb4b17f679679dec7293aaf05a7020730a57dfb8299f77c06a
|