用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/killvxk/cybersecurity-skills-zh --skill reverse-engineering-ransomware-encryption-routine命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
基于 SOC 职业分类
正在显示 SKILL.md
| name | reverse-engineering-ransomware-encryption-routine |
| description | 对勒索软件加密例程进行逆向工程,以识别密码学算法、密钥生成缺陷,以及通过静态和动态分析挖掘潜在的解密机会。 |
| domain | cybersecurity |
| subdomain | malware-analysis |
| tags | ["ransomware","encryption","reverse-engineering","cryptanalysis","aes","rsa","decryption","malware-analysis"] |
| version | 1.0 |
| author | mahipal |
| license | Apache-2.0 |
现代勒索软件使用混合加密方案,将对称算法(AES-256-CBC/CTR、ChaCha20、Salsa20)用于文件加密,将非对称算法(RSA-2048/4096、Curve25519)用于密钥保护。加密例程通常为每个文件生成一个随机对称密钥,加密文件内容,然后用攻击者内嵌的公钥加密对称密钥。对这些例程进行逆向工程,可以识别具体算法、密钥派生方法、初始化向量(IV)、文件定向模式,以及可能在不支付赎金的情况下实现解密的实现缺陷。典型案例包括 Rhysida(AES-256-CTR + RSA-4096)、Qilin.B(带 AES-NI 的 AES-256-CTR 或 ChaCha20 回退)和 Medusa(AES-256 + RSA)。
pycryptodome、pefile勒索软件为每个文件生成唯一的 AES 密钥和 IV。文件内容使用该对称密钥加密。对称密钥再用攻击者的 RSA 公钥(内嵌于二进制文件中或从 C2 获取)加密。加密后的密钥追加或前置到加密后的文件中。只有持有 RSA 私钥的攻击者才能解密每个文件的对称密钥。
Windows 勒索软件通常使用 CryptoAPI(CryptAcquireContext、CryptGenKey、CryptEncrypt)或 CNG(BCryptGenerateSymmetricKey、BCryptEncrypt)。部分使用 OpenSSL 或自定义实现。识别这些 API 调用可立即获取算法、密钥大小和操作模式的信息。
解密机会来自:硬编码加密密钥、密钥生成使用弱伪随机数生成器(PRNG)(以 GetTickCount 或 time() 为种子)、跨文件复用 IV、使用 ECB 模式、加密后密钥仍留在内存中,以及在加密过程中可捕获密钥的竞争条件。
#!/usr/bin/env python3
"""识别勒索软件 PE 文件中的密码学函数。"""
import pefile
import sys
CRYPTO_APIS = {
# Windows CryptoAPI
"CryptAcquireContextA": "CryptoAPI 上下文获取",
"CryptAcquireContextW": "CryptoAPI 上下文获取",
"CryptGenKey": "密钥生成",
"CryptDeriveKey": "密钥派生",
"CryptEncrypt": "加密操作",
"CryptDecrypt": "解密操作",
"CryptImportKey": "密钥导入(公钥?)",
"CryptExportKey": "密钥导出",
"CryptGenRandom": "随机数生成",
"CryptCreateHash": "哈希创建",
"CryptHashData": "哈希操作",
# Windows CNG(BCrypt)
"BCryptOpenAlgorithmProvider": "CNG 算法初始化",
"BCryptGenerateSymmetricKey": "CNG 对称密钥生成",
"BCryptEncrypt": "CNG 加密",
"BCryptDecrypt": "CNG 解密",
"BCryptGenerateKeyPair": "CNG 密钥对生成",
"BCryptImportKeyPair": "CNG 密钥导入",
# OpenSSL
"EVP_EncryptInit_ex": "OpenSSL 加密初始化",
"EVP_EncryptUpdate": "OpenSSL 加密更新",
"EVP_EncryptFinal_ex": "OpenSSL 加密完成",
"RSA_public_encrypt": ,
: ,
: ,
: ,
: ,
: ,
: ,
: ,
: ,
}
AES_SBOX = ([
, , , , , , , ,
, , , , , , , ,
])
CHACHA20_CONSTANT =
():
:
pe = pefile.PE(filepath)
pefile.PEFormatError:
()
()
( * )
crypto_imports = []
(pe, ):
entry pe.DIRECTORY_ENTRY_IMPORT:
dll = entry.dll.decode(, errors=)
imp entry.imports:
imp.name:
name = imp.name.decode(, errors=)
name CRYPTO_APIS:
desc = CRYPTO_APIS[name]
crypto_imports.append((dll, name, desc))
()
crypto_imports:
()
()
crypto_imports
():
(filepath, ) f:
data = f.read()
()
( * )
offset = data.find(AES_SBOX)
offset != -:
()
offset = data.find(CHACHA20_CONSTANT)
offset != -:
()
rsa_markers = [
,
,
,
]
marker rsa_markers:
offset = data.find(marker)
offset != -:
()
re
ext_pattern = re.(, re.IGNORECASE)
extensions = ()
ext_pattern.finditer(data):
ext = .group().decode(, errors=).lower()
target_exts = [
, , , , , ,
, , , , , ,
]
ext target_exts:
extensions.add(ext)
extensions:
()
__name__ == :
(sys.argv) < :
()
sys.exit()
analyze_imports(sys.argv[])
find_crypto_constants(sys.argv[])
def analyze_encryption_pattern(filepath):
"""从勒索软件产物分析文件加密模式。"""
import os
import struct
with open(filepath, 'rb') as f:
data = f.read()
file_size = len(data)
print(f"\n[+] 加密文件分析: {filepath}")
print(f" 大小: {file_size:,} 字节")
# 检查追加的密钥材料(常见模式)
# 许多勒索软件家族在文件末尾追加加密后的密钥
tail_sizes = [256, 512, 1024, 2048] # 常见 RSA 密文大小
for size in tail_sizes:
if file_size > size + 16:
tail = data[-size:]
# 高熵值表明为加密数据
entropy = calculate_entropy(tail)
if entropy > 7.5:
print(f" 文件末尾可能存在加密密钥({size} 字节),"
f"熵值: {entropy:.2f}")
# 检查头部修改
# 许多勒索软件会前置元数据
header = data[:64]
print(f" 前 16 字节: {header[:16].hex()}")
# 检查原始文件头是否被保留
known_headers = {
b'PK': 'ZIP/Office',
b'\x89PNG': ,
: ,
: ,
: ,
}
magic, ftype known_headers.items():
header.startswith(magic):
()
:
()
():
collections Counter
math
data:
freq = Counter(data)
length = (data)
entropy = -(
(count / length) * math.log2(count / length)
count freq.values()
)
entropy