Problem: [WUSTCTF 2020]Space Club
思路
- 初步文件分析: 首先观察
space.txt的内容。根据文件名和题目类型(MISC 编码),推测可能与空白字符隐写有关。 - 读取行长度: 逐行读取
space.txt文件内容,并计算每一行的长度(即其中包含的空格数量,忽略换行符)。 - 确定二进制映射: 每一行的长短对应一个二进制位,长空格是1,短空格是0,观察统计到的行长度分布。如果出现两种主要的长度(例如 6 和 12),则将较短的长度(6)映射为二进制 '0',将较长的长度(12)映射为二进制 '1'。
- 构建二进制字符串: 遍历文件的每一行,根据其长度(是短还是长),将其对应的二进制位追加到总的二进制字符串中。
- 二进制转字符: 将构建好的二进制字符串每8位一组,转换为对应的 ASCII 字符。
- 拼接获取 Flag: 将所有转换后的字符拼接起来,即可得到最终的 Flag。
EXP
def decode_space_steg(filename):
with open(filename, 'r', encoding='utf-8') as f:
lines = f.readlines()
# 1. 统计行长,帮助确定长短阈值
all_line_lengths = []
for line in lines:
stripped_line = line.strip('\n')
if stripped_line:
all_line_lengths.append(len(stripped_line))
unique_lengths = sorted(list(set(all_line_lengths)))
print(f"观察到的所有行长度: {unique_lengths}")
# 根据实际观察结果设置 len_short 和 len_long
# 假设观察结果是 [6, 12]
if len(unique_lengths) == 2:
len_short = unique_lengths[0]
len_long = unique_lengths[1]
print(f"检测到两种行长度: 短空格长度 = {len_short}, 长空格长度 = {len_long}")
else:
print("警告: 未检测到预期的两种行长度。请手动检查文件内容或调整逻辑。")
return "解码失败:行长度不符合预期。"
binary_string = ""
for line in lines:
stripped_line = line.strip('\n')
if not stripped_line:
continue # 忽略空行
current_len = len(stripped_line)
if current_len == len_short:
binary_string += '0'
elif current_len == len_long:
binary_string += '1'
else:
print(f"警告: 发现非预期行长度 {current_len} (行内容: '{repr(line)}'), 跳过此位。")
continue # 跳过不符合预期的行长度
if not binary_string:
return "未能提取到任何二进制位。请检查文件内容和行长定义。"
print(f"\n提取到的二进制字符串长度: {len(binary_string)}")
print(f"提取到的二进制字符串 (前50位): {binary_string[:50]}...")
# 2. 将二进制字符串转换为ASCII字符
decoded_text = ""
if len(binary_string) % 8 != 0:
print(f"警告: 二进制字符串长度 {len(binary_string)} 不是8的倍数。末尾可能缺失或多余数据。")
binary_string = binary_string[:len(binary_string) // 8 * 8]
print(f"已截断为长度 {len(binary_string)}")
for i in range(0, len(binary_string), 8):
byte = binary_string[i:i+8]
if len(byte) == 8:
try:
decoded_text += chr(int(byte, 2))
except ValueError:
print(f"错误: 无法将二进制 '{byte}' 转换为字符。可能不是有效的ASCII码。")
decoded_text += '[ERROR]'
else:
print(f"警告: 剩余的二进制位不足8位 ({len(byte)}位),无法构成完整字符。")
return decoded_text
# 假设 space.txt 文件与此脚本在同一目录下
flag = decode_space_steg('space.txt')
print("\n潜在的 Flag:", flag)
总结
- 考点: 该题目主要考察了对**文本隐写术 (Text Steganography)的理解和应用,特别是利用空白字符(Whitespace Steganography)**进行信息隐藏的技巧。
- 核心原理: 通过文件中不可见的或容易被忽视的细节(如不同数量的空格)来编码二进制信息。在本题中,行中空格的数量(即行的“长短”)被用作了二进制位 '0' 和 '1' 的载体。
- 分析方法:
- 文件内容观察: 首先通过文本编辑器或脚本检查文件内容是否纯文本,有无异常字符或特殊格式。
- 特征统计: 对于空白字符隐写,统计空格、制表符、行长等特征是关键。
- 模式识别: 从统计结果中找出规律,例如本题中观察到两种独特的行长度,从而确定二进制位的映射关系。
- 编程解码: 编写脚本是解决此类 MISC 题目的常用且高效的方法,能够自动化地进行数据提取和转换。
- 防范与思考: 这种隐写方式的隐蔽性在于其视觉上的不易察觉性。在实际场景中,除了空格,还可能利用零宽字符、行尾空格、多余的换行符等进行信息隐藏。
