Skip to main content

ScanCrypt — get back the data the ransomware never touched

License: Apache 2.0 CI

Most ransomware is in a race: encrypting terabytes takes hours, so to finish before it's caught it only scrambles part of each large file — the first chunk, or stripes through it — then renames it so everything looks equally dead. It usually isn't.

ScanCrypt scans an encrypted file or disk, measures exactly which bytes were never actually encrypted, and pulls those bytes back out — no decryption key, no ransom. It is not a decryptor; it's a ransomware-aware partial-recovery tool. Databases, VM disks, and backup archives are typically mostly intact underneath.

Free and open source (Apache-2.0), read-only, by IronSights · scancrypt.org · Plain-English guide for victims

Honest by design. Recoverability is always reported as most, not all, with the measured percentage. A partial file list is flagged as partial, never passed off as complete. Family IDs are labelled validated vs from public reporting. Fully-encrypted and small files are out of scope. Provided AS IS, no warranty; use only on systems you are authorised to examine.


Install

Just want to run it? Download the app from the releases pagescancrypt-gui.exe (Windows) is a single portable file, nothing to install, fully offline. No terminal needed. New to this? Read the plain-English guide.

Windows SmartScreen / Defender note: the project holds a DigiCert OV code signing certificate (signing key in an Azure Key Vault HSM — see the signing & privacy policy). v1.0.0 shipped unsigned; from v1.0.1 the Windows exes are code-signed. Even when signed, SmartScreen may still show "Windows protected your PC" on a new release until download reputation builds — click More info → Run anyway. On macOS, right-click the app and choose Open. Every release is built automatically from this public source by GitHub Actions, and every asset ships with a .sha256 checksum on the release page so you can verify what you downloaded.

From source (any OS):

python3 -m venv .venv
source .venv/bin/activate            # Windows: .venv\Scripts\activate
pip install -e ".[ntfs]"             # ".[ntfs]" adds VHDX/VHD/VMDK + NTFS support
scancrypt --help                     # or:  python -m rprt --help

dissect.hypervisor + dissect.ntfs (pulled in by [ntfs]) are what let ScanCrypt read files out of a virtual disk. Everything else works without them.


Quickstart

1. How much of a file/disk is recoverable?

scancrypt "SQL_DATA_D.vhdx"
size        108.5 GB
pattern     front-only
recoverable 100.0%
encrypted   0.0002%   258 KB at the front
family      Makop / Phobos  (validated)

Add --report triage.html for a shareable HTML report, --json out.json for machine output. Scans stay fast even on huge disks — a 322 GB VM images in seconds, because finding the encryption boundary doesn't require reading the whole file.

2. Recover files from a virtual disk (the headline workflow)

Ransomware often encrypts a VM disk's header, so it won't mount. ScanCrypt rebuilds the disk from the block map that survived and reads the files straight out — names and folders intact.

scancrypt "SQL_DATA_D.vhdx" --list-volume            # see what's inside
scancrypt "SQL_DATA_D.vhdx" --recover-files ./out    # copy the files out

Recover only specific files (near-instant, no full walk):

printf '/Program Files/.../DATA/production.mdf\n' > paths.txt
scancrypt "SQL_DATA_D.vhdx" --recover-files ./out --only-paths paths.txt

If part of the disk didn't survive, the file list says so (… (partial)) instead of pretending it's complete.

3. Check a recovered SQL Server database

scancrypt recovered.mdf --validate-sql
253,478 valid SQL Server page(s)  (90.6%)   verdict: sql-data-present
database name: production_db

A page-level integrity check (a structural analogue to DBCC), so you know what you got back before handing it to a DBA.

4. Triage a whole share at once

scancrypt /mnt/encrypted_share --report incident.html --csv incident.csv

One incident-wide figure — "across N files totalling X TB, this fraction is recoverable for free" — with a per-file breakdown for a client or insurer.

5. Extract the intact bytes of a single large file

scancrypt victim.bin --extract recovered.bin

Common options

Flag What it does
--report FILE standalone HTML triage report (add --hash to embed a SHA-256)
--json FILE full machine-readable report
--list-volume list every file in a virtual disk's NTFS volume
--recover-files DIR recover files from a VHDX/VHD/VMDK (rebuilds an encrypted-header disk)
--only-paths FILE with --recover-files, restrict to listed paths
--validate-sql page-level check of a recovered SQL Server MDF/NDF
--fingerprint emit a privacy-safe family signature stub + pre-filled issue link (no file contents)
--extract FILE write the intact byte ranges of a single file
--carve DIR carve loose files from the recoverable region (needs PhotoRec)
--boundary-only accept the fast front-boundary result; never do a full-disk read
--full force a full block-by-block scan (precise map, reads the whole file)
--audit-log FILE hash-chained, tamper-evident audit trail (+ --case-id, --examiner, --evidence-id)

Scan a raw disk in place (Windows, elevated prompt): scancrypt \\.\PhysicalDrive1 --json triage.json

Evidence-grade run and later verification:

scancrypt disk.img --extract out.bin --audit-log audit.jsonl \
    --case-id CASE-0001 --examiner "A. Analyst" --evidence-id DISK-01
python -c "from rprt import forensics; print(forensics.verify_log('audit.jsonl'))"

How it works (four read-only stages)

  1. Map the encryption. An entropy scan brackets where the encryption starts and stops, then binary-searches down to the byte. It stays cheap on huge disks and only escalates to a full read when the evidence points to a genuine second encrypted region — not to the scattered high-entropy blocks (databases, compressed content) that are normal on any disk.
  2. Tell ciphertext from compression. Encrypted and compressed data both look random; a chi-square test plus archive-header checks separate real ciphertext from an ordinary zip, image, or database blob, so recoverable data isn't written off.
  3. Report the number. A recoverable percentage, an entropy map, the strain, and the limits stated plainly — per file, or rolled up across a whole share.
  4. Recover. Extract intact byte ranges; pull files out of a virtual disk (even one whose header was destroyed); validate a recovered SQL database; carve loose files. Hashes are recorded throughout.

Recovery is family-agnostic — a wrong or unknown family guess never affects what comes back; identification only names the strain and sets expectations. Validated families (matched against real samples) vs public-reporting-only ones are labelled as such.


Honest limits

  • Not decryption — it recovers bytes that were never encrypted; the rest stays locked.
  • Recovery is most, not all; the report gives a measured figure, not a promise every file opens.
  • Small files are usually encrypted end-to-end. The value is in big files: databases, VM disks, backups, media.
  • Periodic/intermittent patterns recover less cleanly than front-only.
  • No warranty, no liability. Authorised systems only.

For developers

Dev setup

python3 -m venv .venv && source .venv/bin/activate   # Windows: .venv\Scripts\activate
pip install -e ".[dev]"
pytest

Run the GUI locally (works on macOS/Linux for development): python -m rprt.gui

Build the Windows app

Must run on Windows (PyInstaller doesn't cross-compile):

python -m venv .venv; .venv\Scripts\activate
pip install -e ".[dev]"
python build_scripts\build_windows.py     # -> dist\rprt-gui.exe (single file, no installer)

CI runs the suite on Ubuntu + Windows on every push and builds rprt-gui.exe; pushing a v* tag attaches it to a GitHub release.

Module map

Module Responsibility
engine.py core scan / classify / boundary-search / extract
stats.py chi-square randomness test (encrypted vs compressed)
signatures.py · ransomnote.py ransomware fingerprinting from extension/footer and from ransom notes
formats.py container/filesystem detection on the recoverable region (VHDX, ZIP/OOXML, NTFS/FAT, …)
ntfs.py read files out of an NTFS volume inside a partially-encrypted / header-encrypted virtual disk
sqlpages.py page-level SQL Server MDF/NDF recovery-quality check
carve.py orchestrates PhotoRec over the recoverable region
batch.py incident-wide directory triage + rollup
report.py standalone HTML triage report (inline CSS + SVG entropy map)
forensics.py before/after integrity proof + hash-chained audit log + case metadata
source.py read-only input abstraction (files, images, raw Windows devices)
gui.py · cli.py PySide6 desktop app · command-line entry point

Help ScanCrypt recognise a strain it doesn't name yet

Point it at one encrypted file:

scancrypt "somefile.newcrypt" --fingerprint

It prints a privacy-safe stub — extension, the family's trailing magic-candidate bytes, the encryption pattern, and any nearby ransom note — as a ready-to-paste signatures.yaml block and a pre-filled GitHub issue link. It reads no file contents, so a victim can submit safely. (In the app: Help improve ScanCrypt… after a scan.)

Contributions welcome — especially new verified family signatures (see CONTRIBUTING.md).


ScanCrypt does not break, weaken, or bypass cryptography, and it does not recover fully-encrypted data. Need an incident handled end to end — full extraction, database rebuilds, forensic reporting? IronSights does that as a paid engagement; the tool stays free.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

scancrypt-1.0.1.tar.gz (150.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

scancrypt-1.0.1-py3-none-any.whl (123.1 kB view details)

Uploaded Python 3

File details

Details for the file scancrypt-1.0.1.tar.gz.

File metadata

  • Download URL: scancrypt-1.0.1.tar.gz
  • Upload date:
  • Size: 150.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for scancrypt-1.0.1.tar.gz
Algorithm Hash digest
SHA256 cbc0874fa812792e10b264a5d77e15bbb72db16609b9d4488328357670327ecc
MD5 2c366c5717040510b63dba0d9f1f2aa8
BLAKE2b-256 4af1c508b4f5494723ccaa21d3540977731bc40d61333324141afbf867294069

See more details on using hashes here.

Provenance

The following attestation bundles were made for scancrypt-1.0.1.tar.gz:

Publisher: publish.yml on ironsightscyber/scancrypt

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file scancrypt-1.0.1-py3-none-any.whl.

File metadata

  • Download URL: scancrypt-1.0.1-py3-none-any.whl
  • Upload date:
  • Size: 123.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for scancrypt-1.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 ca0c13b0a6c620885f2818f792d3eb7782f849d2d309eb8f16549df1688ae1d6
MD5 ea1573bfb5eff892704e00ba80468005
BLAKE2b-256 8cd2fe9b925fbb45693fe1dfb61f1558daf777491b3d2794cba18f169e270778

See more details on using hashes here.

Provenance

The following attestation bundles were made for scancrypt-1.0.1-py3-none-any.whl:

Publisher: publish.yml on ironsightscyber/scancrypt

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

1.1.0

2 files

This release

1.0.1 This release

2 files

1.0.0

2 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