當WORD宏病毒最早開始出現的時候,國內殺毒軟件廠商無一例外的陷入了束手無策的狀況,不像國外的大公司和微軟有非常好的合作,可以得到微軟的一些內部資料,國內廠商對於WORD文件的內部結構一無所知。爲了對付這種病毒,當時廠商想出了兩種方法:
第一種是使用WORD BASIC編寫程序檢測和清除病毒,實際上,WORD BASIC就是宏病毒本身使用的開發語言,開發人員利用WORD BASIC編寫自動加載的一小段代碼(從某種意義上來說,這也是一種病毒),打開任何WORD文件之前,首先檢查其中有沒有叫做“自動打開”,“自動保存”的宏存在,要是存在這些名字的宏就拒絕打開這個文檔。
第二種更加簡單,在分析了WORD文件的格式之後,開發人員很難發現這種文件的格式,所以採用了簡單的查找/替換方式,在整個WORD文件中搜索字符串,比如說搜索名字叫做“AutoOpen”的字符串,如果發現了這個字符串則把它清除爲空格,這樣WORD打開這個文件的時候,就不會再自動的運行這個宏了。
這兩種方式都存在很大的問題,第一種方法只能在WORD環境下運行,不啓動WORD對病毒就沒有任何辦法。第二種方式的問題更大,這種沒有搞清楚文件結構就進行病毒查殺是一種非常不負責的行爲,首先會造成大量的病毒誤報、漏報,把正常的WORD文件當成病毒,甚至如果寫一篇關於宏病毒的文章,裏面假設有這樣一句話:“宏病毒裏面經常包括了AutoOpen名字的宏”,採用這種方式查殺病毒之後,會發現“AutoOpen”這個單詞不見了,我的天啊,這樣也能叫殺病毒?至於殺過毒之後,造成WORD文件的數據損壞更是不勝枚舉。以至於一些廠商在隨後很長時間內,把“殺宏病毒不破壞文檔”這個對殺毒軟件的基本要求作爲產品的重大技術突破反覆宣傳。
“勞拉”文件格式:所有使用“勞拉”文件格式的文件由512字節的數據塊組成(你可以注意一下,所有的WORD、EXCEL、或者其他的Office文件大小都是512的倍數),數據塊的序號從-1開始:
複合文檔
|
|
|
|
|
|||||
512字節
|
512字節
|
序號爲-1的塊是整個文件的文件頭塊,存放了複合文件的一些整體信息,結構如下:
偏移量(十六進制) | 大小(字節) | 內容 |
0 | 8 | 複合文件標識(d0 cf 11 e0 a1 b1 1a e1) |
2C | 4 | 大塊映象圖的大小(塊數) |
30 | 4 | 目錄鏈根的開始塊序號 |
3C | 4 | 小塊映象圖的開始塊序號 |
4C | 不確定 | 大塊映象圖使用的塊的列表 |
在512字節的數據塊基礎上,複合文件中包括了兩種最基本的結構:
第一種是由512字節的大塊連接起來的大塊鏈,如果對以文件分配表(FAT)爲基礎的文件系統熟悉的話,可以很容易的理解大塊鏈的概念,只要知道一個大塊鏈的開始塊的序號,通過大塊映象圖,就可以找到這一條大塊鏈的所有內容。一個典型的大塊映象圖如下:
00200: fd ff ff ff 05 00 00 00 fe ff ff ff 04 00 00 00
00210: 06 00 00 00 fe ff ff ff 07 00 00 00 08 00 00 00
00220: 09 00 00 00 0a 00 00 00 0b 00 00 00 fe ff ff ff
00230: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
我們可以看到,如果一個大塊鏈的開始塊序號是0的話(該處的內容是5),那麼這個大塊鏈包括:序號爲0的數據塊、序號爲5的數據塊(該處的內容是7)、序號爲7的數據塊(該處的內容是9)、序號爲9的數據塊(該處的內容是0b)、序號爲0b的數據塊(該處的內容是-1,表示這是該鏈的最後一個數據塊)。
對於比較小的結構,如果以512字節爲單位的話會造成比較大的空間浪費,所以專門使用一個大塊鏈來存放比較小的數據塊,小於4096字節的數據結構使用小塊鏈來表示,小塊鏈的組成和尋址方法和大塊鏈非常類似,唯一不同的是,小塊鏈裏面對小塊的尋址不是在整個複合文件範圍內的,而是在某一個特定的大塊鏈範圍內的,這個大塊鏈的開始塊序號在後面敘述。
目錄鏈,目錄鏈是複合文件最基本的數據鏈,描述了複合文件的目錄結構信息。目錄鏈的開始在頭塊中可以找到。目錄鏈中包括了複合文件的目錄信息,每一個目錄項的大小是128字節,所以目錄鏈的一個塊可以包括4個目錄項,第一個目錄項是根目錄項,名字叫做“根實體”(Root Entry),任何複合文件裏面這都是第一個目錄項。一個典型的根目錄項如下:
00400: 52 00 6f 00 6f 00 74 00 20 00 45 00 6e 00 74 00 R o o t E n t
00410: 72 00 79 00 00 00 00 00 00 00 00 00 00 00 00 00 r y
00420: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00430: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00440: 16 00 05 00 ff ff ff ff ff ff ff ff 03 00 00 00
00450: 00 09 02 00 00 00 00 00 c0 00 00 00 00 00 00 46
00460: 00 00 00 00 00 00 00 00 00 00 00 00 86 29 f6 1f
00470: ad 57 bb 01 03 00 00 00 00 0f 00 00 00 00 00 00
目錄項結構的說明如下:
偏移量(十六進制) | 大小(字節) | 內容 |
0 | 40 | 目錄項的名字(所以複合文件中名字最長不能超過40字節) |
40 | 2 | 名字的長度 |
42 | 2 | 目錄項的類型1是一個存儲(文件),2是目錄,3是根 |
44 | 4 | 前一個目錄項 |
48 | 4 | 下一個目錄項 |
4C | 4 | 如果是目錄,指向子目錄項 |
74 | 4 | 所存儲內容的開始塊 |
78 | 4 | 所存儲內容的大小 |
由於上面的數據結構不是來源於微軟的官方文檔,包括了很多猜測的成分,所以很多內容暫時無法斷定其意義,有些結構的說明可能和微軟的原意也不相符合,但是我們使用這個結構對微軟的大量文檔進行了分析,至今尚未發現有明顯的錯誤存在。
在基本的“勞拉”文件結構的基礎上,字處理文檔、電子數據表文檔具有不同的內部目錄結構,下面是一個典型WORD文件的內部目錄結構:
1.doc
——1Table:一些數據表
——CompObj:通用的對象
——ObjectPool:對象池,是一個目錄,包括WORD文件中嵌入的圖像、聲音或者其他對象
——WordDocument:實際的文字和格式化信息就存放在這裏
——SummaryInforamtion:摘要信息
——DocumentSummaryInformation:其他的摘要信息