FFRREEQQ RSA - Writeup by AI

FFRREEQQ RSA - Writeup by AI

题目信息

  • 来源: BugKu CTF
  • 类别: Crypto / RSA
  • 考点: RSA 逐字符加密、词频分析

题目描述

看起来是 RSA,但是实际上仔细观察会发现连公钥都没有了,肯定也不能正常做啦~

打开 output.txt 可以发现被加密的字符内容特别长,其实也就说明了这段内容其实可以用词频分析来猜测每一个加密字符到底是啥。

这里注意一点,这里由于没有限制加密的一定是英文,这里出现频率最高的其实是空格。

考点分析

核心知识点

  1. RSA 逐字符加密

    • 加密方式:c = pow(ord(char), e, n)
    • 特征:每个 ASCII 字符单独加密
    • 相同明文字符 → 相同密文
  2. 词频分析攻击

    • 英文文本特征:空格 > e > t > a > o > i > n > s > h > r > d > l > u > ...
    • 明文空间极小(仅 95 个可打印 ASCII 字符)
    • 无需分解大数或推导私钥

攻击链

复制代码
密文数据 → 频率统计 → 简化映射 → 在线工具 → 人工修正 → Flag

解题思路

技术路线

  1. 数据提取:从 output.txt 中提取密文数组
  2. 频率统计:统计每个密文值的出现次数
  3. 简化映射:将大整数密文映射为简单字符(a-z)
  4. 在线破解:使用频率分析网站自动破解替换密码
  5. 人工修正:根据上下文修正特殊字符和占位符
  6. 提取 Flag:从解密文本中找到 flag

详细步骤

步骤 1:检查文件结构

bash 复制代码
# 查看文件列表
ls
# 输出:rsa.py, output.txt

# 查看 output.txt 内容
head -20 output.txt

发现:output.txt 包含密文数组,但没有公钥信息(n, e)

步骤 2:提取密文并统计频率

python 复制代码
from collections import Counter

# 提取密文数组
ciphertext = [...]  # 从 output.txt 提取

# 统计频率
counter = Counter(ciphertext)
print(f"不同密文值数量:{len(counter)}")
# 输出:29 个不同的密文值

分析:仅有 29 个不同的密文值,说明明文由少量不同字符组成,适合词频分析。

步骤 3:生成简化密文

运行 frequency_analysis.py 生成简化密文:

python 复制代码
# 将高频密文映射为空格,其余映射为 a-z
mapping = {}
mapping[most_common] = ' '  # 频率最高的是空格
for i, val in enumerate(unique_values[1:], 0):
    mapping[val] = chr(ord('a') + i)

输出示例:

复制代码
kifxc ecbg wa de b lb gwajioe eo gwdwbj mbl atcha mbla...

关键发现:

  • 空格占比 24.46%(符合英文文本特征)
  • 共 29 个不同字符,可映射到字母表

步骤 4:在线频率分析

将简化密文粘贴到以下网站之一:

网站自动破解结果:

复制代码
don't starve is a marvelous survival game...
the flag is this is also fake rsa

步骤 5:人工修正

观察网站结果,发现需要修正的地方:

  • gamez → games
  • playerqs → player's
  • trailer_26_ → trailer.
  • donqt → don't

修正后得到完整明文。

步骤 6:提取 Flag

从解密文本末尾找到:

复制代码
the flag is this is also fake rsa

因此 Flag 为:this is also fake rsa

完整代码

solve.py

python 复制代码
# CTF RSA 频率分析 - 最终解密脚本
# 题目:FFRREEQQ RSA
# 考点:RSA 逐字符加密 + 词频分析

from collections import Counter

def extract_ciphertext(filename):
    """从 output.txt 中提取密文数组"""
    with open(filename, 'r') as f:
        lines = f.readlines()
    
    ciphertext_str = ''
    for line in lines:
        if line.strip().startswith('['):
            ciphertext_str += line.strip()
        elif ciphertext_str and not line.strip().startswith('Public'):
            ciphertext_str += line.strip()
    
    # 清理格式
    ciphertext_str = ciphertext_str.replace(' ', '').replace('\n', '')
    if ciphertext_str.endswith(','):
        ciphertext_str = ciphertext_str[:-1]
    if ciphertext_str.startswith('['):
        ciphertext_str = ciphertext_str[1:]
    if ciphertext_str.endswith(']'):
        ciphertext_str = ciphertext_str[:-1]
    
    return [int(x) for x in ciphertext_str.split(',') if x]

def analyze_frequency(ciphertext):
    """统计频率并返回按频率排序的唯一值列表"""
    counter = Counter(ciphertext)
    return [item[0] for item in counter.most_common()], counter

def decrypt_with_mapping(ciphertext, mapping):
    """使用映射字典解密"""
    return ''.join([mapping.get(val, '?') for val in ciphertext])

def main():
    # 提取密文
    print("="*80)
    print("CTF RSA 频率分析解题工具")
    print("="*80)
    
    ciphertext = extract_ciphertext('output.txt')
    print(f"\n密文长度:{len(ciphertext)}")
    
    # 频率分析
    unique_values, counter = analyze_frequency(ciphertext)
    print(f"不同密文值数量:{len(unique_values)}")
    
    # 创建初始映射(基于英语频率)
    mapping = {}
    mapping[unique_values[0]] = ' '  # 频率最高的是空格
    
    english_freq = 'etaoinsrhlducmfwypvbgkqjxz'
    for i, val in enumerate(unique_values[1:], 0):
        if i < len(english_freq):
            mapping[val] = english_freq[i]
        else:
            mapping[val] = '?'
    
    # 初始解密
    initial_result = decrypt_with_mapping(ciphertext, mapping)
    print("\n" + "="*80)
    print("初始解密结果(自动频率分析):")
    print("="*80)
    print(initial_result[:600])
    if len(initial_result) > 600:
        print("\n...")
        print(initial_result[-400:])
    print("="*80)
    
    # 根据网站破解结果输出最终版本
    final_text = """don't starve is a marvellous survival game. the game opens with maxwell snidely 
commenting on the player's gaunt appearance and includes little further story. 
the game's setup is told further through its trailer. on a dark and stormy night, 
wilson appears to be getting nowhere in a chemistry experiment until he is startled 
by his radio speaking to him. it reveals that it has noticed his trouble and has 
secret knowledge of him. when he eagerly agrees, a flurry of equations and diagrams 
encircle him and fill his head. using white rats, a typewriter, and his blood among 
other tools and materials, wilson creates a giant machine. the radio commends his 
work and tells him to pull the machine's switch. he hesitates, but at the radio's 
insistence, he does so. the machine rattles violently, and a pair of ghostly arms 
whisk him into a different world while an apparition of maxwell cackles.

the flag is this is also fake rsa"""
    
    print("\n\n" + "="*80)
    print("修正后的最终解密结果(基于网站破解):")
    print("="*80)
    print(final_text)
    print("="*80)
    
    # 提取 Flag
    flag = "this is also fake rsa"
    print(f"\n🚩 Flag: {flag}")
    print("="*80)
    
    # 保存详细映射关系
    with open('mapping_detailed.txt', 'w') as f:
        f.write("频率统计和映射关系:\n\n")
        f.write(f"{'排名':<5} {'出现次数':<8} {'密文값 (前 30 位)':<60} {'映射字符'}\n")
        f.write("-" * 80 + "\n")
        for i, (val, count) in enumerate(counter.most_common()):
            mapped_char = mapping.get(val, '?')
            display_val = str(val)[:50] + '...' if len(str(val)) > 50 else str(val)
            f.write(f"{i+1:<5} {count:<8} {display_val:<60} '{mapped_char}'\n")
    
    print("\n✅ 映射关系已保存到 mapping_detailed.txt")

if __name__ == "__main__":
    main()
相关推荐
寻林写彡38 分钟前
云安全 | Docker 容器逃逸复盘(一):从隔离边界到运行时链路,如何确认自己身处容器
安全·云原生
网络毒刘2 小时前
Manual 模式精修补丁:在 Agent 提案后用最小编辑完成高风险改动
安全·agent·ai编程·cursor
hasty3 小时前
超时不等于安全结束:Wasmtime 批量操作漏洞与取消后的状态一致性
安全
troy1283 小时前
智能体沙箱:如何为 Agent 模型搭建安全试验场,降低幻觉带来的损失
网络·安全
Chengbei114 小时前
拒绝无效洞!蚂蚁Src榜一Clown 2.0 SRC SKill 第二代带状态闭环的白盒 & 黑盒审计 Skill
网络·人工智能·安全·web安全·网络安全·自动化·安全架构
hasty5 小时前
安全扫描器也要被隔离:Trivy Terraform 文件读取漏洞与 CI 输出边界
安全·ci/cd·terraform
科技小登6 小时前
零信任与远程办公安全方案对比:身份认证、权限最小化与访问审计的选型测评
安全
事圆则缓6 小时前
Kotlin 入门与面试:从空安全、扩展函数到协程
安全·面试·kotlin
沫璃染墨7 小时前
《从零入门Linux系统篇(五十八):线程篇·十一——线程安全与死锁详解:从可重入到多锁管理》
linux·服务器·开发语言·c++·驱动开发·安全·架构
Flynt8 小时前
800KB 的 JSON 吃掉 8.5 秒 CPU:jackson 这波修复里,最容易被漏掉的洞藏在字符串里
java·安全