这是什么编码 - writeup by AI

这是什么编码 - writeup by AI

📋 题目信息

项目 内容
题目名称 这是什么编码
来源平台 BUGKU CTF
题目类型 Crypto (密码学)
核心考点 Base 家族编码识别、多层嵌套解码
涉及编码 Hex、Base32、Base64

🎯 题目描述

给定的密文文件 encode.txt 中包含一串经过多重编码的字符串,需要通过分析和解码,最终提取出隐藏的 flag。

原始密文(前 100 字符):

复制代码
4b5a4b455536534e4b5a48454f56334f4a5a4b57455232534b564b464d5754584b524c4655574445493544464f544b5647...

密文总长度:2560 个字符


🔍 考点分析

1. 主要考点

  • 编码特征识别:通过字符集和长度特征判断编码类型
  • 多层解码能力:理解编码可以嵌套使用
  • 耐心与细心:需要多次迭代解码

2. 涉及的编码知识

十六进制编码 (Hex)
特征 说明
字符集 0-9, A-F (16 个字符)
长度特征 偶数
Padding
压缩比 2:1 (编码后长度翻倍)
Base32 编码
特征 说明
字符集 A-Z, 2-7 (32 个字符)
长度特征 8 的倍数
Padding = (最多 6 个)
压缩比 8:5 ≈ 1.6:1
Base64 编码
特征 说明
字符集 A-Z, a-z, 0-9, +, / (64 个字符)
长度特征 4 的倍数
Padding = (最多 2 个)
压缩比 4:3 ≈ 1.33:1

💡 解题思路

整体策略

  1. 观察特征:分析密文的字符组成和长度
  2. 初步判断:根据特征推测编码类型
  3. 逐层解码:从外层到内层依次解码
  4. 循环检测:每次解码后检查是否出现 flag
  5. 记录路径:保存完整的解码过程

编码嵌套逻辑

复制代码
原始数据 
  ↓ [Hex 编码]
Hex 密文 (2560 字符)
  ↓ [Base32 编码]
Base32 密文 (1280 字符)
  ↓ [Base64 编码]
Base64 密文 #1 (800 字符)
  ↓ [Base64 编码]
Base64 密文 #2 (600 字符)
  ↓ [Base64 编码]
Base64 密文 #3 (448 字符)
  ↓ [Base32 编码]
Base32 密文 #4 (336 字符)
  ↓ [Base32 编码]
Base32 密文 #5 (208 字符)
  ↓ [Base64 编码]
Base64 密文 #6 (128 字符)
  ↓ [Base32 编码]
Base32 密文 #7 (96 字符)
  ↓ [Base64 编码]
Base64 密文 #8 (56 字符)
  ↓ [Base32 编码]
Base32 密文 #9 (40 字符)
  ↓ [解码]
Flag (23 字符)

📝 详细解题步骤

Step 1: 初始密文分析

输入:原始密文(2560 字符)

特征分析

  • ✅ 只包含字符 0-9A-F
  • ✅ 长度为偶数(2560)
  • ✅ 符合十六进制编码特征

判断 :这是十六进制编码 (Hex)

操作

python 复制代码
decoded = bytes.fromhex(cipher).decode('utf-8')

结果

  • 解码后长度:1280 字符
  • 压缩比:2:1
  • 新密文特征:只包含 A-Z2-7

Step 2: Base32 解码

输入:Step 1 的结果(1280 字符)

特征分析

  • ✅ 只包含大写字母 A-Z 和数字 2-7
  • ✅ 长度能被 8 整除(1280 % 8 = 0)
  • ✅ 符合 Base32 编码特征

判断 :这是Base32 编码

操作

python 复制代码
padding = (8 - len(s) % 8) % 8  # 计算 padding
decoded = base64.b32decode(s + '=' * padding).decode('utf-8')

结果

  • 解码后长度:800 字符
  • 压缩比:1.6:1
  • 新密文特征:包含大小写字母、数字,可能是 Base64

Step 3: 第一次 Base64 解码

输入:Step 2 的结果(800 字符)

特征分析

  • ✅ 包含大小写字母和数字
  • ✅ 长度能被 4 整除(800 % 4 = 0)
  • ✅ 符合 Base64 编码特征

判断 :这是Base64 编码

操作

python 复制代码
padding = (4 - len(s) % 4) % 4
decoded = base64.b64decode(s + '=' * padding).decode('utf-8')

结果

  • 解码后长度:600 字符
  • 压缩比:1.33:1
  • 仍然是 Base64 编码特征

Step 4-5: 连续 Base64 解码

继续对 Step 3 的结果进行 Base64 解码:

Step 4

  • 输入:600 字符
  • 输出:448 字符
  • 仍然是 Base64 编码

Step 5

  • 输入:448 字符
  • 输出:336 字符
  • 变化:不再符合标准 Base64 特征

Step 6: Base32 解码(关键转折)

输入:Step 5 的结果(336 字符)

特征分析

  • ✅ 只包含大写字母和部分数字(2-7)
  • ❌ 长度不能被 4 整除(336 % 4 = 0,但字符集不符合 Base64)
  • ✅ 符合 Base32 特征

判断 :切换回Base32 编码

操作

python 复制代码
padding = (8 - len(s) % 8) % 8
decoded = base64.b32decode(s + '=' * padding).decode('utf-8')

结果

  • 解码后长度:208 字符
  • 仍然是 Base32 编码特征

Step 7: 再次 Base32 解码

输入:Step 6 的结果(208 字符)

操作:继续使用 Base32 解码

结果

  • 解码后长度:128 字符
  • 变为 Base64 编码特征

Step 8-11: 交替解码

按照以下顺序继续解码:

步骤 编码类型 输入长度 输出长度 压缩比
8 Base64 128 96 1.33:1
9 Base32 96 56 1.71:1
10 Base64 56 40 1.4:1
11 Base32 40 23 1.74:1

Step 12: 发现 Flag

输入:Step 11 的结果(23 字符)

检查结果

python 复制代码
if 'flag{' in current.lower():
    print("✓ 找到 Flag!")


💻 完整解题代码

python 复制代码
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import base64
from datetime import datetime

def analyze_string(s, step_name=""):
    """分析字符串的特征信息"""
    print(f"\n{'='*70}")
    print(f"[{step_name}] 字符串特征分析")
    print('='*70)
    
    # 基本信息
    print(f"长度:{len(s)} 字符")
    print(f"长度 % 4: {len(s) % 4} (Base64 要求)")
    print(f"长度 % 8: {len(s) % 8} (Base32 要求)")
    
    # 字符集分析
    unique_chars = sorted(set(s.replace('=', '')))
    char_set = ''.join(unique_chars)
    
    print(f"\n唯一字符数:{len(unique_chars)}")
    print(f"字符集:{char_set[:50]}{'...' if len(char_set) > 50 else ''}")
    
    # 字符类型
    has_upper = any(c.isupper() for c in s)
    has_lower = any(c.islower() for c in s)
    has_digit = any(c.isdigit() for c in s)
    has_only_hex = all(c in '0123456789ABCDEFabcdef' for c in s.replace('=', ''))
    has_only_b32 = all(c in 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567' for c in s.replace('=', ''))
    
    print(f"\n包含大写字母:{'是' if has_upper else '否'}")
    print(f"包含小写字母:{'是' if has_lower else '否'}")
    print(f"包含数字:{'是' if has_digit else '否'}")
    
    print(f"\n编码匹配:")
    print(f"  Hex: {'✓' if has_only_hex else '✗'}")
    print(f"  Base32: {'✓' if has_only_b32 else '✗'}")
    print(f"  Base64: {'✓' if (has_upper or has_lower or has_digit) else '✗'}")


def try_decode_hex(s):
    try:
        return bytes.fromhex(s).decode('utf-8')
    except:
        return None


def try_decode_b32(s):
    try:
        clean = s.replace('=', '')
        pad = (8 - len(clean) % 8) % 8
        return base64.b32decode(clean + '=' * pad).decode('utf-8')
    except:
        return None


def try_decode_b64(s):
    try:
        pad = (4 - len(s) % 4) % 4
        return base64.b64decode(s + '=' * pad).decode('utf-8')
    except:
        return None


def solve():
    start_time = datetime.now()
    
    print("="*70)
    print("CTF 题目:这是什么编码 - 详细解题过程")
    print("="*70)
    
    # 读取密文
    with open('encode.txt', 'r') as f:
        current = f.read().strip()
    
    step = 0
    path = []
    
    while step < 50:
        step += 1
        
        # 检查 Flag
        if 'flag{' in current.lower():
            print(f"\n{'='*70}")
            print("🎉 成功找到 Flag! 🎉")
            print(f"{'='*70}")
            print(f"步数:{step}")
            print(f"路径:{' -> '.join(path)}")
            print(f"\nFlag: {current}")
            break
        
        # Step 1: Hex
        if step == 1:
            result = try_decode_hex(current)
            if result:
                path.append("Hex")
                current = result
                analyze_string(current, "Step 1 - Hex 解码后")
                continue
        
        # 尝试 Base32
        result = try_decode_b32(current)
        if result:
            path.append("Base32")
            current = result
            analyze_string(current, f"Step {step} - Base32 解码后")
            continue
        
        # 尝试 Base64
        result = try_decode_b64(current)
        if result:
            path.append("Base64")
            current = result
            analyze_string(current, f"Step {step} - Base64 解码后")
            continue
        
        break
    
    end_time = datetime.now()
    print(f"\n耗时:{(end_time - start_time).total_seconds():.2f} 秒")


if __name__ == '__main__':
    solve()

🎓 经验总结

1. 编码识别技巧

编码类型 快速识别方法
Hex 只有 0-9 和 A-F,长度偶数
Base32 只有 A-Z 和 2-7,可能有等号
Base64 有大小写字母、数字,可能有+/和等号

📌 工具推荐

在线工具


相关推荐
一名优秀的码农3 小时前
vulhub系列-39-y0usef(超详细)
安全·web安全·网络安全·网络攻击模型·安全威胁分析
黑棠会长4 小时前
ABP框架09.数据安全与合规:审计日志与实体变更追踪
分布式·安全·架构·c#·abp
Echo-J6 小时前
KVM-VMI项目编译安装全过程,包含所遇问题及解决措施
安全·网络安全·云计算·系统安全
小金鱼Y6 小时前
🔥 前端人必看:浏览器安全核心知识点全解析(XSS/CSRF/DDoS)
前端·javascript·安全
奥升新能源平台6 小时前
奥升充电最小化高可用机房部署方案
运维·安全·开源·能源·springcloud
oi..6 小时前
Flag入门—Flag在返回包中
网络·笔记·测试工具·安全·网络安全
AI周红伟7 小时前
周红伟:现象级,OpenClaw安全防控:OpenClaw+Skills+星辰大模型安全部署、实操和企业应用实操
安全
风曦Kisaki7 小时前
#Linux进阶Day04 用户 sudo 提权、IP 地址配置、SELinux 安全管理
linux·tcp/ip·安全
不一样的故事1268 小时前
软件测试在未来10年
大数据·网络·人工智能·安全