知识点:
typedef FrameHeader
{ //数字代表大小,单位bite
unsigned int sync:12; //同步信息
unsigned int version:2; //版本
unsigned int layer: 2; //层
unsigned int error protection:1; // CRC校验
unsigned int bitrate_index:4; //位率
unsigned int sampling_frequency:2; //采样频率
unsigned int padding:1; //帧长调节
unsigned int private:1; //保留字
unsigned int mode:2; //声道模式
unsigned int mode extension:2; //扩充模式
unsigned int copyright:1; // 版权
unsigned int original:1; //原版标志
unsigned int emphasis:2; //强调模式
}
-
帧长度是压缩时每一帧的长度,包括帧头的4个字节(32bit)。它将填充的空位也计算在内。
-
padding的值会影响每一帧的长度(具体分析见下面的题目)
将解压后的mp3
文件用 010Editor (winhex等) 打开
分析详见图片
通过观察可知,private bit的数值在0和1中变化,但多看一些 mf[] 发现,大部分是 0,应该不会有什么有效的信息,再看copyright 也是在 0 和 1 发生改变,去查资料,copyright代表着版权,应该是固定不变的值,所以copyright中应该有flag或者重要的信息,先提取出copyright
具体脚本如下:
import re
n = 984486 # 起始位置(是padding的起始位置)
result = ''
files = open('2.mp3', 'rb') # 以二进制打开文件
# 提取
while n < 12658083: # 结束位置
files.seek(n, 0)
head = files.read(1) #读取 一个 字节(8位),见上图呀
# print(head,end='')
padding = '{:08b}'.format(ord(head))[-2] # 该字节的倒数第二位是padding的值
# print(padding) 检验padding 值提取是否有误
files.seek(n + 1, 0)
file_read_result = files.read(1)
result += '{:08b}'.format(ord(file_read_result))[-4]
# print(len(bin(ord(file_read_result))))
# result += bin(ord(file_read_result))[-4]
# n += 1045 if padding == "1" else 1044 # 高级写法
# 普通写法
if padding == "0":
n += 1044
else:
n += 1045
# print(result)
# 拼接
flag = ''
textArr = re.findall('.{' + str(8) + '}', result)
for i in textArr:
flag = flag + chr(int(i, 2)).strip('n')
print(flag)
脚本分析:
第3行的 n 为起始位置(padding的起始位置) 通过 010Editor 可知,mp3文件的头帧起始位置是235984(用十进制表示)、由下面的两张图片可以得到第一帧的起始位置 由上面的大图可以知道,每一帧的大小是32bit(即4字节),sync、mpeq id、layer id、protection id共占了16bit(即2字节),所以padding的起始位置是头帧的起始位置 加2,即235986
第7行的 结束位置 (拉到最下面,方法同上)
第 19 ~ 22 行,增加的值取决于 帧长(大小,用十进制表示,如下图的蓝框),其大小还与padding的值有关
第 8 行:seek(offset,x) -> 移动文件读取的指针到指定位置 offset:是偏移量,也就是要移动的字节数,如果是负数,就是从后往前 x:可选,默认为 0 ,【0表示从头开始,1表示从当前位置开始,2表示从文件尾开始】
第 9 行:read([size])读取文件内容 size:可选,代表从文件读取的字节数,默认为-1,表示读取整个文件
第 11 行:获取padding对应的值
ord() -> 返回对应字符的十进制整数
format(num) -> 将括号里的整数 num 转换为对应到进制
{:08b} -> 域宽为 8 ,不足八位就 补 0,b代表是 二进制
第13行:将文件读取的指针向下移动一个字节(看第一张图可以知道,copyright位于每一帧(4字节)的第四个字节中的第 5 个bite【注意:从零开始计数】(倒数第四个同理)(该MP3中,具体情况具体分析)
第26 ~ 30行,就是正则表达式库(re库)函数的用法了
链接:
http://jzcheng.cn/archives/146.html
https://blog.tms.im/2021/03/30/ctf-mp3-copyright-bit.html
原文始发于微信公众号(搁浅安全):MP3文件隐写之Copyright位
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论