MP3 Fuzz学习

  这篇文章主要是学习一波MP3格式fuzz的知识。目录如下

0x0.MP3格式的构成

0x0.MP3格式的构成

  MP3是一种通俗叫法,学名叫MPEG1 Layer-3。MP3是三段式的结构,依次由ID3V2、Frame、ID3V1构成。其中Frame为帧,这是MP3格式的基本单位,一个个的帧构成了整个MP3文件。先来看结构最简单的ID3V1,这个结构的大小是固定的,共128字节。可见都是一些MP3的相关信息如作者、标题之类的。

typedef struct tagID3V1
{
    char Header[3];        //固定为"TAG"
    char Title[30];        //标题
    char Artist[30];    //作者
    char Album[30];        //专辑
    char Year[4];        //出品年代
    char Comment[28];    //备注
    char reserve;        //保留
    char track;            //音轨
    char Genre;            //类型
}ID3V1,*pID3V1;

接下来是存放数据的Frame帧结构。其中FrameHeader一共4个字节共32位,这32位是当作标志来用的,就是说每个位对应不同的意义。其中CRC域有可能不存在,这是有FrameHeader中的位决定的。而且FrameHeader中的帧头记录的MainData的大小。

typedef struct _FRAME
{
    char FrameHeader[4];//每个帧都有一个4字节的帧头
    char CRC[2];        //帧头第16字节决定是否存在CRC
    char MainData[?];    //帧头决定大小
}FRAME,*PFRAME;

FrameHeader定义为AAAAAAAAAAA BB CC D EEEE FF G H II JJ K L MM,不同字母代表不同意义的域。以下是这些域的意义。

A-11   帧同步
B-2    表示版本,有1、2、2.5三种
C-2    表示Layer版本,即mp1、mp2、mp3
D-1    决定是否有CRC
E-4    表示比特率
F-2    表示采样率
G-1    表示填充位
H-1    保留
I-2    表示声道
J-2    立体声的扩展模式
K-1    是否有版权信息
L-1    是否是原创
M-2    强调

前面已经说过了Frame的大小是由FrameHeader来决定的,

下面来看下ID3V2标签,ID3V2标签是MP3文件的第一个标签,由一个标签头和若干个标签帧构成。其中标签头如下所示

typedef struct tagID3V2
{
    char Header[3];//固定为"ID3"
    char Ver;       //记录版本号,3表示ID3V2.3
    char Revision; //副版本号,这里为0
    char Flag;       //定义标识位
    char Size[4];  //定义标签大小,包括这10个字节
}ID3V2,*PID3V2;Size算法是每个字节取后7位来组成28位数字,作为大小的值。
typedef struct Header
{
    char FrameID[4];//帧标识,说明这个帧的含义
    char Size[4];   //帧内容的大小,不包括帧头,不得小于1
    char Flags[2];  //存放标识
}HEADER;Size是32位的大小值

ID3V2的大小只取每个字节的前位进行计算,作为ID3V2块的总大小进行计算。

如上所示每个ID3V2所属的标签还有其他的标签头,每个小标签头所表示的标签具有一定的含义,含义由FrameID决定,下面列出了一些常见的FrameID。size的计算法就是当成4个字节的DWORD来计算的。Flag和FrameID更多的值可以在附件的PDF里面看。

1 TIT2 标题
2 TPE1 作者
3 TALB 专集
4 TRCK 音轨
5 TYER 年代
6 TCON 类型
7 COMM 备注

0x1.MP3格式的脆弱点

前面主要是介绍了一下MP3文件的文件格式,这里在就要对MP3文件格式进行FUZZING之前要搞清楚的一点是MP3文件的脆弱点在哪里,就是说哪里是可能出现问题的地方,搞清楚这一点对于Fuzzing样本的生成也有很大的好处。而且有一个问题就是MP3的帧大小问题。我们前面已经知道了一个MP3是由许多帧构成的,但是注意帧头中并没有size域,因为一个帧的大小是由比特率和采样率算出来的,而比特率和采用率储存在帧头中分别为E、F。计算公式如下。

帧长度(字节)= 每帧采样数 / 采样率(HZ) * 比特率(bps)/8 + 填充
例:LayerIII 比特率 128000,采样率 44100,填充0 =〉帧大小 417字节

这样来说还有一个简单的公式(144*比特率)/采样率+填充位注意,比特率是以k为单位的,比如128是128k的比特率。

MPEG1


MPEG2


MPEG2.5


Layer1


384


384


384


Layer2


1152


1152


1152


Layer3


1152


576


576



【每帧采【每帧采样数表】


这样就有一个问题了,我们要不要对E、F进行随机生成呢?如果也对E、F进行随机生成那么帧大小就会乱掉了。但是如果不随机生成的话,那么这几个域就固定了。这点我还没想明白怎么搞的。

下面提供了一个解析MP3文件操作的步骤

解析方法
当你想读取MPEG文件的信息时,解析前三个字节,判断是否有ID3V2标签,有则根据上面的方法算出ID3V2标签的总大小,这样就找到了音频数据帧的第一帧,读取它的头信息,获取比特率、采样率、MPEG版本号、Layer描述号等信息,根据上面提供的方法算出每帧的长度和每帧持续时间,对于定比特率的其它帧是相同的,也就是说解析第一帧就达到了目的。但这也不是所有情况。变比特率的MPEG文件使用使用所谓比特变换,也就是说每一帧的比特率依照具体内容变化。这时就需要你每一帧都解析。

这个解析步骤是从网上看到的,我不知道有哪些的解码器是用这种方法解码的,但是我们可以根据上面提供的这个操作猜测出一些信息。首先IDV2的size标签域不能随意生成,因为如果随意生成这个域的话,那么就没有办法定位到第一帧了,那么这个mp3文件就整个乱掉的了,对于这种情况估计播放器会直接说文件损坏根本起不到测试的效果了。与此类似的是数据帧的比特率和采样率也不能随意生成,因为这两个值是用来计算数据帧大小用的,如果随意生成那么帧的大小就会计算错误,根据上面的解析方法可以解析的方法就是逐大小往下移,如果一个帧的大小计算不对,那么整个mp3的解析都会出现问题。这样同样就是无法达到测试的效果的。但是如果都是动态生成呢?我觉得当然是可以的了,但是数据的逻辑关系就太复杂了。尤其是很蛋疼的有一个按位的运算,这个直接用标签好像难以实现的,应该需要内嵌pyhon脚本来实现。目前还不知道该怎么搞,所以先生成固定长度的内容。

时间: 2024-11-08 21:42:51

MP3 Fuzz学习的相关文章

ANDROID_MARS学习笔记_S01原始版_023_MP3PLAYER003_播放mp3

一.简介 1.在onListItemClick中实现点击条目时,跳转到PlayerActivity,mp3info通过Intent传给PlayerActivity 2.PlayerActivity通过android.media.MediaPlayer实现播放,暂停.停止 二.代码1.xml(1)player.xml 1 <?xml version="1.0" encoding="utf-8"?> 2 <LinearLayout xmlns:andr

【C#学习笔记】播放wma/mp3文件

using System; using System.Runtime.InteropServices; namespace ConsoleApplication { class Program { [DllImport("winmm.dll")] public static extern uint mciSendString(string lpstrCommand,string lpstrReturnString, uint uReturnLength, uint hWndCallba

Intent学习

1.Intent是什么 Android中提供了Intent机制来协助应用间的交互与通讯,Intent负责对 应用中一次操作的动作.动作涉及数据.附加数据进行描述,Android则 根据此Intent的描述,负责找到对应的组件,将 Intent传递给调用的组 件,并完成组件的调用. Intent不仅可用于应用程序之间,也可用于应用程序内部的Activity/Service 之间的交互.因此,Intent在这里起着一个中介的作用,专门提供组 件互相调用的相关信息,实现调用者与被调用者之间的解耦. 2

我的算法学习之路

关于 严格来说,本文题目应该是我的数据结构和算法学习之路,但这个写法实在太绕口--况且CS中的算法往往暗指数据结构和算法(例如算法导论指的实际上是数据结构和算法导论),所以我认为本文题目是合理的. 这篇文章讲了什么? 我这些年学习数据结构和算法的总结. 一些不错的算法书籍和教程. 算法的重要性. 初学 第一次接触数据结构是在大二下学期的数据结构课程.然而这门课程并没有让我入门--当时自己正忙于倒卖各种MP3和耳机,对于这些课程根本就不屑一顾--反正最后考试划个重点也能过,于是这门整个计算机专业本

varnish简单学习

操作系统:redhat5.5 前端服务器:varnish cache 2.1.5 监听端口8080 后端服务器:tengine 1.4.6 监听端口80 接着,建立varnish用户以及用户组,并且创建Varnish缓存目录和日志目录:[[email protected] ~]#useradd  -s /sbin/nologin varnish[[email protected] ~]#mkdir /data/varnish/cache[[email protected] ~]#mkdir /d

学习Python的day1

自己以前从来没有写博客的想法,但是学Python,里面的老师也说了,写博客可以加深自己的记忆,也能回顾内容.还能给别人参考.挺值的.2017-09-16 一. Python介绍 python的创始人为吉多·范罗苏姆(Guido van Rossum).1989年的圣诞节期间,吉多·范罗苏姆为了在阿姆斯特丹打发时间,决心开发一个新的脚本解释程序,作为ABC语言的一种继承. 最新的TIOBE排行榜,Python赶超PHP占据第五, Python崇尚优美.清晰.简单,是一个优秀并广泛使用的语言. Py

JavaWeb的学习--Response

1.HttpServletResponse概述 我们在创建Servlet时会覆盖service()方法,或doGet()/doPost(),这些方法都有两个参数,一个为代表请求的request和代表响应response. service方法中的response的类型是ServletResponse,而doGet/doPost方法的response的类型是HttpServletResponse,HttpServletResponse是ServletResponse的子接口,功能和方法更加强大,今天

iOS学习笔记12-网络(一)NSURLConnection

一.网络请求 在网络开发中.须要了解一些经常使用的请求方法: GET请求:get是获取数据的意思,数据以明文在URL中传递,受限于URL长度,所以数据传输量比較小. POST请求:post是向server提交数据的意思.提交的数据以实际内容形式存放到消息头中进行传递,无法在浏览器url中查看到,大小没有限制. HEAD请求:请求头信息,并不返回请求数据体,而仅仅返回请求头信息,经常使用用于在文件下载中取得文件大小.类型等信息. 二.NSURLConnection NSURLConnection是

android多媒体框架学习 详解 最新版本

一:多媒体框架概述   jellybean 的多媒体跟以前的版本,通过对比没啥变化,最大的变化是google终于舍得给multimedia建个独立的git了(framework/av),等你好久了!也体现了media 在整个android系统中的重要性!framework/av下都是些C/C++代码(libmedia,libmediaplayerservice,libstagefright),jni和 java api 还是保留在原来的位置,改革还不够彻底,但还是迈出了这一步,以后维护能更好的进