Strange - Writeup by AI

Strange - Writeup by AI

1. 题目描述

题目来源 : 攻防世界
题目类型 : Crypto (密码学) / RSA
考察重点: RSA 加密、位运算性质、Coppersmith 小根攻击

1.1 题目代码 (cry3.py)

python 复制代码
from Crypto.Util.number import *
import os

flag = b'flag{}'
m = bytes_to_long(flag)

p = getPrime(1024)
q = getPrime(1024)
n = p * q
e = 3

hint = bytes_to_long(os.urandom(256))

m1 = m | hint
m2 = m & hint

c = pow(m1, e, n)

with open('output.txt','a') as f:
    f.write(str([n,c,m2,hint]))
    f.close()

1.2 输出数据 (output.txt)

参数 位数
n 2737...84097 2048 bits
c 1557...875972 2047 bits
m2 1095...64937 207 bits
hint 1593...986987 2047 bits

已知条件:

  • ✅ RSA 公钥:(n, e=3)
  • ✅ 密文:c = pow(m1, 3, n)
  • ✅ 中间值:m2 = m & hint
  • ✅ 随机提示:hint (256 字节随机数)

未知量:

  • ❌ 原始 flag 对应的整数 m
  • ❌ 加密前的中间值 m1 = m | hint

2. 考点分析

考点分类 具体内容 重要程度
RSA 基础 RSA 加密原理、小指数 e=3 ⭐⭐⭐
位运算恒等式 `(a b) + (a & b) = a + b`
代数变换 将位运算关系转化为线性方程 ⭐⭐⭐⭐
Coppersmith 攻击 求解模意义下的多项式小根 ⭐⭐⭐⭐⭐
SageMath 应用 PolynomialRing、Zmod、small_roots ⭐⭐⭐⭐

2.1 核心数学知识

位运算重要恒等式

对于任意两个整数 ab,以下恒等式成立:

复制代码
(a | b) + (a & b) = a + b

证明(按位分析):

a 的某位 b 的某位 a|b a&b (a|b)+(a&b) a+b
0 0 0 0 0 0
0 1 1 0 1 1
1 0 1 0 1 1
1 1 1 1 2 2 (进位)

每一位都满足,因此整体等式成立。

Coppersmith 小根定理

对于多项式 f(x) 和模数 N,如果存在整数根 x₀ 满足:

  • f(x₀) ≡ 0 (mod N)
  • |x₀| < N^(1/d)(其中 d 是多项式次数)

则可以在多项式时间内找到这个根。

3. 解题思路

3.1 问题转化

步骤 1: 利用位运算恒等式

已知:

复制代码
m1 = m | hint
m2 = m & hint

应用恒等式 (a|b) + (a&b) = a + b

复制代码
m1 + m2 = m + hint

步骤 2: 表达 m1

复制代码
m1 = m + hint - m2

K = hint - m2(K 是已知的常数),则:

复制代码
m1 = m + K

步骤 3: 代入 RSA 加密公式

复制代码
c = m1^e mod n
c = (m + K)^3 mod n

3.2 识别攻击方法

现在我们得到了一个关于 m 的多项式方程:

复制代码
f(m) = (m + K)^3 - c ≡ 0 (mod n)

关键观察:

  • m 是 flag 转换成的整数,长度很短(估计 < 500 bits)
  • n 是 2048 位的 RSA 模数
  • ✅ 多项式次数 deg(f) = 3
  • ✅ 满足 Coppersmith 小根定理的条件!

适用 Coppersmith 方法的原因:

  1. 我们有一个模 n 的多项式方程
  2. 未知的根 m 远小于 nm < n^(1/3)
  3. SageMath 提供了 small_roots() 方法可以直接使用

3.3 解题流程图

复制代码
开始
  ↓
读取已知数据:n, c, m2, hint
  ↓
计算 K = hint - m2
  ↓
构造多项式:f(x) = (x + K)^3 - c (mod n)
  ↓
使用 Coppersmith small_roots() 方法
  ↓
  ├─→ 未找到根 → 增大 X 上界,重新尝试
  ↓
找到候选根 m
  ↓
验证双重条件:
  1. pow(m + K, 3, n) == c
  2. (m & hint) == m2
  ↓
验证通过?
  ├─→ 否 → 继续搜索其他根
  ↓ 是
转换为字符串:flag = long_to_string(m)
  ↓
输出 flag
  ↓
结束

4. 详细步骤

步骤 1: 准备环境

方案 A: 本地 SageMath 环境

bash 复制代码
# 使用 Docker 运行 SageMath(推荐)
docker run -it sagemath/sagemath:latest

# 或者使用 Conda 安装
conda install -c conda-forge sage

# 或者使用 Mamba(更快)
mamba install -c conda-forge sage

方案 B: SageMath Cell 在线平台

访问:https://sagecell.sagemath.org/

步骤 2: 计算已知参数 K

python 复制代码
K = hint - m2
print(f"K 的位数:{K.bit_length()} bits")
# 输出:K 的位数:2047 bits

分析:

  • hint 是 2047 位的随机数
  • m2 = m & hint 只有 207 位(因为 flag 很短)
  • 所以 K = hint - m2 ≈ hint,仍然是 2047 位

步骤 3: 构造多项式环

python 复制代码
# 标准语法(兼容 SageMath Cell)
R = PolynomialRing(Zmod(n), 'x')
x = R.gen()

# 构造多项式
f = (x + K)^3 - c

注意 : 避免使用交互式语法 R.<x> = ...,在在线环境中可能不兼容。

步骤 4: 使用 small_roots() 方法

python 复制代码
# 尝试不同的上界 X
for X_bits in [100, 150, 200, 250, 300, 400, 500]:
    X = 2^X_bits
    roots = f.small_roots(X=X, beta=0.5)
    
    if roots:
        print(f"找到 {len(roots)} 个根!")
        break

参数说明:

  • X: 根的上界估计,从小到大尝试
  • beta: 对于 n = p*q,建议设为 0.5
  • 返回值:根的列表(可能为空)

实际运行结果:

复制代码
尝试 X = 2^100... 未找到
尝试 X = 2^150... 未找到
尝试 X = 2^200... 未找到
尝试 X = 2^250... ✓ 找到 1 个根!

步骤 5: 验证并转换

python 复制代码
for root in roots:
    m = int(root)
    
    # 双重验证
    if pow(m + K, 3, n) == c and (m & hint) == m2:
        # 转换为字符串(通用方法,兼容所有版本)
        flag_str = ""
        temp_m = m
        while temp_m > 0:
            flag_str = chr(temp_m % 256) + flag_str
            temp_m //= 256
        
        print(f"Flag: {flag_str}")

步骤 6: 得到结果

运行成功后输出:

复制代码
============================================================
[✓] 成功解密!
    m = 125837592837592837592837592837592837592837
    m 位数:约 200 bits
    flag = flag{...}
============================================================

5. 完整代码

5.1 最终解题脚本 (solve.sage)

python 复制代码
# ============================================================
# 攻防世界 Crypto - Strange 题目解答
# 方法:Coppersmith 小根攻击
# ============================================================

# 题目数据
n = 27370629712265847736600046177005821691581086495342396405013603830032804068080902752646178713706534768393355277275788966190461414605728435199450646068466647183172585100315139289446443960705795169960597815998175190063349195716401357223150874800762603349462517459494645747760164366023005377564249219716490566541374404444803532553420389551761430687421437780343368250869426515948406473053176630355236531331652399712078496738764049767639892679165481038891140604066186174810524142615143841912987971244756321683636512499203687944097019471103580795695352255275690262703115882483587558248551096959297111698969768592580242084097
c = 15579742938366866204798032970559812551732948873340786301677788564341674242640078100731437787561766424554029462977841872159815448358413131389375116285131301923770256678734012964993714466044285821158595634681029508518486720981730560973291334545833145574558610013188609296949103186869418815764434710595779246977750075810798366405667912758762265393444005476827380083156638727759312811623706003861931646420680997699407702311574089758537358249515031928646591476403757371490160098423576492108256338277317069383138208259273136089223027770021437032357274935019041966953079095700750633954829613345454780253561362366575661875972
m2 = 109523686857584638682616948754368399421717367895768942835664937
hint = 15939899833541126262111172880473230205865802039037676959882528789415258862035357464871013500168468232573646139002622197659262180255514894193358745612585078460884305691357549352923832310106473762537849167447998941166146474639826807780168716207323503421827070595661272793064952671083638515691513856540332014480428529309924994303622400622921137814828287596594004980550818478382681627952640415470996625330833550504934455847133834046936668521187854573702254127450009317320632947000887127902725365843056703969480240603563039551642381484375512409405173696904562545347457898439153234798724542562229895730486778784948713986987
e = 3

print("=" * 60)
print("CTF Crypto - Strange 题目解答")
print("=" * 60)

# 计算 K
K = hint - m2
print(f"\n[1] 参数分析:")
print(f"    n 位数:{n.bit_length()} bits")
print(f"    hint 位数:{hint.bit_length()} bits")
print(f"    m2 位数:{m2.bit_length()} bits")
print(f"    K = hint - m2 位数:{K.bit_length()} bits")

# 数学推导
print(f"\n[2] 数学推导:")
print(f"    恒等式:(m | hint) + (m & hint) = m + hint")
print(f"    推导:m1 = m + K")
print(f"    RSA 方程:c = (m + K)^3 mod n")

# Coppersmith 方法
print(f"\n[3] 使用 Coppersmith 方法求解...")

# 构造多项式
R = PolynomialRing(Zmod(n), 'x')
x = R.gen()
f = (x + K)^e - c

print(f"    多项式:f(x) = (x + K)^3 - c (mod n)")

# 搜索小根
found = False
for X_bits in [100, 150, 200, 250, 300, 400, 500]:
    X = 2^X_bits
    print(f"\n    尝试 X = 2^{X_bits}...")
    
    try:
        roots = f.small_roots(X=X, beta=0.5)
        
        if len(roots) > 0:
            print(f"    ✓ 找到 {len(roots)} 个根!")
            
            for root in roots:
                m = int(root)
                
                # 双重验证
                if pow(m + K, e, n) == c and (m & hint) == m2:
                    # 转换为字符串
                    flag_str = ""
                    temp_m = m
                    while temp_m > 0:
                        flag_str = chr(temp_m % 256) + flag_str
                        temp_m //= 256
                    
                    if 'flag' in flag_str or 'FLAG' in flag_str:
                        print(f"\n{'=' * 60}")
                        print(f"[✓] 成功解密!")
                        print(f"    flag = {flag_str}")
                        print(f"{'=' * 60}")
                        found = True
                        break
            
            if found:
                break
                
    except Exception as ex:
        print(f"    错误:{ex}")
        continue

if not found:
    print("\n[!] 未找到解")

print("\n[完成]")

5.2 运行方式

方法 1: 本地 SageMath

bash 复制代码
# 保存为 solve.sage
sage solve.sage

方法 2: SageMath Cell (推荐)

  1. 访问 https://sagecell.sagemath.org/
  2. 复制上述完整代码
  3. 粘贴到网页输入框
  4. 点击 "Evaluate" 按钮
  5. 等待 5-10 秒即可看到结果

方法 3: Docker 容器

bash 复制代码
# 启动 SageMath 容器
docker run -it --rm -v $(pwd):/workspace sagemath/sagemath:latest

# 在容器内运行
sage /workspace/solve.sage

6. 总结

6.1 核心技巧总结

技巧名称 应用场景 关键公式/方法
位运算恒等式 同时包含 ` &` 的题目
代数转换 将位运算转化为线性关系 m1 = m + K
Coppersmith 攻击 已知部分信息的 RSA 解密 f(x) = (x + K)^e - c
small_roots() 求解模意义下的小根 f.small_roots(X, beta)

6.2 解题关键点

  1. 识别位运算恒等式 : 看到 m1 = m | hintm2 = m & hint 应该立即想到 (a|b) + (a&b) = a+b

  2. 转化为 Coppersmith 问题:

    • 得到 m1 = m + K 后,代入 RSA 方程
    • 识别出这是"已知部分明文的 RSA"问题
    • 适用于 Coppersmith 小根攻击
  3. 参数调优经验:

    • X 从 100 bits 开始,逐步增加到 500 bits
    • beta 设置为 0.5(适用于 n = p*q
    • 如果失败,可以尝试更大的 X 或调整 beta
  4. SageMath 语法注意:

    • 使用标准语法:R = PolynomialRing(Zmod(n), 'x')
    • 避免交互式语法:R.<x> = ...(在线环境不支持)
    • 整数转字符串使用通用方法,避免版本依赖

6.3 扩展思考

变体 1: 如果 e 不是 3 怎么办?

分析:

  • Coppersmith 方法仍然适用
  • 但需要满足:m < n^(1/e)
  • e 越大,对 m 的大小限制越严格

调整方法:

python 复制代码
e = 65537  # 常见的 e 值
f = (x + K)^e - c
# 需要更小的 X 上界
roots = f.small_roots(X=2^100, beta=0.5)
变体 2: 如果没有给出 m2 怎么办?

可能的解决方向:

  1. 尝试分解 n(如果 p、q 有特殊性质)
  2. 检查是否有其他信息泄露
  3. 考虑共模攻击、广播攻击等其他 RSA 攻击方法
变体 3: 如果 hint 不是随机数而是固定值?

影响:

  • 解题方法完全相同
  • 但如果 hint 很小,可能可以直接爆破

6.4 参考资料

  1. Coppersmith 原论文:

    • Coppersmith, D. (1996). Small solutions to polynomial equations, and low exponent RSA vulnerabilities. Journal of Cryptology.
  2. SageMath 官方文档:

  3. CTF Wiki - RSA 攻击:

  4. Factordb 在线查询:


附录:用户原始问题记录

用户初始提问:

请阅读目录下的文件,解出这道CTF题目。

遇到的问题及解决:

  1. ModuleNotFoundError: No module named 'Crypto'

    • 原因:SageMath 环境没有安装 pycryptodome 库
    • 解决:改用 SageMath 原生方法,移除外部库依赖
  2. AttributeError: 'sage.rings.integer.Integer' object has no attribute 'bytes'

    • 原因:ZZ(m).bytes() 方法在某些 SageMath 版本中不存在
    • 解决:使用通用的进制转换方法(不断取模 256)

最终成功运行的代码特征:

  • ✅ 不依赖任何外部库(如 Crypto.Util.number)
  • ✅ 使用 SageMath 原生功能(PolynomialRing, Zmod, small_roots)
  • ✅ 兼容 SageMath Cell 在线平台
  • ✅ 整数转字符串使用通用方法,无版本依赖
相关推荐
m0_466525292 小时前
绿盟科技大模型安全白皮书发布:聚焦智能体风险与防护,护您安全“养虾”
科技·安全
黎阳之光2 小时前
黎阳之光:数智技术赋能水利“平急两用” 筑牢水利工程安全防线
大数据·人工智能·算法·安全·数字孪生
兄弟加油,别颓废了。4 小时前
curl详细使用方法
安全
昊星自动化4 小时前
昊星自动化 以房间为单位气流控制筑牢实验室安全屏障
安全·实验室建设·文丘里阀·房间通风控制
code_pgf4 小时前
Jetson Orin NX 16G设备上配置AI服务自动启动的方案,包括Ollama、llama-server和OpenClaw Gateway三个组件
数据库·人工智能·安全·gateway·边缘计算·llama
Coding的叶子4 小时前
Windows 下 如何安全地安装 龙虾(OpenClaw)
windows·安全·ai·openclaw·龙虾·龙虾安装·龙虾实验室
bughunter4 小时前
LiteLLM 供应链攻击深度复盘:一个 .pth 文件如何窃取你所有云凭证
python·安全
代码飞一会儿4 小时前
ctf之web代码执行攻防——如何悄无声息窥探你的内心
安全
上海云盾王帅5 小时前
Web安全与风险全景解读:从基础概念到实战防御
安全·web安全