網(wǎng)站的數(shù)據(jù)庫怎么建立太原seo
文章目錄
- 復合文檔二進制解析
- 復合文檔數(shù)據(jù)結構解析
- 準備工作
- 基礎知識
- Header
- FAT
- Directory
- 補充
- 宏代碼數(shù)據(jù)結構解析
- 說明
目前主流殺軟在處理宏病毒時,都是直接刪除含有宏病毒的文檔,這樣處理顯得有些粗暴,將導致用戶無法查看文檔里的數(shù)據(jù),如果是一些重要的業(yè)務數(shù)據(jù),將造成業(yè)務數(shù)據(jù)的丟失,產(chǎn)生無法估計的后果。本文將介紹一種宏病毒處理思路,在不刪除文檔文件的情況下清除宏病毒。
復合文檔二進制解析
在正式處理宏病毒前,我們必須對Office文檔的數(shù)據(jù)結構以及宏的數(shù)據(jù)結構有著初步的了解。
復合文檔數(shù)據(jù)結構解析
Office文檔(如:.doc、.ppt、.xls等)很多是復合文檔(OLE文件),所有文件數(shù)據(jù)都是存儲在一個或多個流中。每個流都有一個相似的數(shù)據(jù)結構,用于存儲元數(shù)據(jù)的數(shù)據(jù)結構。這些元數(shù)據(jù)有用戶和系統(tǒng)的信息、文件屬性、格式信息、文本內(nèi)容、媒體內(nèi)容。宏代碼信息也是以這種方式存儲在復合文檔中的。為了在Office文檔文件中提取出宏代碼,必須能夠解析復合文檔的二進制格式,下面以word為例,分析復合文檔的二進制結構。
準備工作
(1)準備工具:
Office Visualization Tool:微軟提供的office二進制格式查看工具,用于學習doc,xls,ppt等文檔二進制格式;
010Editor:一款流行的二進制編輯器。
(2)doc、docx和docm
? 許多用戶在新建word文檔時會發(fā)現(xiàn)有兩個選項,新建Microsoft Word 97 - 2003 文檔和新建新建 Microsoft Word文檔。當用戶點擊新建Microsoft Word 97 - 2003 文檔時,就會創(chuàng)建出一個.doc文件;而用戶點擊新建Microsoft Word 文檔時,就會創(chuàng)建出一個.docx文件,實際上Microsoft Word 2007及之后的Word版本還支持.docm文件,那么這三種文件有什么區(qū)別呢?.doc文件是一種普通的OLE文件(復合文件),能夠包含宏。而.docx和.docm文件,實際上都是是壓縮文件,下圖是.doc文件.docx和.docm文件頭二進制數(shù)據(jù)的對比圖:
將docx.docx文件的文件名修改為docx.zip就可以以壓縮包的形式打開.docx文件,如圖所示:
實際上.docx主要的內(nèi)容基本都存在于word目錄下,比較重要的有以下的內(nèi)容:
-
document.xml:記錄Word文檔的正文內(nèi)容
-
footer*.xml:記錄Word文檔的頁腳
-
header*.xml:記錄Word文檔的頁眉
-
comments.xml:記錄Word文檔的批注
-
footnotes.xml:記錄Word文檔的腳注
-
endnotes.xml:記錄Word文檔的尾注
利用同樣的方式打開.docm文件,可以發(fā)現(xiàn)和.docx文件的內(nèi)容基本相同,但是比.docx文件多了一個文件:
vbaProject.bin:這是一個復合文件,記錄vba工程信息
基礎知識
OLE文件數(shù)據(jù)的存儲結構和磁盤數(shù)據(jù)的存儲結構有很大的相似性,都是以扇區(qū)為單位進行存儲的,但二者的扇區(qū)是截然不同的。
對于一個doc文件,其實質(zhì)是一復合二進制文件(OLE文件),用Office Visualization Tool載入.doc文件,可以看到清晰的文件結構,如圖所示:
首先是文件頭Header,是固定的512字節(jié)。Header中記錄著文件解析必須的所有參數(shù)。Header之后的區(qū)域是不同的Sector。
Sector(扇區(qū)),一般是512字節(jié),是實際數(shù)據(jù)存儲的地方,復合文檔中數(shù)據(jù)都是以扇區(qū)為單位進行存儲的。扇區(qū)有兩種Sector和Mini-Sector(Sector:扇區(qū),一般是512字節(jié);Mini-Sector:短扇區(qū),64字節(jié))。扇區(qū)內(nèi)存儲的數(shù)據(jù)有種類有Stroage、Stream、Directory、FAT、Mini-FAT(屬于Mini-Sector)、DIF等,但每個扇區(qū)中只能存儲一種數(shù)據(jù)類型。每個Sector都有一個SectorID,但是Header所在的扇區(qū)ID是-1,并不是0。Header后的Sector才是“第一個”Sector,其SectorID為0[22]。
Storage與Stream的功能相當于文件系統(tǒng)中的文件夾與文件的功能。Storage中是沒有任何“實質(zhì)性”的內(nèi)容的,只會記錄其包含的Stream和Storage,是一個Stream和Storage的目錄?!皩嵸|(zhì)性”的內(nèi)容全在Stream里面。
Directory,中文“目錄”,和Storage的“目錄”功能有著很大區(qū)別,Directory是一個Storage和Stream的索引。這一部分存儲空間是用來記錄Storage和Stream的存儲結構以及名稱、大小、起始地址等信息。
FAT是索引表。數(shù)據(jù)在硬盤上的存儲是離散的,需要有一個索引表能找到這些數(shù)據(jù),索引表中存放著數(shù)據(jù)的起始地址(即扇區(qū)的),其實每一條索引也是離散的,索引中一般還有一條數(shù)據(jù)指向下一條索引,類似于鏈表。FAT實際記錄了該扇區(qū)指向的下一個扇區(qū)的地址。
DIFAT是分區(qū)表,是FAT的索引表。FAT也是存儲在Sector里面,但是FAT本身也比較大,所以利用DIFAT作為FAT的索引表,記錄了FAT所在的Sector的起始地址以及邏輯關系
每個扇區(qū)占據(jù)512字節(jié),Header占據(jù)一個扇區(qū)。除去文件頭外,扇區(qū)ID從0開始。若要讀取某個扇區(qū)的信息,可以采用以下的公式:
扇區(qū)ID x 扇區(qū)大小 + 512
但是要長扇區(qū)和短扇區(qū),默認扇區(qū)是長扇區(qū),長扇區(qū)大小為512字節(jié),短扇區(qū)大小是64字節(jié)。
Header
復合文檔的文件的頭Header是固定的512字節(jié),其中每一個字節(jié)都有十分重要的含義。圖所示的是一個doc文件的Header部分:
下表是對圖中這512字節(jié)的解析:
字節(jié)偏移 | 說明 |
---|---|
0x00H~0x07H | 8個字節(jié):固定值:0xD0 0xCF 0x11 0xE0 0xA1 0xB1 0x1A0xE1,表示此文件是復合文件 |
0x08H~0x17H | 16個字節(jié):ClassID,不過很多文件都置0 |
0x18H~0x19H | 2個字節(jié):一般為0x3E,表示文件格式的修訂號 |
0x1AH~0x1BH | 2個字節(jié):一般為0x3,表示文件格式的版本號 |
0x1CH~0x1DH | 2個字節(jié):一般0FE 0xFF,表示文檔使用的存儲格式是小端模式(理論上0xFF 0xFE則表示大端存儲方式) |
0x1EH~0x1FH | 2個字節(jié):默認值:0x09 0x00,表示Sector的大小,當值為9時,即每個Sector為512(29)字節(jié) |
0x20H~0x21H | 2個字節(jié):默認值:0x06 0x00,表示Mini-Sector的大小,當值為6時,即每個Mini-Sector為64(26)字節(jié) |
0x22H~0x23H | 2個字節(jié),UInt16,預留值,置0 |
0x24H~0x27H | 4個字節(jié),UInt32,預留值,置0 |
0x28H~0x2BH | 4個字節(jié):表示目錄扇區(qū)Directory Sectors的數(shù)量的數(shù)量;若版本號為3,則該值為0 |
0x2CH~0x2FH | 4個字節(jié):表示FAT的數(shù)量 |
0x30H~0x33H | 4個字節(jié):表示Directory開始的SectorID文件目錄流的起始扇區(qū)編號 |
0x34H~0x37H | 4個字節(jié):一般置0,用于事務 |
0x38H~0x3BH | 4個字節(jié):表示ulMiniSectorCutoff,是最小串(Stream)的最大大小,默認為4096(0x00 0x10 0x00 0x00) |
0x3CH~0x3FH | 4個字節(jié):_sectMiniFatStart ,是MiniFAT表開始的SectorID |
0x40H~0x43H | 4個字節(jié):表示MiniFAT表的數(shù)量 |
0x44H~0x47H | 4個字節(jié):表示DIFAT開始的SectorID,DIFAT的起始扇區(qū)編號 |
0x48H~0x4BH | 4個字節(jié):表示DIFAT的數(shù)量 |
0x4CH~0x1FFH | 436個字節(jié):UInt32,包含了109個DIFAT,每個DIFAT占用4個字節(jié),是前109塊FAT表的SectorID。Header中存儲的了109個DIFAT數(shù)據(jù)。但是有時候109個還不夠,這時候可以使用其它扇區(qū)專門存儲DIFAT數(shù)據(jù),0x44H~0x47H中記錄的就是除這109項外,其他的DIFAT數(shù)據(jù)的起始扇區(qū)編號。在DIFAT扇區(qū)的最后4個字節(jié),存儲了下個DIFAT扇區(qū)的ID,以表示下個DIFAT數(shù)據(jù)的存儲位置 |
FAT
FAT實際記錄了該扇區(qū)指向的下一個扇區(qū)的地址。
前文已述一個扇區(qū)能且只能存放一種類型的數(shù)據(jù),但是復合文檔怎么知道扇區(qū)中存儲的是哪一種類型的數(shù)據(jù)?因而在復合文檔的FAT數(shù)據(jù)中,除了表示扇區(qū)ID的數(shù)字,還有些特殊的數(shù)字ID表示一些特定的扇區(qū),詳細介紹見表:
類型 | ID值 | 描述 |
---|---|---|
REGSECT | 0x00000000-0xFFFFFFF9 | 正常的數(shù)據(jù)扇區(qū)ID,表示下一個數(shù)據(jù)扇區(qū) |
MAXREGSECT | 0xFFFFFFFA | 扇區(qū)ID最大值 |
Not applicable | 0xFFFFFFFB | 保留扇區(qū)ID |
DIFSECT | 0xFFFFFFFC | DIFAT扇區(qū)ID,表示該扇區(qū)存儲了DIFAT的數(shù)據(jù) |
FATSECT | 0xFFFFFFFD | FAT扇區(qū)ID,表示該扇區(qū)存儲了FAT的數(shù)據(jù) |
ENDOFCHAIN | 0xFFFFFFFE | 結束字符 |
FREESECT | 0xFFFFFFFF | 空扇區(qū)ID |
一個扇區(qū)大小為512字節(jié),一組FAT信息占據(jù)4個字節(jié)。因而一個FAT扇區(qū)中,最多能夠存放128組FAT信息,可以利用DIFAT列表把不同的FAT扇區(qū)串聯(lián)起來。FAT信息在一個扇區(qū)內(nèi)部的存儲都是連續(xù)的。比如某個FAT扇區(qū),第1組FAT信息代表的扇區(qū)的ID是3的話,則這個扇區(qū)可以表示的扇區(qū)ID范圍是3到131。
MINIFAT的解析,其方法和FAT類似,其起始扇區(qū)ID存放在Header信息中,MINIFAT表的順序,當記錄在FAT中,這里就不贅述了
Directory
復合文檔從字面上理解就是很多內(nèi)容放在一起復合形成文檔,這么多內(nèi)容當然需要有個目錄,而Directory就是這個目錄。Directory起始的SectorID需要從Header中讀取,定位的方法在上文中提到(512+ 扇區(qū)大小 * 扇區(qū)ID)。Directory中每個DirectoryEntry固定為128字節(jié),其主要結構如表所示:
偏移 | 描述 |
---|---|
0x00H~0x3FH | 64個字節(jié):存儲DirectoryEntry名稱的,并且是以Unicode存儲的,即每個字符占2個字節(jié), |
0x40H~0x41H | 2個字節(jié):DirectoryEntry名稱的長度(包括最后的“\0”) |
0x42H~0x42H | 1個字節(jié):是DirectoryEntry的類型。0為非法,1為目錄(storage),2為節(jié)點(Stream),5為根節(jié)點(Root Entry即第一個目錄內(nèi)容) |
0x43H~0x43H | 1個字節(jié):節(jié)點的顏色 |
0x44H~0x47H | 4個字節(jié):該DirectoryEntry左兄弟的EntryID(第一個DirectoryEntry的EntryID為0,下同) |
0x48H~0x4BH | 4個字節(jié):該DirectoryEntry右兄弟的EntryID |
0x4CH~0x4FH | 4個字節(jié):該DirectoryEntry一個孩子的EntryID |
0x50H~0x5FH | 16個字節(jié):表示CLSID |
0x60H~0x63H | 4個字節(jié):表示UserFlags,一般是0 |
0x64H~0x6BH | 8個字節(jié):表示文件創(chuàng)建時間 |
0x6CH~0x73H | 8個字節(jié):表示文件修改時間 |
0x74H~0x77H | 4個字節(jié):表示該DirectoryEntry開始的SectorID |
0x78H~0x7BH | 4個字節(jié):是該DirectoryEntry存儲的所有字節(jié)長度 |
0x7CH~0x7FH | 4個字節(jié):保留置0 |
Directory為Storage的有clsid、time、和sidChild,stream可能沒有。Stream有個有效的sectdtart和ulsize,但是storage的是0。
當usize小于ulMiniSectorCutoff時,表示stream使用的是MiniFat。常見的Directory有很多,比較重要的有root entry、WordDocument、1Table、SummaryInformation、DocumentSummaryInformation、Macros和Vba。root entry是Directory里的第一個內(nèi)容,只是作為根節(jié)點,有些文檔中直接命名為R,接下來的介紹WordDocument、1Table、SummaryInformation、DocumentSummaryInformation、Macro都是位于root entry節(jié)點下的,其中Vba位于Orphaned節(jié)點下。DocumentSummaryInformation和SummaryInformation是摘要信息。對于DocumentSummaryInformation,其結構如表所示:
對于每個屬性組,其結構如下:
1.0x00H~0x03H:是屬性組大小。
2.0x04H~0x07H:是屬性組中屬性的個數(shù)。
3.從008H開始的每8字節(jié),是屬性的信息:
? 前4字節(jié):屬性的種類。
? 后4字節(jié):屬性內(nèi)容相對于屬性組的偏移。
常見的屬性編號如表所示:
屬性 | 值 | 屬性 | 值 |
---|---|---|---|
Unknown | 0x00 | Scale | 0x0B |
CodePage | 0x01 | HeadingPairs | 0x0C |
Category | 0x02 | DocumentParts | 0x0D |
PresentationTarget | 0x03 | Manager | 0x0E |
Bytes | 0x04 | Company | 0x0F |
LineCount | 0x05 | LinksDirty | 0x10 |
ParagraphCount | 0x06 | CountCharsWithSpaces | 0x11 |
Slides | 0x07 | SharedDoc | 0x13 |
Notes | 0x08 | HyperLinksChanged | 0x16 |
HiddenSlides | 0x09 | Version | 0x17 |
MMClips | 0x0A | ContentStatus | 0x1B |
對于每個屬性,其結構如下:
1.0x00H~0x03H:屬性內(nèi)容的類型,值有:
0x02表示UInt16
0x03表示UInt32
0x0B表示Boolean
0x1E表示String
2.屬性組中剩下的字節(jié)是屬性的內(nèi)容,當屬性組中內(nèi)容類型是String時,剩下字節(jié)不定長,剩下三種類型都是4個字節(jié)(多余字節(jié)置0)。
“WordDocument”和“1Table”是專門存儲文檔內(nèi)容的DirectoryEntry。需要說明的是,Word中的存儲文檔內(nèi)容的DirectoryEntry與PowerPoint和Excel中都不同,Word中是“WordDocument”和“1Table”,PowerPoint是“PowerPoint Document”,Excel是“Workbook”。
對于WordDocument,其最重要的應該是其中包含的FIB(File Information Block)了,FIB位于WordDocument的開頭,其包含著Word文件非常重要的參數(shù),諸如文件的加密方式、文字的編碼等等。
FIB是可變長的,開頭是固定32字節(jié)長的FibBase:
0x00H~0x01H:0xA5EC(0xEC 0xA5),表示W(wǎng)ord二進制文件。
0x02H~0x03H:一般是0xC1,表示W(wǎng)ord97版本,表示最低版本
0x0AH~0x0BH:16bit,被分成了13部分。除了第5部分占了4bit外,其余12部分各站1bit,總計16bit。說明下13部分是如何分配的,最左為最低位。
A:為文檔是否是.Dot文件(Word模板文件)
B:目前該位沒有解析出含義。
C:文檔快速保存時生成的格式。
D,文檔中是否存在圖片。
E,快速保存的次數(shù)。
F,文檔有沒有加密。
G,文字存儲的位置,為1表示1Table,為0表示0Table。
H,是否只讀方式代開
I,是否含有寫保護密碼。
J,固定值1。
K,應用程序默認的語言和字體。
L,文檔語言是東亞語言。
M,文檔加密方式,1表示異或混淆,0則是其他加密方式;如果文檔未加密則忽略該值。
0x0CH~0x0DH:一般為0x00BF,少數(shù)是0x00C1。
0x0EH~0x11H:文檔加密的密鑰;否則應置0。
0x12H~0x12H:置0。
0x13H~0x13H:16bit被劃分為6部分
第1位:0。
第2位:新建文件的方式。
第3位:頁面默認的格式。
第4位:忽略
第5位:忽略。
第6-8位:忽略。
014H~017H:置0,忽略。
018H~01FH:忽略。
FIB中內(nèi)容仍然有很多,但是了解上述內(nèi)容就可以讀取文檔的內(nèi)容,之后的部分就不再介紹了。
“1Table”和“0Table”也是存儲文檔內(nèi)容的目錄,有時候也被叫做Table Stream,Table Stream其實是他們的總稱,根據(jù)FIB中的信息判斷文字存于“1Table”還是“0Table”。但是目前仍然不知道文字存儲與哪一個扇區(qū)中。這些信息都存放在Table Stream中的Piece Table中,Piece Table的位置可以從FIB中獲取到。Piece Table,其結構為:
0x00H~0x00H:固定值0x02,Piece Table的標識。
0x01H~0x04H:是Piece Table的大小。
Piece Table中數(shù)量的計算公式:
n=(Piece Table的大小 - 4)/(4 + Piece Element的大小)
隨后的4*(n + 1)個字節(jié),存儲Piece Element中存儲的文本的開始位置(結束位置即下一個的開始位置)。
之后的8*n個字節(jié),存儲每個Piece Element的信息。
由此可以獲取Word中文本的存儲位置,文字是按下面的順序存儲的:
正文內(nèi)容(Main document)
腳注(Footnote subdocument)
頁眉和頁腳(Header subdocument)
批注(Comment subdocument)
尾注(Endnote subdocument)
文本框(Textbox subdocument)
頁眉文本框(Textbox Subdocument of the header)
Macro和Vba的解析與WordDocument的解析類似,需要注意的是其Type標志為1。
補充
在Word中,WordDocument永遠是Header后的第一個扇區(qū),但是PowerPoint Document不一定。不過,PowerPoint的數(shù)據(jù)都存儲在PowerPoint Document中。
PowerPoint以Record為基礎存儲的內(nèi)容。Record有Container Record和Atom Record兩種。類似于Sector中的 Stroge和Stream,Container Record是容器,Atom Record是容器中的內(nèi)容,那么其實PowerPoint Document中存儲結構也類似于WordDocument的其實也就是樹形結構。對于每一個Record,其結構如下:
0x00H~0x01H:Record的版本,其中低4位是recVer(如果是0x0F則一定為Container),高12位是recInstance。
0x02H~0x03H:Record的類型recType。
0x04H~0x07H:Record內(nèi)容的長度recLen。
剩下的字節(jié)是Record的具體內(nèi)容。
由于PowerPoint支持上百種Record,表舉一些常用的Record:
值(16進制) | 值(10進制) | 描述 |
---|---|---|
0x03E8 | 1000 | DocumentContainer |
0x0FF0 | 4080 | MasterListWithTextContainer/SlideListWithTextContainer/NotesListWithTextContainer |
0x03F3 | 1011 | MasterPersistAtom/SlidePersistAtom/NotesPersistAtom |
0x0F9F | 3999 | TextHeaderAtom |
0x03EA | 1002 | EndDocumentAtom |
0x03F8 | 1016 | MainMasterContainer |
0x040C | 1036 | DrawingContainer |
0x03EE | 1006 | SlideContainer |
0x0FD9 | 4057 | SlideHeadersFootersContainer/NotesHeadersFootersContainer |
0x03EF | 1007 | SlideAtom |
0x03F0 | 1008 | NotesContainer |
0x0FA0 | 4000 | TextCharsAtom |
0x0FA8 | 4008 | TextBytesAtom |
0x0FBA | 4026 | CString,儲存很多文字的Atom |
宏代碼數(shù)據(jù)結構解析
在使用oledump.py提取宏代碼數(shù)據(jù)時,會發(fā)現(xiàn)每段宏代碼起點處都是一段“Attribute”信息。實際上,我們可以使用“Attribute”字符來定位宏代碼在文檔中的存儲位置。使用010Editor打開demo1.doc,搜索字符串”Attribut”,注意這里不是搜索“Attribute”,不要加e!!!:
從圖中,我們可以看到autoopen()和MsgBox等字符,可以確定這里存儲的就是宏代碼數(shù)據(jù)
文檔中的宏代碼數(shù)據(jù)是分段存儲的,每段最大是0xFFF字節(jié),圖中的D3和B0表示此段宏代碼數(shù)據(jù)的長度:0x0*0x100+0xD3=0xD3,0xD3、0xB0后的數(shù)據(jù)就是宏代碼數(shù)據(jù)(包含宏屬性信息)
宏代碼里的數(shù)據(jù)是按組進行劃分的,每組包括一個字節(jié)的標志,和8個元素:
Flag | 0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40 | 0x80 |
---|---|---|---|---|---|---|---|---|
標志字 | 元素1 | 元素2 | 元素3 | 元素4 | 元素5 | 元素6 | 元素7 | 元素8 |
一般來說一個元素對應一個字節(jié),標志字Flag的每一位對應一個元素,表示這一個元素的具有兩個字節(jié)。
在解析宏代碼時,就是把這些元素拼接起來,組成完整的宏代碼。
說明
- 本文并非原創(chuàng),乃是征得作者同意后的轉載 原作者為狐貍先生 未經(jīng)允許,禁止轉載
- 需要相關文件可以到我的Github下載:https://github.com/TonyChen56/Virus-Analysis