[经验总结][加解密]SecureCRT新版加密逻辑和破解方式(附破解脚本和演示)

一、前言

SecureCRT的加密方式有两种:旧版使用双Blowfish加密,固定密钥和随机填充;新版使用AES-CBC,密钥基于配置口令的哈希,且包含校验信息。该篇文章主要介绍新版加解密的思路,并提供解密的脚本和实操的解密效果。

二、加密逻辑

新版加密 (SecureCRTCryptoV2)
算法:AES-256 (CBC 模式),密钥基于配置口令的 SHA256 哈希。该加密支持动态口令,包含完整性校验

2.1 编码转换

将明文密码转为 UTF-8 字节。

plain_bytes = Plaintext.encode('utf-8')

2.2 添加元信息

  • 前 4 字节:明文长度(小端序)
  • 末尾 32 字节:明文的 SHA256 哈希值(用于完整性校验)
plain_with_meta = len(plain_bytes).to_bytes(4, 'little') + plain_bytes + SHA256(plain_bytes).digest()

2.3 填充

使用随机字节填充至 AES 块大小(16 字节对齐)。

padded_plain = plain_with_meta + os.urandom(AES.block_size - len(plain_with_meta) % AES.block_size)

2.4 加密

使用基于配置口令生成的 AES-256 密钥进行加密(IV 为全零)。

key = SHA256(ConfigPassphrase.encode()).digest()
cipher = AES.new(key, CBC, iv=全零IV)
ciphertext = cipher.encrypt(padded_plain)

注:

  • AES.new() 生成一个 AES 对象,后续可用 .encrypt() 和 .decrypt() 方法进行加密/解密。
  • iv(初始化向量):在CBC模式需要,长度需为 16 字节(ECB 模式 不需要 iv,但安全性较低)。需随机生成且每次加密不同,可通过 os.urandom(16) 生成。

2.5 输出结果

最终密文以十六进制字符串形式返回。

整个过程如下图所示:
在这里插入图片描述

三、解密逻辑

3.1 AES-256解密

3.1.1 密钥生成

因为AES-256解密需要对应的密钥,因此解密之前,需要还原加密时使用的 AES-256 密钥

输入参数:用户提供的 ConfigPassphrase(若未设置则为空字符串)
生成方式:

key = SHA256(config_passphrase.encode()).digest()  # 输出32字节密钥

注:若配置口令错误,生成的密钥错误 → 导致后续解密数据无效 → 哈希校验失败。
因此为了提高代码鲁棒性,可以考虑加上错误检查。

3.1.2 AES-256-CBC 解密

参数:

  • IV:固定为 16字节全零(b'\x00'*16
  • 密钥:上一步生成的 key
cipher = AES.new(key, AES.MODE_CBC, iv=iv)
decrypted_data = cipher.decrypt(ciphertext_bytes)

注:
CBC 模式需要块对齐(16字节),所以如果密文无法完成块对齐,那么无法成功解密(可在解密前进行检查)。
又因为加密时已填充随机字节,所以解密后需精确截取有效数据。

解密后的数据格式如下:
在这里插入图片描述
即前面的4字节(红色框)指明了明文的长度,我们可以根据明文长度(3.2节),截取出对应的明文(3.3节)。

3.2 读取明文长度

plain_length = int.from_bytes(decrypted_data[0:4], 'little')  # 小端序解析

为什么是小端序呢。使用小端序还是大端序,得和加密部分对应。
即如果加密使用小端序,那么解密也对应使用小端序。大端序同理。
根据实测,SecureCRT加密时使用了小端序,因此我们便对应使用小端序进行解密。

3.3 提取明文数据

plain_bytes = decrypted_data[4 : 4 + plain_length]

从第4字节开始,取 plain_length 字节,提取哈希校验值

3.4 完整性校验

这一步不是必须的,但是是解密完整步骤中的重要一环。

3.4.1 提取SHA256校验值

expected_hash = decrypted_data[4 + plain_length : 4 + plain_length + 32]

SHA校验值位于明文数据后的32字节。

3.4.2 哈希完整性校验

验证解密数据的完整性和口令正确性。如果校验不通过,那么直接说明我们拿到的不是实际的明文密码。有以下的可能情况:

  • 因密钥错误(3.1.1节生成的密钥有误),导致解密出的plain_bytesexpected_hash有误。
  • 密文被篡改,导致解密后的结构化数据损坏
actual_hash = SHA256.new(plain_bytes).digest()
if actual_hash != expected_hash:
    raise ValueError("Hash mismatch")

3.5 明文解码

将UTF-8字节数据转为字符串

return plain_bytes.decode('utf-8')

整个解密代码如下所示:

from Crypto.Hash import SHA256
from Crypto.Cipher import AES

def decrypt_securecrt_v2(ciphertext_hex, config_passphrase=''):
	# ciphertext_hex (str): 十六进制格式的密文字符串
	# config_passphrase (str): 配置口令(若未设置则留空)
	
    # 将密文转换为字节
    ciphertext = bytes.fromhex(ciphertext_hex)
    # 生成解密密钥3.1.1
    key = SHA256.new(config_passphrase.encode('utf-8')).digest()
    # 初始化AES解密器(IV为全零)
    iv = b'\x00' * AES.block_size
    cipher = AES.new(key, AES.MODE_CBC, iv=iv)
    # 执行AES解密3.1.2
    decrypted_data = cipher.decrypt(ciphertext)
    # 解析数据结构(格式:4字节长度 + 明文 + 32字节SHA256)
    if len(decrypted_data) < 4 + 32:
        raise ValueError("密文长度过短")
        
    # 提取明文长度(小端序)3.2
    plain_length = int.from_bytes(decrypted_data[0:4], 'little')
    
    # 提取明文部分3.3
    plain_start = 4
    plain_end = plain_start + plain_length
    plain_bytes = decrypted_data[plain_start:plain_end]
    # 提取校验哈希3.4.1
    hash_start = plain_end
    expected_hash = decrypted_data[hash_start:hash_start + 32]

    # 验证哈希完整性3.4.2
    actual_hash = SHA256.new(plain_bytes).digest()
    if actual_hash != expected_hash:
        raise ValueError("哈希校验失败,可能配置口令错误或数据被篡改")

    # 返回UTF-8解码结果3.5
    return plain_bytes.decode('utf-8')


if __name__ == "__main__":
    sample_cipher = "67ce8baadd44bc43bbaee41041234f0c1373125cf65bbfa708f0e17f42e510266ab9eecdd26b11c4f26bc42fc7430dd7cf954710580db4cceac2e538c0d87043"

    try:
        # 情况1:没有配置口令
        plain = decrypt_securecrt_v2(sample_cipher)

        # 情况2:有配置口令
        # plain = decrypt_securecrt_v2(sample_cipher, "mypass")

        print(f"解密结果: {plain}")
    except Exception as e:
        print(f"解密失败: {str(e)}")

四、实操

4.1 从ini文件中获取密文密码

在这里插入图片描述
密文即图中的绿色选中部分。

4.2 替换值并运行解密脚本

在这里插入图片描述


原创,转发请注明。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wingaso

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值