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。。。任意一個都算匹配
