从零复现CTF赛题:Python实现数字水印提取与RC4解密实战

在网络安全竞赛中,数字水印和RC4算法是常见的考察点。本文将带您用Python完整复现这两个技术点的解题过程,通过可运行的代码演示如何从图片中提取隐藏信息以及解密RC4加密数据。

1. 环境准备与工具安装

1.1 安装必要Python库

首先需要安装以下Python库,这些库将帮助我们处理图像和实现加密算法:

pip install opencv-python pywt numpy

注意:建议使用Python 3.8或更高版本,某些库在不同版本中可能有兼容性问题

1.2 准备测试文件

我们需要准备两个测试文件:

  • 包含水印的图片文件(如 watermarked.png
  • 加密后的数据文件(如 encrypted.bin

这些文件可以从CTF比赛提供的素材中获取,或者自行创建测试用例。

2. 数字水印提取实战

数字水印技术常用于版权保护和信息隐藏,我们将使用离散小波变换(DWT)方法提取隐藏信息。

2.1 DWT数字水印原理

离散小波变换将图像分解为不同频率的子带:

  • LL:低频近似分量
  • LH、HL、HH:高频细节分量

水印信息通常嵌入在高频分量中,因为人类视觉对高频变化不敏感。

2.2 Python实现水印提取

以下是完整的数字水印提取类实现:

import cv2
import numpy as np
import pywt

class WatermarkExtractor:
    def __init__(self, watermarked_img_path, key=20, weights=[0.2, 0.2, 0.5, 0.4]):
        self.key = key
        self.img = cv2.imread(watermarked_img_path, cv2.IMREAD_GRAYSCALE)
        self.coef = weights
        
    def inverse_arnold(self, img):
        """逆向Arnold变换,用于还原水印图像"""
        r, c = img.shape
        p = np.zeros((r, c), np.uint8)
        a, b = 1, 1
        for _ in range(self.key):
            for i in range(r):
                for j in range(c):
                    x = ((a*b + 1)*i - b*j) % r
                    y = (-a*i + j) % c
                    p[x, y] = img[i, j]
        return p
    
    def extract(self, output_path='extracted_watermark.png'):
        """提取水印并保存结果"""
        # 三级小波分解
        coeffs = pywt.wavedec2(self.img, 'db2', level=3)
        cA3, (cH3, cV3, cD3), (cH2, cV2, cD2), (cH1, cV1, cD1) = coeffs
        
        # 水印提取算法
        extracted_watermark = pywt.waverec2([
            cA3 * self.coef[0],
            (cH3 * self.coef[1], cV3 * self.coef[2], cD3 * self.coef[3])
        ], 'db2')
        
        # 后处理
        extracted_watermark = np.clip(extracted_watermark, 0, 255).astype(np.uint8)
        extracted_watermark = self.inverse_arnold(extracted_watermark)
        
        # 保存结果
        cv2.imwrite(output_path, extracted_watermark)
        return extracted_watermark

# 使用示例
if __name__ == "__main__":
    extractor = WatermarkExtractor("watermarked.png")
    watermark = extractor.extract()
    print("水印提取完成,已保存为extracted_watermark.png")

提示:Arnold变换是一种图像置乱技术,常用于水印预处理,key参数需要与嵌入时一致才能正确还原

2.3 常见问题排查

问题现象 可能原因 解决方案
提取的水印模糊 权重系数不匹配 调整weights参数
提取失败 小波基不匹配 尝试使用'db1'或'haar'小波
图像尺寸不符 原始图像尺寸变化 确保使用原始尺寸图像

3. RC4算法解密实战

RC4是一种流加密算法,在CTF中经常出现。我们将实现完整的RC4解密过程。

3.1 RC4算法原理

RC4包含两个主要阶段:

  1. 密钥调度算法(KSA):初始化状态数组
  2. 伪随机生成算法(PRGA):生成密钥流

3.2 Python实现RC4解密

class RC4:
    def __init__(self, key):
        self.key = key
        self.S = list(range(256))
        self.T = [ord(c) for c in key] * (256 // len(key)) + [ord(c) for c in key][:256 % len(key)]
        self.initialize()
    
    def initialize(self):
        """KSA密钥调度算法"""
        j = 0
        for i in range(256):
            j = (j + self.S[i] + self.T[i]) % 256
            self.S[i], self.S[j] = self.S[j], self.S[i]
    
    def decrypt(self, ciphertext):
        """解密数据"""
        plaintext = []
        i = j = 0
        for byte in ciphertext:
            i = (i + 1) % 256
            j = (j + self.S[i]) % 256
            self.S[i], self.S[j] = self.S[j], self.S[i]
            k = self.S[(self.S[i] + self.S[j]) % 256]
            plaintext.append(byte ^ k)
        return bytes(plaintext)

# 使用示例
if __name__ == "__main__":
    # 示例:解密蓝桥杯CTF题目
    encrypted_data = bytes.fromhex("已知的加密数据十六进制字符串")
    key = "CTF竞赛提供的密钥"
    
    rc4 = RC4(key)
    decrypted = rc4.decrypt(encrypted_data)
    print(f"解密结果: {decrypted.decode('utf-8', errors='ignore')}")

3.3 RC4解密技巧

在实际CTF比赛中,RC4解密可能遇到以下情况:

  1. 密钥未知 :尝试常见密钥或暴力破解
  2. 部分明文已知 :利用已知明文攻击恢复密钥
  3. 非标准实现 :检查是否有算法修改点
# 暴力破解示例(简单密钥)
def brute_force_rc4(ciphertext, known_plaintext_part, max_key_length=3):
    from itertools import product
    from string import printable
    
    for length in range(1, max_key_length+1):
        for possible_key in product(printable, repeat=length):
            key = ''.join(possible_key)
            rc4 = RC4(key)
            decrypted = rc4.decrypt(ciphertext)
            if known_plaintext_part in decrypted.decode('utf-8', errors='ignore'):
                return key, decrypted
    return None, None

4. 综合实战:CTF题目复现

让我们模拟一个完整的CTF解题流程,结合数字水印和RC4解密技术。

4.1 题目分析

假设题目提供:

  1. 一张包含flag提示的图片(使用DWT水印)
  2. 一个加密的flag文件(使用RC4加密)

4.2 解题步骤

  1. 从图片中提取水印,获取RC4密钥提示
  2. 使用获取的密钥解密加密文件
  3. 提取最终flag
# 完整解题代码
def solve_ctf_challenge():
    # 第一步:提取水印获取密钥提示
    img_extractor = WatermarkExtractor("challenge_image.png")
    watermark = img_extractor.extract("extracted_hint.png")
    print("水印提取完成,请查看extracted_hint.png获取密钥提示")
    
    # 假设从水印中获取到密钥是"CTF2023"
    key = "CTF2023"
    
    # 第二步:解密加密文件
    with open("encrypted_flag.bin", "rb") as f:
        encrypted_data = f.read()
    
    rc4 = RC4(key)
    flag = rc4.decrypt(encrypted_data)
    
    print(f"解密得到的flag: {flag.decode('utf-8')}")

# 执行解题
solve_ctf_challenge()

4.3 调试技巧

在复现过程中可能会遇到各种问题,以下是一些实用调试方法:

  1. 可视化中间结果 :对于图像处理步骤,保存中间图像便于分析
  2. 单元测试 :对RC4算法单独测试,确保加解密正确性
  3. 边界检查 :特别注意图像尺寸是否为2的幂次方(小波变换要求)
# 调试示例:检查小波分解结果
def debug_dwt():
    import matplotlib.pyplot as plt
    
    img = cv2.imread("test.png", cv2.IMREAD_GRAYSCALE)
    coeffs = pywt.wavedec2(img, 'db2', level=3)
    
    # 可视化各子带
    plt.figure(figsize=(12, 8))
    titles = ['Approximation', 'Horizontal', 'Vertical', 'Diagonal']
    for i, (cH, cV, cD) in enumerate(coeffs[1:]):
        plt.subplot(3, 3, i*3+1)
        plt.imshow(cH, cmap='gray')
        plt.title(f'Level {i+1} Horizontal')
        plt.subplot(3, 3, i*3+2)
        plt.imshow(cV, cmap='gray')
        plt.title(f'Level {i+1} Vertical')
        plt.subplot(3, 3, i*3+3)
        plt.imshow(cD, cmap='gray')
        plt.title(f'Level {i+1} Diagonal')
    plt.tight_layout()
    plt.show()

通过本文的实战演练,您应该已经掌握了使用Python复现CTF中数字水印和RC4解密题目的完整流程。在实际比赛中,关键在于理解题目背后的技术原理,并将其转化为可执行的代码解决方案。

更多推荐