序
我對 Excel 檔案結構的學習研究,也是最近才開始。隻是好奇,拿出改遊戲的勁頭與手段,一點點的啃。發覺似乎有不少人也對該檔案格式感興趣。隻是很可惜,我找不到能力足夠、并且願意一起共享心得體會、共同學習的同道。
一人獨行,自然倍感寂寞,興趣的火花也就時燃時滅;再加上我人比較懶,工作忙,也難以抵禦外界的種種誘惑,比如娛樂、遊戲、小說等等,是以,火花也就滅的時候居多。這裡就先請讀者原諒,打聲招呼,如果這篇文章寫得太慢,或者不能最終完成,千萬不要罵我。當然這是閑話了。
另外,因為沒有正式的資料,既然是研究,下面的内容也可能全盤皆錯。有早知早覺的大俠,想批,請随便拿磚頭砸吧!
第一章 前言
一、前人的研究
能夠找到的前人研究資料不多。MSDN online裡有部分,可惜組織得很零散,微軟也删除了重要内容。有人說 MS Office Develop 附帶的MSDN Library 中有介紹,可是我沒有這個東東,也無從知道講了什麼東西。如果有人有這些東西,不知是否友善發給我看看。先謝謝了!
不過,我還是按照我所知道的來寫吧!
1996 年,德國人 martin Schwartz 寫了一篇語焉不詳的“Hacking Guide”,他研究了Word 6的存盤檔案,文章裡他叫這種檔案結構為Laola。他認為Laola是一個檔案系統,包含子目錄與子檔案。照搬到Excel中,根據這種思路,Excel 裡的workbook、或VBA,都應該是一個子檔案,微軟好象叫它們OLE2 Storage,也就是說,一個 Excel 檔案,包含了一個目錄結構和若幹個子檔案,每個子檔案都是一個 OLE2 Storage。我們下面就沿用martin Schwartz定義的Laola的概念。
不過,martin Schwartz最大的貢獻是用 Perl 4 寫了一個Package (類似于 VBA 裡的類),提供了讀取 Laola 檔案系統的方法。(我正在用VBA重寫這個Package,并增加寫子產品,工作忙,斷斷續續,是以還沒寫完)。
1997 年的《Excel Digest》裡發表了一篇文章,作者是Guy Boertje,内容是一個讀取Workbook裡使用者定義數字格式的VBA。他用的辦法是直接在Excel檔案裡直接搜尋Workbook BOF記錄(Beginning of File,辨別是Hex 0809),找到檔案的起始偏移。關于這樣的VBA程式,大家可以參考我的文章(讀取 Excel 工作表的背景圖檔),發表在壇子裡。因為當時還不知道Laola的概念,是以讀出來的圖檔時對時錯。
二、分析Excel 檔案二進制結構的基本工具
為了簡化,我們就使用三個基本工具,也大緻夠用了。一個是UltraEdit 32,可以16進制的形式編輯二進制檔案。另外一個工具是WinHex,這個工具的主要特點是可以進行二進制比較,也可以直接編輯機器記憶體中的二進制資料,實在是改遊戲、做 memory dump 的利器。再一個工具就是Windows中的電腦,我們可以用他來完成十進制——十六進制——和二進制的轉換。
好,有了這些工具,我們就可以開始。
另外,講三個基本常識:
1、數字的表示方式:
十進制:我們就用一般的表示方式,比如“1234”。
十六進制:表示為“Hex 1234”或“0x1234”。
二進制:表示為“Bin 1001”。
2、數字的存放順序
數字在Intel的機器,二進制檔案中是順序存放的,比如 Hex 0809,就表示為0x09 0x08,高位在後,低位在前。
3、基本資料類型
我們主要涉及到三種資料類型,位元組(Byte)、字(Word,占兩個位元組)和雙字(Dword,四個位元組),Word和Dword就相當于無符号的整型和無符号長整型。
第二章 Laola 結構
這第二章我們先研究 Laola 結構,第三章學習Workbook的結構,也就是xiaog貼出來的東西,第四章看看VBA,第五章就是Excel 檔案中根據Laola概念分解出來的,其它有趣的東東;第六章,應用工具程式示例,我就想把一些讀取Excel的VBA程式、以及通過ADO方式的VBA程式和C++程式歸為這一章。
如果沒意見,我們繼續。
Excel 檔案中的第一個512位元組塊(0x200),是Laola的初始塊,從偏移0x00到0x1FF。我們先拿80位元組出來學習一下。
0x00000h: D0 CF 11 E0 A1 B1 1A E1 00 00 00 00 00 00 00 00
0x00010h: 00 00 00 00 00 00 00 00 3E 00 03 00 FE FF 09 00
0x00020h: 06 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00
0x00030h: 19 00 00 00 00 00 00 00 00 10 00 00 FE FF FF FF
0x00040h: 00 00 00 00 FE FF FF FF 00 00 00 00 18 00 00 00
偏移00開始是Laola辨別,“D0 CF 11 E0 A1 B1 1A E1”,表示這是一個Laola檔案系統。
偏移0x18是Word,可能是小版本号,
偏移0x1a是Word,可能是版本号,一般為3。
偏移0x 1e是Word,表示塊的大小,固定為9,是2的幂次(2^9為512位元組)
偏移0x 20表示小檔案塊的大小,2^6為64位元組。
好,作了一個簡單的示例,我們再講講一些Laola中的概念。
1、初始塊
就是Excel 檔案中的前512個位元組。這個塊中資料結構的定義表我們放在本章末尾列出,在本章的各個部分我們将逐漸分析這個初始塊的含義。
2、大檔案塊檔案表
大檔案塊檔案表是存放檔案塊索引号的, 比如,
0x0003200: 01 00 00 00 02 00 00 00 03 00 00 00 05 00 00 00
0x0003210: FE FF FF FF 06 00 00 00 07 00 00 00 FE FF FF FF
0x0003220: 09 00 00 00 0A 00 00 00 0B 00 00 00 0C 00 00 00
0x0003230: 0D 00 00 00 0E 00 00 00 0F 00 00 00 FE FF FF FF
0x0003240: 11 00 00 00 12 00 00 00 13 00 00 00 14 00 00 00
0x0003250: 15 00 00 00 16 00 00 00 17 00 00 00 FE FF FF FF
0x0003260: FD FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
索引号從0開始編号,一個DWORD表示一個索引。
索引的取值範圍:
0xFFFFFFFD:特别塊
0xFFFFFFFE:索引鍊結束标志
0xFFFFFFFF:未使用
0… 檔案塊總數:索引鍊中的下一個元素
大檔案塊檔案表中是按索引鍊的方式排列的,通過索引鍊我們可以将在Excel檔案中若幹個不連續排放的大檔案塊,組織起來。
比如,我們先建立一個空的大檔案塊清單“{}”,我們從偏移0x0003200 + 0*4 (0為索引)中取DWORD,值為1,是以把0和1放入大檔案塊清單中,為{0, 1};偏移0x0003200 + 1*4處數值為2,是以把2放入清單中,為{0, 1 , 2};再到偏移0x0003200 + 2*4處取數值,為3,如此往複,一直到偏移0x0003200 + 7*4,數值為0xFFFFFFFE,表示索引鍊結束,而大檔案塊清單已經為{0, 1, 2, 3, 5, 6, 7}。這樣,我們就已經取得了一個應該連續排放的若幹個大檔案塊。