
Analyzing Ransomware Encryption Mechanisms
- 259 installs
- 27.3k repo stars
- Updated August 2, 2026
- mukul975/anthropic-cybersecurity-skills
analyzing-ransomware-encryption-mechanisms is an agent skill that analyzes ransomware encryption behavior to inform security decisions.
About
analyzing-ransomware-encryption-mechanisms is an agent skill from the Anthropic cybersecurity skills lineage that guides systematic analysis of how ransomware families implement encryption—keys, modes, file targeting, and operational constraints—so you can reason about blast radius and controls. Solo builders with security responsibilities, indie SaaS operators handling customer data, or small teams doing threat-informed design use it during security reviews, tabletop exercises, or post-incident learning—not for everyday feature work. The public Prism excerpt is predominantly license text, so invoke details should be confirmed in the full SKILL.md before autonomous runs. Treat outputs as analytical hypotheses that must be validated against samples, logs, and your environment. The skill advances Ship-phase security depth by translating encryption behavior into actionable detection and backup priorities without replacing professional incident response.
- Focuses on ransomware encryption mechanisms rather than generic malware trivia
- Fits security review and incident-readiness workflows for agent-assisted analysis
- Distributed under Apache License 2.0 per bundled license text
- Pairs with Anthropic cybersecurity skills catalog patterns for structured agent procedures
- Supports defenders mapping crypto behavior to detection and recovery playbooks
Analyzing Ransomware Encryption Mechanisms by the numbers
- 259 all-time installs (skills.sh)
- +15 installs in the week ending Aug 4, 2026 (Skillselion tracking)
- Ranked #670 of 2,203 Security skills by installs in the Skillselion catalog
- Security screen: LOW risk (skills.sh audit)
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/mukul975/anthropic-cybersecurity-skills --skill analyzing-ransomware-encryption-mechanismsAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 259 |
|---|---|
| repo stars | ★ 27.3k |
| Security audit | 3 / 3 scanners passed |
| Last updated | August 2, 2026 |
| Repository | mukul975/anthropic-cybersecurity-skills ↗ |
What it does
Analyze how ransomware implements encryption so you can assess impact, detection gaps, and defensive priorities before or after an incident.
Who is it for?
Best when you're doing threat-informed security reviews or studying ransomware crypto behavior with agent assistance.
Skip if: Casual projects with no security surface, legal constraints on malware handling, or teams wanting quick marketing copy instead of technical analysis.
When should I use this skill?
You need structured agent assistance analyzing ransomware encryption design, key handling, or file-targeting behavior.
What you get
You get a structured encryption-mechanism analysis you can map to monitoring rules, backup scope, and containment steps before wider exposure.
- Encryption mechanism breakdown
- Defense-oriented notes linking crypto behavior to detection and recovery actions
Files
Analyzing Ransomware Encryption Mechanisms
When to Use
- A ransomware infection has occurred and recovery requires understanding the encryption scheme used
- Assessing whether decryption is possible without paying the ransom (implementation flaws, known decryptors)
- Reverse engineering ransomware to identify the encryption algorithm, key derivation, and key storage mechanism
- Developing a decryptor tool when a weakness in the ransomware's cryptographic implementation is identified
- Classifying a ransomware sample by its encryption approach to attribute it to a known family
Do not use for production data recovery operations without first verifying the decryption method on test copies of encrypted files.
Prerequisites
- Ghidra or IDA Pro for reverse engineering the ransomware binary
- Python 3.8+ with
pycryptodomelibrary for testing encryption/decryption routines - Sample encrypted files and their corresponding plaintext originals (known-plaintext pairs)
- Access to the ransomware binary (unpacked if applicable)
- Familiarity with symmetric (AES, ChaCha20) and asymmetric (RSA) cryptographic algorithms
- NoMoreRansom.org database for checking existing free decryptors
Workflow
Step 1: Identify the Encryption Algorithm
Determine which cryptographic algorithm the ransomware uses:
# Check for Windows Crypto API usage in imports
import pefile
pe = pefile.PE("ransomware.exe")
crypto_apis = {
"CryptAcquireContextA": "Windows CryptoAPI",
"CryptAcquireContextW": "Windows CryptoAPI",
"CryptGenKey": "Windows CryptoAPI key generation",
"CryptEncrypt": "Windows CryptoAPI encryption",
"CryptImportKey": "Windows CryptoAPI key import",
"BCryptOpenAlgorithmProvider": "Windows CNG (modern crypto)",
"BCryptEncrypt": "Windows CNG encryption",
"BCryptGenerateKeyPair": "Windows CNG asymmetric key gen",
}
print("Crypto API Imports:")
for entry in pe.DIRECTORY_ENTRY_IMPORT:
for imp in entry.imports:
if imp.name and imp.name.decode() in crypto_apis:
print(f" {entry.dll.decode()} -> {imp.name.decode()}: {crypto_apis[imp.name.decode()]}")Common Ransomware Encryption Schemes:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
AES-256-CBC + RSA-2048: Most common hybrid scheme (LockBit, REvil, Conti)
AES-256-CTR + RSA-4096: Stream cipher mode variant (BlackCat/ALPHV)
ChaCha20 + RSA-4096: Modern stream cipher (Hive, Royal)
Salsa20 + ECDH: Curve25519 key exchange (Babuk)
AES-128-ECB: Weak mode - potential decryption via known-plaintext
XOR-only: Trivial encryption - always recoverable
Custom algorithm: Often contains implementation flawsStep 2: Analyze Key Generation and Management
Reverse engineer how encryption keys are generated and stored:
Key Management Patterns in Ransomware:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
1. STRONG (no recovery possible without key):
- Per-file AES key generated with CryptGenRandom
- AES key encrypted with embedded RSA public key
- Encrypted key appended to each file or stored separately
- RSA private key held only by attacker's C2 server
2. WEAK (potential recovery):
- AES key derived from predictable seed (timestamp, PID)
- Same AES key used for all files (single key compromise = full recovery)
- Key transmitted to C2 before encryption starts (PCAP may contain key)
- XOR with short repeating key (brute-forceable)
- PRNG seeded with GetTickCount or time() (limited keyspace)
3. FLAWED IMPLEMENTATION:
- ECB mode (preserves plaintext patterns)
- Initialization vector (IV) reuse across files
- Key stored in plaintext in memory (recoverable from memory dump)
- Partial encryption (only first N bytes encrypted)Step 3: Examine File Encryption Routine
Reverse engineer the file processing logic:
// Typical ransomware file encryption flow (decompiled pseudo-code from Ghidra):
void encrypt_file(char *filepath) {
// 1. Check file extension against target list
if (!is_target_extension(filepath)) return;
// 2. Generate per-file AES key (32 bytes for AES-256)
BYTE aes_key[32];
CryptGenRandom(hProv, 32, aes_key);
// 3. Generate random IV (16 bytes)
BYTE iv[16];
CryptGenRandom(hProv, 16, iv);
// 4. Read file contents
HANDLE hFile = CreateFile(filepath, GENERIC_READ, ...);
BYTE *plaintext = read_entire_file(hFile);
// 5. Encrypt with AES-256-CBC
aes_cbc_encrypt(plaintext, file_size, aes_key, iv);
// 6. Encrypt AES key with RSA public key
BYTE encrypted_key[256]; // RSA-2048 output
rsa_encrypt(aes_key, 32, rsa_pubkey, encrypted_key);
// 7. Write: encrypted_data + encrypted_key + IV to file
write_file(filepath, encrypted_data, encrypted_key, iv);
// 8. Rename file with ransomware extension
rename_file(filepath, strcat(filepath, ".locked"));
}Step 4: Check for Cryptographic Weaknesses
Test the implementation for exploitable flaws:
from Crypto.Cipher import AES
import os
import struct
# Test 1: Check if same key is used for multiple files
# Compare encrypted versions of known files
def check_key_reuse(file1_enc, file2_enc):
with open(file1_enc, "rb") as f:
data1 = f.read()
with open(file2_enc, "rb") as f:
data2 = f.read()
# Extract IVs (location depends on ransomware family)
# If IVs are same and files share encrypted blocks -> same key
iv1 = data1[-16:] # Example: IV at end
iv2 = data2[-16:]
if iv1 == iv2:
print("[!] Same IV detected - key reuse likely")
# Test 2: Check for predictable key derivation
# If key is derived from timestamp, iterate possible values
def brute_force_timestamp_key(encrypted_file, known_header, timestamp_range):
with open(encrypted_file, "rb") as f:
encrypted_data = f.read()
for ts in timestamp_range:
# Derive key the same way ransomware does
import hashlib
key = hashlib.sha256(str(ts).encode()).digest()
iv = encrypted_data[-16:]
cipher = AES.new(key, AES.MODE_CBC, iv)
decrypted = cipher.decrypt(encrypted_data[:16])
if decrypted[:len(known_header)] == known_header:
print(f"[!] Key found! Timestamp: {ts}")
return key
return None
# Test 3: Check for ECB mode (pattern preservation)
def check_ecb_mode(encrypted_file):
with open(encrypted_file, "rb") as f:
data = f.read()
# ECB produces identical ciphertext for identical plaintext blocks
blocks = [data[i:i+16] for i in range(0, len(data), 16)]
unique = len(set(blocks))
total = len(blocks)
if unique < total * 0.95:
print(f"[!] ECB mode likely: {total-unique} duplicate blocks out of {total}")Step 5: Attempt Key Recovery
Use identified weaknesses for key recovery:
# Recovery Method 1: Extract key from memory dump
# Volatility plugin to scan for AES key schedules
# vol3 -f memory.dmp windows.yarascan --yara-rule "aes_key_schedule"
# Recovery Method 2: Known-plaintext attack (weak algorithms)
def xor_key_recovery(encrypted_file, known_plaintext):
"""Recover XOR key from known plaintext-ciphertext pair"""
with open(encrypted_file, "rb") as f:
ciphertext = f.read()
key = bytes(c ^ p for c, p in zip(ciphertext, known_plaintext))
# Find repeating key length
for key_len in range(1, 256):
candidate = key[:key_len]
if all(key[i] == candidate[i % key_len] for i in range(min(len(key), key_len * 4))):
print(f"XOR key (length {key_len}): {candidate.hex()}")
return candidate
return None
# Recovery Method 3: Check NoMoreRansom for existing decryptors
# https://www.nomoreransom.org/en/decryption-tools.htmlStep 6: Document Encryption Analysis
Compile findings into a structured report:
Analysis should document:
- Algorithm identified (AES, RSA, ChaCha20, custom)
- Key size and mode of operation (CBC, CTR, ECB, GCM)
- Key generation method (CSPRNG, predictable seed, static key)
- Key storage location (appended to file, registry, C2 transmission)
- File modification pattern (full encryption, partial, header-only)
- Targeted file extensions
- Ransom note format and payment infrastructure
- Decryption feasibility assessment (possible/impossible/partial)
- Recommended recovery approachKey Concepts
| Term | Definition |
|---|---|
| Hybrid Encryption | Combining symmetric (AES) for fast file encryption with asymmetric (RSA) for secure key wrapping; the standard ransomware approach |
| Key Wrapping | Encrypting the per-file symmetric key with the attacker's RSA public key so only the attacker's private key can decrypt it |
| ECB Mode | Electronic Codebook mode encrypts each block independently; preserves patterns in plaintext, a critical weakness enabling partial recovery |
| Known-Plaintext Attack | Using a known original file and its encrypted version to derive the encryption key; effective against XOR and weak stream ciphers |
| Key Schedule | The expanded form of an AES key in memory; scannable in memory dumps to recover encryption keys before they are erased |
| CSPRNG | Cryptographically Secure Pseudo-Random Number Generator; ransomware using CryptGenRandom produces unpredictable keys |
| Partial Encryption | Some ransomware only encrypts the first N bytes or every Nth block for speed; unencrypted portions may aid recovery |
Tools & Systems
- Ghidra: Reverse engineering suite for analyzing ransomware encryption routines at the assembly level
- PyCryptodome: Python cryptographic library for implementing and testing decryption routines
- NoMoreRansom.org: Free decryption tool repository maintained by Europol and security vendors for known ransomware families
- Volatility: Memory forensics framework for extracting encryption keys from RAM dumps of infected systems
- CryptoTester: Tool for identifying cryptographic algorithms based on constants and code patterns
Common Scenarios
Scenario: Assessing Decryption Feasibility for a Ransomware Incident
Context: An organization is hit with ransomware encrypting file servers. Management needs to know if decryption is possible without paying the ransom before making a recovery decision.
Approach: 1. Identify the ransomware family from ransom note, file extension, and sample hash (check ID Ransomware) 2. Check NoMoreRansom.org for existing free decryptors for this family 3. Reverse engineer the encryption routine in Ghidra to identify the algorithm and key management 4. Test for implementation weaknesses (key reuse, predictable seeds, ECB mode) 5. Check if PCAP from the incident captured the key transmission to C2 (if key was sent before encryption) 6. Scan memory dumps from affected machines for AES key schedules in RAM 7. Report findings: decryption possible/impossible with specific technical justification
Pitfalls:
- Testing decryption methods on the only copy of encrypted files (always work on copies)
- Assuming all files use the same key without verifying (some ransomware uses per-file keys)
- Not checking for volume shadow copies (vssadmin) which ransomware may have failed to delete
- Confusing the file encryption algorithm with the key wrapping algorithm in reports
Output Format
RANSOMWARE ENCRYPTION ANALYSIS
================================
Sample: lockbit3.exe
Family: LockBit 3.0 / LockBit Black
SHA-256: abc123def456...
ENCRYPTION SCHEME
File Cipher: AES-256-CTR (per-file unique key)
Key Wrapping: RSA-2048 (public key embedded in binary)
Key Generation: CryptGenRandom (CSPRNG - unpredictable)
IV Generation: Random 16 bytes per file
File Structure: [encrypted_data][rsa_encrypted_key(256B)][iv(16B)][magic(8B)]
TARGETED EXTENSIONS
Total: 412 extensions targeted
Categories: Documents (.doc, .xls, .pdf), Databases (.sql, .mdb),
Archives (.zip, .7z), Source code (.py, .java, .cs)
Excluded: .exe, .dll, .sys, .lnk (system files preserved)
IMPLEMENTATION ANALYSIS
Key Strength: STRONG - per-file random keys, no reuse
Mode Security: STRONG - CTR mode with unique nonces
Key Storage: RSA-encrypted key appended to each file
Shadow Copies: Deleted via vssadmin and WMI
DECRYPTION FEASIBILITY
Without Key: NOT POSSIBLE
- No implementation flaws identified
- RSA-2048 key wrapping prevents brute force
- CSPRNG prevents key prediction
- No existing free decryptor available
RECOVERY OPTIONS
1. Restore from offline backups (recommended)
2. Check for volume shadow copies (low probability - ransomware deletes them)
3. Memory forensics if machine was not rebooted (key may persist in RAM)
4. Negotiate with attacker (last resort - no guarantee of decryption)
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to the Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by the Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding any notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. Please do not remove or change
the license header comment from a contributed file except when
necessary.
Copyright 2026 mukul975
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
API Reference: Ransomware Encryption Mechanism Analysis
PyCryptodome - Encryption Testing
AES Decryption
from Crypto.Cipher import AES
# AES-CBC
cipher = AES.new(key, AES.MODE_CBC, iv)
plaintext = cipher.decrypt(ciphertext)
# AES-CTR
cipher = AES.new(key, AES.MODE_CTR, nonce=nonce)
plaintext = cipher.decrypt(ciphertext)
# AES-ECB (weak mode used by some ransomware)
cipher = AES.new(key, AES.MODE_ECB)
plaintext = cipher.decrypt(ciphertext)ChaCha20 Decryption
from Crypto.Cipher import ChaCha20
cipher = ChaCha20.new(key=key, nonce=nonce)
plaintext = cipher.decrypt(ciphertext)RSA Key Analysis
from Crypto.PublicKey import RSA
key = RSA.import_key(open("pubkey.pem").read())
print(f"Key size: {key.size_in_bits()} bits")
print(f"Modulus (n): {key.n}")
print(f"Exponent (e): {key.e}")pefile - Crypto API Import Detection
Syntax
import pefile
pe = pefile.PE("ransomware.exe")
for entry in pe.DIRECTORY_ENTRY_IMPORT:
for imp in entry.imports:
print(f"{entry.dll.decode()} -> {imp.name}")Key Windows Crypto APIs
| API | Purpose |
|---|---|
CryptAcquireContext | Initialize crypto provider |
CryptGenRandom | CSPRNG random bytes |
CryptGenKey | Generate symmetric key |
CryptEncrypt | Encrypt data via CryptoAPI |
CryptImportKey | Import key blob |
BCryptOpenAlgorithmProvider | CNG algorithm handle |
BCryptEncrypt | CNG encryption |
BCryptGenerateKeyPair | CNG asymmetric keygen |
Volatility 3 - Key Recovery from Memory
Syntax
vol3 -f memory.dmp windows.yarascan --yara-rule "aes_key"
vol3 -f memory.dmp windows.malfind
vol3 -f memory.dmp windows.pslist
vol3 -f memory.dmp windows.handles --pid <PID>AES Key Schedule YARA Rule
rule AES_Key_Schedule {
strings:
$sbox = { 63 7c 77 7b f2 6b 6f c5 30 01 67 2b fe d7 ab 76 }
condition:
$sbox
}Entropy Analysis Thresholds
| Range | Interpretation |
|---|---|
| 0-1 | Empty / uniform data |
| 1-5 | Normal code / plaintext |
| 5-7 | Compressed or obfuscated |
| 7-7.9 | Encrypted (block cipher) |
| 7.9-8.0 | Encrypted (stream cipher / AES-CTR) |
Known Ransomware Encryption Schemes
| Family | File Cipher | Key Wrapping | Weakness |
|---|---|---|---|
| WannaCry | AES-128-CBC | RSA-2048 | Key may persist in memory |
| LockBit 3.0 | AES-256-CTR | RSA-2048 | None known |
| Conti | AES-256-CBC | RSA-4096 | Leaked builder exposes keys |
| REvil | Salsa20 | ECDH | None known |
| STOP/Djvu | AES-256-CFB | RSA-1024 | Offline key variant decryptable |
| Hive | ChaCha20 | RSA-4096 | Master key recovered by FBI |
| BlackCat | AES-256 | RSA-4096 | None known |
| Babuk | ChaCha20 | ECDH (Curve25519) | Leaked source code |
| Akira | ChaCha20 | RSA-4096 | None known |
| Phobos | AES-256-CBC | RSA-1024 | Weak RSA key size |
File Structure Patterns
Common Ransomware File Layout
[encrypted_data][encrypted_aes_key(256B)][iv(16B)][magic_marker(4-8B)]Identifying Appended Metadata
with open("file.locked", "rb") as f:
f.seek(-280, 2) # Seek 280 bytes from end
tail = f.read()
rsa_blob = tail[:256] # RSA-2048 encrypted key
iv = tail[256:272] # AES IV (16 bytes)
marker = tail[272:] # Ransomware magic markerNoMoreRansom / ID Ransomware
Identification
Upload encrypted file + ransom note to:
https://id-ransomware.malwarehunterteam.com/Free Decryptors
Check for available decryptors:
https://www.nomoreransom.org/en/decryption-tools.htmlGhidra - Reverse Engineering Crypto Routines
Crypto Identification Steps
1. Search > For Strings > "AES", "RSA", "Crypt", "encrypt"
2. Search > For Bytes > AES S-Box: 63 7c 77 7b f2 6b
3. Imports > advapi32.dll / bcrypt.dll for Crypto API calls
4. Trace CryptEncrypt xrefs to find encryption routine
5. Identify key buffer size (16=AES-128, 32=AES-256)
6. Check for CryptGenRandom vs time()/GetTickCount seed#!/usr/bin/env python3
"""Ransomware encryption mechanism analysis agent.
Analyzes encryption algorithms, key management, file encryption routines,
and assesses decryption feasibility for ransomware samples and encrypted files.
"""
import os
import sys
import hashlib
import math
import json
from collections import Counter
def compute_hash(filepath):
"""Compute SHA-256 hash of a file."""
sha256 = hashlib.sha256()
with open(filepath, "rb") as f:
for chunk in iter(lambda: f.read(65536), b""):
sha256.update(chunk)
return sha256.hexdigest()
def shannon_entropy(data):
"""Calculate Shannon entropy of byte data."""
if not data:
return 0.0
freq = Counter(data)
length = len(data)
return -sum((c / length) * math.log2(c / length) for c in freq.values())
CRYPTO_CONSTANTS = {
bytes.fromhex("637c777bf26b6fc53001672bfed7ab76"): "AES S-Box (Rijndael)",
bytes.fromhex("52096ad53036a538bf40a39e81f3d7fb"): "AES S-Box (continued)",
bytes.fromhex("6a09e667bb67ae853c6ef372a54ff53a"): "SHA-256 initialization vector",
b"expand 32-byte k": "ChaCha20/Salsa20 constant (256-bit key)",
b"expand 16-byte k": "ChaCha20/Salsa20 constant (128-bit key)",
bytes.fromhex("d1310ba698dfb5ac"): "Blowfish P-array fragment",
}
CRYPTO_API_NAMES = [
b"CryptAcquireContext", b"CryptGenKey", b"CryptEncrypt", b"CryptDecrypt",
b"CryptImportKey", b"CryptExportKey", b"CryptGenRandom", b"CryptDeriveKey",
b"BCryptOpenAlgorithmProvider", b"BCryptEncrypt", b"BCryptGenerateKeyPair",
b"BCryptGenerateSymmetricKey", b"BCryptCreateHash",
b"RtlEncryptMemory", b"RtlDecryptMemory",
]
RANSOMWARE_EXTENSIONS = {
".locked": ["LockBit", "Generic"],
".encrypt": ["Generic"],
".crypt": ["CryptXXX", "Generic"],
".locky": ["Locky"],
".cerber": ["Cerber"],
".zepto": ["Locky variant"],
".odin": ["Locky variant"],
".aesir": ["Locky variant"],
".wncry": ["WannaCry"],
".WNCRY": ["WannaCry"],
".wnry": ["WannaCry"],
".wcry": ["WannaCry"],
".dharma": ["Dharma/CrySiS"],
".basta": ["Black Basta"],
".blackcat": ["BlackCat/ALPHV"],
".hive": ["Hive"],
".royal": ["Royal"],
".rhysida": ["Rhysida"],
".akira": ["Akira"],
".lockbit": ["LockBit 3.0"],
".conti": ["Conti"],
".ryuk": ["Ryuk"],
".maze": ["Maze"],
".revil": ["REvil/Sodinokibi"],
".sodinokibi": ["REvil/Sodinokibi"],
".phobos": ["Phobos"],
".makop": ["Makop"],
".stop": ["STOP/Djvu"],
".djvu": ["STOP/Djvu"],
}
def identify_ransomware_extension(filepath):
"""Identify ransomware family from file extension."""
ext = os.path.splitext(filepath)[1].lower()
if ext in RANSOMWARE_EXTENSIONS:
return {"extension": ext, "families": RANSOMWARE_EXTENSIONS[ext]}
for known_ext, families in RANSOMWARE_EXTENSIONS.items():
if ext.endswith(known_ext):
return {"extension": ext, "families": families}
return {"extension": ext, "families": ["Unknown"]}
def scan_crypto_constants(filepath):
"""Scan binary for known cryptographic constants."""
with open(filepath, "rb") as f:
data = f.read()
findings = []
for const_bytes, description in CRYPTO_CONSTANTS.items():
offset = data.find(const_bytes)
if offset != -1:
findings.append({
"constant": description,
"offset": f"0x{offset:08X}",
"hex": const_bytes[:16].hex(),
})
return findings
def scan_crypto_apis(filepath):
"""Scan binary for Windows Crypto API string references."""
with open(filepath, "rb") as f:
data = f.read()
found = []
for api in CRYPTO_API_NAMES:
if api in data:
found.append(api.decode("ascii", errors="replace"))
return found
def analyze_encrypted_file(filepath):
"""Analyze an encrypted file for ransomware characteristics."""
with open(filepath, "rb") as f:
data = f.read()
file_size = len(data)
entropy = shannon_entropy(data)
# Check for appended metadata (many ransomware families append key material)
tail_256 = data[-256:] if file_size >= 256 else data
tail_entropy = shannon_entropy(tail_256)
# Check for ECB mode (duplicate 16-byte blocks)
blocks_16 = [data[i:i+16] for i in range(0, min(len(data), 65536), 16)]
unique_16 = len(set(blocks_16))
total_16 = len(blocks_16)
ecb_ratio = 1.0 - (unique_16 / total_16) if total_16 > 0 else 0
# Check for partial encryption (low entropy regions)
chunk_size = min(4096, file_size // 4) if file_size > 16 else file_size
first_entropy = shannon_entropy(data[:chunk_size]) if chunk_size > 0 else 0
mid_offset = file_size // 2
mid_entropy = shannon_entropy(data[mid_offset:mid_offset+chunk_size]) if chunk_size > 0 else 0
last_entropy = shannon_entropy(data[-chunk_size:]) if chunk_size > 0 else 0
# Detect magic bytes at tail (ransomware markers)
tail_8 = data[-8:] if file_size >= 8 else data
tail_marker = tail_8.hex() if all(b > 0 for b in tail_8) else None
return {
"file_size": file_size,
"overall_entropy": round(entropy, 4),
"tail_256_entropy": round(tail_entropy, 4),
"ecb_duplicate_ratio": round(ecb_ratio, 4),
"ecb_likely": ecb_ratio > 0.05,
"partial_encryption": {
"first_chunk_entropy": round(first_entropy, 4),
"mid_chunk_entropy": round(mid_entropy, 4),
"last_chunk_entropy": round(last_entropy, 4),
"likely_partial": abs(first_entropy - mid_entropy) > 2.0,
},
"tail_marker_hex": tail_marker,
"fully_encrypted": entropy > 7.5,
}
def xor_key_recovery(encrypted_data, known_plaintext):
"""Attempt XOR key recovery from known plaintext-ciphertext pair."""
if len(known_plaintext) == 0:
return None
key_stream = bytes(c ^ p for c, p in zip(encrypted_data, known_plaintext))
# Detect repeating key
for key_len in range(1, min(256, len(key_stream) // 2)):
candidate = key_stream[:key_len]
match = all(
key_stream[i] == candidate[i % key_len]
for i in range(min(len(key_stream), key_len * 4))
)
if match and key_len < len(key_stream):
return {"key_hex": candidate.hex(), "key_length": key_len, "key_ascii": candidate.decode("ascii", errors="replace")}
return None
def check_file_header_known_plaintext(encrypted_filepath):
"""Check if encrypted file retains known file header (partial encryption indicator)."""
KNOWN_HEADERS = {
b"%PDF": "PDF document",
b"PK\x03\x04": "ZIP/DOCX/XLSX archive",
b"\x89PNG": "PNG image",
b"\xff\xd8\xff": "JPEG image",
b"MZ": "PE executable",
b"\x7fELF": "ELF executable",
b"Rar!": "RAR archive",
b"\xd0\xcf\x11\xe0": "OLE2 (DOC/XLS)",
b"SQLite format 3": "SQLite database",
}
with open(encrypted_filepath, "rb") as f:
header = f.read(16)
for magic, filetype in KNOWN_HEADERS.items():
if header[:len(magic)] == magic:
return {"detected": True, "original_type": filetype,
"note": "File header intact - partial encryption or not encrypted"}
return {"detected": False, "note": "No known file header found - likely fully encrypted from start"}
def assess_decryption_feasibility(crypto_constants, crypto_apis, enc_analysis):
"""Assess decryption feasibility based on analysis results."""
weaknesses = []
strong_points = []
if enc_analysis.get("ecb_likely"):
weaknesses.append("ECB mode detected - block patterns preserved, partial plaintext recovery possible")
if enc_analysis.get("partial_encryption", {}).get("likely_partial"):
weaknesses.append("Partial encryption detected - unencrypted file regions may aid recovery")
if enc_analysis.get("overall_entropy", 8) < 6.0:
weaknesses.append("Low entropy suggests weak or partial encryption")
has_csprng = any("GenRandom" in api for api in crypto_apis)
has_rsa = any("KeyPair" in api or "ImportKey" in api for api in crypto_apis)
has_aes = any("AES" in c.get("constant", "") or "Rijndael" in c.get("constant", "") for c in crypto_constants)
has_chacha = any("ChaCha" in c.get("constant", "") or "Salsa" in c.get("constant", "") for c in crypto_constants)
if has_csprng:
strong_points.append("CSPRNG key generation (CryptGenRandom) - keys not predictable")
if has_rsa:
strong_points.append("RSA key wrapping - per-file keys protected by asymmetric encryption")
if has_aes:
strong_points.append("AES encryption identified")
if has_chacha:
strong_points.append("ChaCha20/Salsa20 stream cipher identified")
if not has_csprng:
weaknesses.append("No CSPRNG detected - key generation may be predictable")
feasibility = "NOT POSSIBLE" if len(strong_points) >= 2 and len(weaknesses) == 0 else \
"POSSIBLE" if len(weaknesses) >= 2 else \
"UNLIKELY - check for specific implementation flaws"
return {
"feasibility": feasibility,
"weaknesses": weaknesses,
"strong_points": strong_points,
"recommendation": "Check NoMoreRansom.org and memory forensics" if feasibility != "NOT POSSIBLE"
else "Restore from backups; no cryptographic weakness found",
}
def generate_report(sample_path=None, encrypted_path=None):
"""Generate full ransomware encryption analysis report."""
report = {"analysis_type": "Ransomware Encryption Mechanism Analysis"}
if sample_path and os.path.exists(sample_path):
report["sample"] = {
"path": sample_path,
"sha256": compute_hash(sample_path),
"size": os.path.getsize(sample_path),
"entropy": round(shannon_entropy(open(sample_path, "rb").read()), 4),
}
report["crypto_constants"] = scan_crypto_constants(sample_path)
report["crypto_apis"] = scan_crypto_apis(sample_path)
if encrypted_path and os.path.exists(encrypted_path):
report["encrypted_file"] = {
"path": encrypted_path,
"sha256": compute_hash(encrypted_path),
"family_match": identify_ransomware_extension(encrypted_path),
}
report["encryption_analysis"] = analyze_encrypted_file(encrypted_path)
report["header_check"] = check_file_header_known_plaintext(encrypted_path)
if "crypto_constants" in report or "encryption_analysis" in report:
report["feasibility"] = assess_decryption_feasibility(
report.get("crypto_constants", []),
report.get("crypto_apis", []),
report.get("encryption_analysis", {}),
)
return report
if __name__ == "__main__":
print("=" * 60)
print("Ransomware Encryption Mechanism Analysis Agent")
print("Algorithm identification, key analysis, decryption feasibility")
print("=" * 60)
if len(sys.argv) < 2:
print("\n[DEMO] Usage:")
print(" python agent.py <ransomware_binary> # Analyze ransomware sample")
print(" python agent.py <ransomware_binary> <encrypted_file> # Full analysis")
print(" python agent.py --encrypted <encrypted_file> # Analyze encrypted file only")
sys.exit(0)
sample = None
encrypted = None
if sys.argv[1] == "--encrypted" and len(sys.argv) > 2:
encrypted = sys.argv[2]
else:
sample = sys.argv[1]
encrypted = sys.argv[2] if len(sys.argv) > 2 else None
report = generate_report(sample_path=sample, encrypted_path=encrypted)
if sample and os.path.exists(sample):
info = report.get("sample", {})
print(f"\n[*] Sample: {sample}")
print(f" SHA-256: {info.get('sha256', 'N/A')}")
print(f" Size: {info.get('size', 0)} bytes")
print(f" Entropy: {info.get('entropy', 0)}")
print("\n--- Crypto Constants Found ---")
for c in report.get("crypto_constants", []):
print(f" [{c['offset']}] {c['constant']}")
print("\n--- Crypto API Imports ---")
for api in report.get("crypto_apis", []):
print(f" {api}")
if encrypted and os.path.exists(encrypted):
fm = report.get("encrypted_file", {}).get("family_match", {})
print(f"\n[*] Encrypted file: {encrypted}")
print(f" Extension: {fm.get('extension', '?')}")
print(f" Possible families: {', '.join(fm.get('families', ['Unknown']))}")
ea = report.get("encryption_analysis", {})
print(f"\n--- Encryption Analysis ---")
print(f" Overall entropy: {ea.get('overall_entropy', 0)}")
print(f" Fully encrypted: {ea.get('fully_encrypted', False)}")
print(f" ECB mode likely: {ea.get('ecb_likely', False)}")
partial = ea.get("partial_encryption", {})
print(f" Partial encryption: {partial.get('likely_partial', False)}")
hc = report.get("header_check", {})
print(f"\n--- Header Check ---")
print(f" Known header: {hc.get('detected', False)}")
print(f" Note: {hc.get('note', '')}")
if "feasibility" in report:
f = report["feasibility"]
print(f"\n--- Decryption Feasibility ---")
print(f" Assessment: {f['feasibility']}")
print(f" Weaknesses:")
for w in f.get("weaknesses", []):
print(f" [!] {w}")
print(f" Strong points:")
for s in f.get("strong_points", []):
print(f" [+] {s}")
print(f" Recommendation: {f['recommendation']}")
print(f"\n[*] Full report:\n{json.dumps(report, indent=2, default=str)}")
Related skills
How it compares
A specialized security analysis skill, not a general code linter or dependency vulnerability scanner.
FAQ
Who is analyzing-ransomware-encryption-mechanisms for?
Security-minded developers, operators with compliance exposure, and analysts who need agent-guided depth on ransomware encryption design.
When should I use analyzing-ransomware-encryption-mechanisms?
Use it in Ship during security hardening, after suspicious file activity, or while designing detection around encryption patterns—not for routine UI or growth tasks.
Is analyzing-ransomware-encryption-mechanisms safe to install?
Malware analysis can involve sensitive samples and elevated risk; review the Security Audits panel on this page and run only in isolated lab environments with explicit agent permissions.