linux系统下file使用的magic文件格式说明

magic
本手册是file命令所使用的magic文件的格式说明文档,版本是5.04.
file命令用于识别文件类型,其他检测,检测文件内容中是否符合 'magic模式',也就是规则。
/usr/share/misc/magic 文件指定什么模式将被用于检测,当匹配到规则时什么信息或者MIME type将打印输出。从文件提取额外信息
文件每行都指定一个可执行的测试。一个测试比较的是在数据中的起始位置开始,在特定的偏移位置文件的字节值。一个字符串或者一个数字值。如果测试成功,将打印信息。magic文件中的行由以下字段构成
offset 
    一个数字说明偏移量,用字节,从数据文件中哪里开始检测
type 检测的数据的类型,可以是以下值:
    byte   一个字节值
    short  两个字节值在此计算机本机字节序
    long   四个字节值在此计算机本机字节序
    quad  八个字节值在此计算机本机字节序
    float   32位的单精度浮点数在此计算机本机字节序
    double   64位的双精度浮点数在此计算机本机字节序
    string   一个字符串字节,字符串类型说明可以随意跟 /[Bbc]*
            B标志压缩目标中的空格,必须包含至少一个空格字符。如果magic有n个连续的空白字符,目标需要至少n个连续的空格去匹配。
            b标志处理每个目标的空白字符作为一个可选空白
            c标志说明大小写不敏感的匹配,magic中的小写字符匹配目标的大写和小写字符,然而magic中的大写字符串仅仅匹配目标的大写字符。
    pstring  一个Pascal-style字符串第一个字节解释为无符号的长度。这个字符串不是以空结尾
    date  一个四字节的值,解释为一个UNIX日期
    qdate  一个八字节的值,解释为一个UNIX日期
    ldate   一个四字节的值,解释为一个UNIX-style日期,并且是解释为本地时间而不是UTC
    qldate  一个八字节值解释为一个UNIX-style日期,并且解释为本地时间不是UTC
     beid3  一个32位ID3长度以大端字节序表示
     beshort 一个两字节值以大端字节序表示
     belong  一个四字节值以大端字节序表示
     bequad  一个八字节值以大端字节序表示
     befloat  一个32位单精度浮点数以大端字节序表示
     bedoublt  一个64位双精度浮点数以大端字节序表示
     bedate  一个四字节值大端字节序表示,解释为一个Unix日期     
     beqdate  一个八字节值大端字节序表示,解释为一个Unix日期
      beldate  一个四字节值以大端字节序表示,解释为一个UNIX-style日期,并且解释为本地时间不是UTC
     beldate  一个八字节值以大端字节序表示,解释为一个UNIX-style日期,并且解释为本地时间不是UTC

     bestring16 一个两个字节unicode(UCS16)字符串以大端字节序表示

 
     leid3  一个32位ID3长度以小端字节序表示
     leshort 一个两字节值以小端字节序表示
     lelong  一个四字节值以大端字节序表示
     lequad  一个八字节值以小端字节序表示
     lefloat  一个32位单精度浮点数以小端字节序表示
     ledoublt  一个64位双精度浮点数以小端字节序表示
     bedate  一个四字节值小端字节序表示,解释为一个Unix日期     
     leqdate  一个八字节值小端字节序表示,解释为一个Unix日期
     leldate  一个四字节值以小端字节序表示,解释为一个UNIX-style日期,并且解释为本地时间不是UTC
     leldate  一个八字节值以小端字节序表示,解释为一个UNIX-style日期,并且解释为本地时间不是UTC
     lestring16 一个两个字节unicode(UCS16)字符串以小端字节序表示
 
     melong 一个四字节值以中端(PDP-11)字节序表示
     medate  一个四字节值以中端(PDP-11)字节序表示,解释为一个Unix日期   
     meldate 一个八字节值以中端(PDP-11)字节序表示,解释为一个UNIX-style日期,并且解释为本地时间不是UTC  
      indirect  在偏移的起始位置,再次查询magic数据库
      regex 一个匹配的正则表达式,使用扩展的POSXI正则表达式语法。正则表达式可以花费指数级时间在程序中。他们的效率很难被预测。所以尽量不要使用。当用在生产环境中他们的效率需要仔细检查。类型参数可以跟[c][s]任意一个。
                 c标志将使匹配大小写不敏感
                 s标志更新偏移量为匹配后偏移的起始位置,而不是最后。
       正则表达式再次检测前面的N+1行。N是已经知道的偏移量。行尾是假定匹配机器的本地格式。^和$分别匹配单独的行首和行尾,不是分解的开始和结尾
       search  搜索一个字面字符串从给定偏移的起始位置。相同的修饰符可以被使用做为字符串规则。如果有修饰符标志,必须根据/number范围内。也就是说,位置数量将要试图匹配,从起始位置开始偏移。这是适合搜索大的二进制表达式用变量偏移。特殊字符使用\ 转义。偏移量作为正则表达式。
         default  这个是打算用做测试 x (这个始终是真的)和一个消息时使用,如果这里不匹配
 
根据使用类型每个顶层的magic规则(看下面的层级说明)分为text和binary。类型 regex和search是被分为text测试,除非非打印字符被用做规则,所有其他测试都被分为binary类型。当一个顶级规则的所有规则是text规则,则把他考虑作为一个text测试,,否则看作是一个binary规则。匹配一个文件时,binary规则是最先尝试的,如果不匹配,并且文件看起来像文本并且编码确定,那将尝试文本模式。
numeric类型可能随意跟&和数字值,指定值被 AND'ed 用数值在匹配完成之前。头部添加一个 u 到类型表明要求比较应该是无符号类型的。
test 比较的值从文件中的值。如果类型是numeric,这个值指定为C格式,如果它是一个字符串,它是指定为一个C字符串允许用通常的转义(例如:\n 新行)
数字值可能在一个字符之前,表明操作被执行。他可能是
          =,文件指定值必须相等和指定值,
          <,文件中的指定值必须小于指定值
          >,文件中的指定值必须大于指定值
          &,文件中的指定值必须设置所有位设置为指定值
          ^,指定值从文件必须清除任何位设置在指定的值
          ~,值指定否定测试 
          x,指定任何值将匹配
          !,指定行匹配如果测试没有成功
如果字符被省略,他被假定为=,操作符&,^,~不能用于float和
double。
数字值被指定为C格式,例如:13是十进制,013是八进制,0x13是十六进制
对于字符串值,文件中的字符串必须匹配指定字符串。操作符=,<,>(除了&)可以被用在字符串。 长度用于在magic文件中字符串参数匹配。这意味着一行可以匹配任意非空字符串(通常使用打印字符串),用 >\0(因为所有的非空字符串是大于空字符串)。
特殊测试X通常指定为true,如果比较成功就打印信息。如果字符串中包含一个printf()格式的参数,文件中的值(使用任何指定的隐蔽完成)用格式化字符串打印输出。如果字符串以\b开始,信息打印剩余字符串用无空格补充,多个匹配通常用一个空格分开。
一个APPLE 4+4字符APPLE创建者和类型可以被指定为:
!:apple
 
creatype
一个MIME type是在单独一行,他必须是下一个非空或者注释行后magic行识别文件类型,有下面的格式:
!:mime  MIMETYPE

 

即,文字字符串 !:mime 跟着 MIME type
一个随机的strength可以被提供在单独的一行,他指定是当前的magic描述,使用下面的格式:
!:strength OP VALUE

 

操作符OP 可以是:+,-,*,/和VALUE一个0-255的常量。这个常量被用于指定操作数当前的计算机默认的magic strength。
一些文件格式包含额外信息打印文件类型。或者需要额外测试确定文件类型。这些额外的测试由一个或者跟多的>字符,在偏移之前。数字 数目 > 在行表明测试的等级,一行没有>在开始是考虑0级。测试是安排一个树形层级:如果一个测试一行在n级成功,所有一下测试在n+1级被完成。如果测试成功信息被打印。直到一行n级出现。更多的复合文件,一个可以使用空信息去获取"if/then"效果。用以下方法:
 

#在开始位置找到MZ
0 string MZ  

>0x18 leshort <0x40 MS-DOS executable 
>0x18 leshort >0x3f extended PC executable (e.g., MS Windows)
(>0x18)(找到了MZ继续则继续向下找,偏移0X18个字节找值小于0x40匹配)
 
偏移量不需要一定是常量,也可以从文件检查中读取。如果第一个字符跟着最后的>是一个括号,那么括号后的字符串是解释为一种间接抵消,那意味着括号后的数字被用作一个在文件中的偏移量,在偏移量处的值被读取,并被用作在文件中的偏移再次被使用。
间接偏移的格式:(( x [.[bislBISL]][+-][ y ]). )
x的值是用于在文件中的偏移量。一个字节,ID3长,short或者long是被读取在那个偏移量根据[bislBISLm] 类型说明,大写的类型解释数字作为一个大端值,反之小写类型解释为一个小端值。m类型解释数字作为中端值(PDP-11),
y的值,这个数字是额外的结果被用于文件中的偏移。如果没有指定默认类型是long。
 
这样可变长度结构可以被检查
# MS Windows executables are also valid MS-DOS executables
0           string  MZ
>0x18       leshort <0x40   MZ executable (MS-DOS)
# skip the whole block below if it is not an extended executable
>0x18       leshort >0x3f
>>(0x3c.l)  string  PE\0\0  PE executable (MS-Windows)
>>(0x3c.l)  string  LX\0\0  LX executable (OS/2)

 (0x3c.l):读取从开始偏移0x3c个字节位置的long长度的值(l的含义)用该值和PE\0\0做字符串的比较,如果相等就匹配

这种检测的方法有一个缺点,你必须确保你最终打印一些东西,或者用户可以获得空的输出(例如:上面的例子中当既不是PE\0\0 也不是LE\0\0)
如果间接的偏移不能被直接使用,简单计算可以是:附加 [+-*/%&|^]number

圆括号内允许一个去修改从文件中读取的值在他被用作一个偏移量之前。

 
# MS Windows executables are also valid MS-DOS executables
0           string  MZ
# sometimes, the value at 0x18 is less that 0x40 but there's still an
# extended executable, simply appended to the file
>0x18       leshort <0x40
>>(4.s*512) leshort 0x014c  COFF executable (MS-DOS, DJGPP)
>>(4.s*512) leshort !0x014c MZ executable (MS-DOS)

 

有时候你不知道前面字段确切的偏移,它取决于长度或者位置(当间接被使用之前)。你可以指定一个相对偏移最后高等级范围的末尾使用&作为一个前缀给偏移量
0           string  MZ
>0x18       leshort >0x3f
>>(0x3c.l)  string  PE\0\0    PE executable (MS-Windows)
# immediately following the PE signature is the CPU type
>>>&0       leshort 0x14c     for Intel 80386
>>>&0       leshort 0x184     for DEC Alpha

 相对位置偏移0字节(&0)

 

间接和直接偏移可以结合使用
0             string  MZ
>0x18         leshort <0x40
>>(4.s*512)   leshort !0x014c MZ executable (MS-DOS)
# if it's not COFF, go back 512 bytes and add the offset taken
# from byte 2/3, which is yet another way of finding the start
# of the extended executable
>>>&(2.s-514) string  LE      LE executable (MS Windows VxD driver)

 

或者其他方法:
0                 string  MZ
>0x18             leshort >0x3f
>>(0x3c.l)        string  LE\0\0  LE executable (MS-Windows)
# at offset 0x80 (-4, since relative offsets start at the end
# of the up-level match) inside the LE header, we find the absolute
# offset to the code area, where we look for a specific signature
>>>(&0x7c.l+0x26) string  UPX     \b, UPX compressed

 

或者甚至两个:
1 0                string  MZ
2 >0x18            leshort >0x3f
3 >>(0x3c.l)       string  LE\0\0 LE executable (MS-Windows)
4 # at offset 0x58 inside the LE header, we find the relative offset
5 # to a data area where we look for a specific signature
6 >>>&(&0x54.l-3)  string  UNACE  \b, ACE self-extracting archive

 

最后如果你不得不解决偏移/长度 组合在你的文件中,甚至第二个值在
括号表达式可以从文件自身,使用括号的另外一些设置。注意那是额外的间接偏移是经常相对主的间接偏移开始
1 0                 string       MZ
2 >0x18             leshort      >0x3f
3 >>(0x3c.l)        string       PE\0\0 PE executable (MS-Windows)
4 # search for the PE section called ".idata"...
5 >>>&0xf4          search/0x140 .idata
6 # ...and go to the end of it, calculated from start+length;
7 # these are located 14 and 10 bytes after the section name
8 >>>>(&0xe.l+(-4)) string       PK\3\4 \b, ZIP self-extracting archive

 

 匹配MP3文件的一个示例:

# MP3, M1A
# modified by Joerg Jenderek
# GRR the original test are too common for many DOS files
# so don't accept as MP3 until we've tested the rate
0       beshort&0xFFFE  0xFFFA
# rates
>2      byte&0xF0       0x10           MPEG ADTS, layer III, v1,  32 kbps
!:mime    audio/mpeg
>2      byte&0xF0       0x20           MPEG ADTS, layer III, v1,  40 kbps
!:mime    audio/mpeg
>2      byte&0xF0       0x30           MPEG ADTS, layer III, v1,  48 kbps
!:mime    audio/mpeg>2      byte&0xF0       0xA0           MPEG ADTS, layer III, v1, 160 kbps
!:mime    audio/mpeg
>2      byte&0xF0       0xB0           MPEG ADTS, layer III, v1, 192 kbps
用开始位置的数值的二进制值&(与)0xFFFE结果如果是0XFFFA就匹配,简化后可以这样
1  beshort&0xFE  0xFA

(>2 byte&0xF0 0x10):偏移2个字节的值&0xF0的值是对应0x10、0x20、0x30。。。任意一个都算匹配

 
posted on 2015-07-08 10:05  欢跳的心  阅读(5672)  评论(0编辑  收藏  举报