最好的语言reverse网鼎杯2018

JLing 2026-05-28 04:18:26 7 0


最好的语言 - Writeup

题目: 最好的语言 (Best Language)
类型: REVERSE (Python Bytecode)
平台: Python 2.7, 32-bit

题目分析

文件识别

题目给出一个文本文件re,内容为 XML 格式的 Python 2.7 字节码:

  • Magic number:03f30d0a→ Python 2.7 bytecode
  • 包含 3 个 code object:主模块、函数_、函数____

算法还原

反编译字节码后还原出以下算法:

# 变量定义
f = 'flag{*******}'  # flag 模板
key1 = ''.join(random.sample(string.digits, 4))  # 4位随机数字密钥1
key2 = ''.join(random.sample(string.digits, 4))  # 4位随机数字密钥2

def _(b):
    """XOR 加密:每字节与4位密钥循环异或"""
    return ''.join(chr(ord(b[i]) ^ ord(key[i % 4])) for i in range(len(b)))

def ____(a):
    """MD5 摘要(raw bytes)"""
    return hashlib.md5(a).digest()

# 编码过程
e = _(f[:12]) + ____(f[12:19]) + _(f[19:])
# 结果 Base64 编码输出:
# U1VQU05pSHdqCEJrQu7FS7Vngk1OTQ58qqghXmt2AUdrcFBBUEU=

编码分三段:

  1. f[:12]→ XOR 加密 →12 字节
  2. f[12:19]→ MD5 原始摘要 →16 字节
  3. f[19:]→ XOR 加密 →10 字节

Total:12 + 16 + 10 = 38 字节→ Base64 → 最终输出。

Flag 总长度:12 + 7 + 10 = 29 字符

解题思路

1. Base64 解码

U1VQU05pSHdqCEJrQu7FS7Vngk1OTQ58qqghXmt2AUdrcFBBUEU=
↓ base64 decode
e[0:12]  = 535550534e6948776a08426b (12 bytes)
e[12:28] = 42eec54bb567824d4e4d0e7caaa8215e (16 bytes, MD5)
e[28:38] = 6b7601476b7050415045 (10 bytes)

2. 恢复 key1(已知前缀攻击)

已知 flag 前缀为flag{PyC_1s_(12 字符),XOR 特性:

key1 = XOR(e[:12], 'flag{PyC_1s_')
     = XOR([83,85,80,83,78,105,72,119,106,8,66,107],
           [102,108,97,103,123,80,121,67,95,49,115,95])
     = [53, 57, 49, 52, 53, 57, 49, 52, 53, 57, 49, 52]
     = '591459145914' → key1 = '5914'

3. 恢复 key2(已知后缀攻击)

已知 flag 后缀为}(f[28] = '}'),且 key2 是 4 位不重复数字:

# f[28] = '}' = 125
# e[37] XOR key2[1] = f[28]
# 69 XOR key2[1] = 125 → key2[1] = 56 = '8'

枚举所有可能的 key2(504 种,4 位不重复数字,已知第 2 位 = '8'):

唯一产生可读结果的组合:key2 = '4813'→ f[19:] =_N0t_Hard}

4. 破解 MD5

已知 f[12:19](7 字符)的 MD5 =42eec54bb567824d4e4d0e7caaa8215e

7 字符 + 字母数字混合 → 36^7 ≈ 780 亿,无法暴力破解。

关键操作:在cmd5.com查询该 MD5 哈希,直接获得原值:613u21i

5. 合成 Flag

f[:12]  = 'flag{PyC_1s_'
f[12:19] = '613u21i'
f[19:]   = '_N0t_Hard}'

Flag:flag{PyC_1s_613u21i_N0t_Hard}

解题脚本

import hashlib, base64

# 题目给的 Base64
encoded = 'U1VQU05pSHdqCEJrQu7FS7Vngk1OTQ58qqghXmt2AUdrcFBBUEU='
raw = base64.b64decode(encoded)

# 已知前缀
known_prefix = b'flag{PyC_1s_'

# 恢复 key1
key1 = bytes([raw[i] ^ known_prefix[i] for i in range(12)])
print(f'key1 = {key1.decode()}')  # 5914

# key2[1] 由 '}' 推出
key2_byte1 = raw[37] ^ ord('}')   # 56 = '8'

# 枚举 key2,找到可读的尾部
key2 = b'4813'
tail = bytes([raw[28 + i] ^ key2[i % 4] for i in range(10)])
print(f'tail = {tail.decode()}')     # _N0t_Hard}

# MD5 中间段(查 cmd5.com)
middle = '613u21i'

# 拼接 flag
flag = 'flag{PyC_1s_613u21i_N0t_Hard}'

# 验证
def xor_encode(s, key):
    return bytes([ord(s[i]) ^ key[i % 4] for i in range(len(s))])

f = flag
verify = xor_encode(f[:12], key1) + \
         hashlib.md5(f[12:19].encode()).digest() + \
         xor_encode(f[19:], key2)
assert base64.b64encode(verify).decode() == encoded
print(f'Flag verified: {flag}')

验证结果

检查项结果
MD5('613u21i') = 42eec54...匹配
Base64 往返编码验证匹配
Flag 长度 = 29匹配

考点总结

  1. Python 字节码分析:.pyc文件结构、dis模块使用、code object 重建
  2. 已知明文 XOR 攻击: 已知前缀/后缀直接恢复 XOR 密钥
  3. MD5 在线查询: cmd5.com 可查询常见弱密码的 MD5 原值 — CTF 中经常会遇到
  4. Base64 编码识别: 末尾=填充是 Base64 特征
  5. 约束搜索: key2 搜索时利用"不重复数字"+"已知一位"+"可打印字符"将搜索空间从 10000 降到 504
分类:Reverse
image
作者:JLing

10

提交

0

收入

相关WriteUP

  • 2018网鼎杯3-babyre

    ***收费WriteUP请购买后查看,VIP用户可免费查看***

    • Reverse
    • 5年前
  • EasyXor

    ***收费WriteUP请购买后查看,VIP用户可免费查看***

    • Reverse
    • 2年前
  • EasyReverse

    ***收费WriteUP请购买后查看,VIP用户可免费查看***

    • Reverse
    • 2年前
  • [NUAACTF-2017] [Reverse]robots解法

    ***收费WriteUP请购买后查看,VIP用户可免费查看***

    • Reverse
    • 2年前
  • 2018-网鼎杯-advance

    ***收费WriteUP请购买后查看,VIP用户可免费查看***

    • Reverse
    • 2年前
问题反馈