知識概要
金山的wps系列的dps wps et的二進位格式是和微軟的office系列的ppt word excel相對應的,OpenOffice應該也是一樣相容微軟的二進位格式的。這裡的原因大家都應該知道還不是因為人家微軟是老大啊,不過有反壟斷法的保護,微軟還是要公開它的二進位格式給其他廠商的。閑話少說,開始正題.
要進行二進位檢測前,必須知道以下知識。
1.倉庫(這裡有個很重要的 根倉庫 root storage)
2.標準流
3.短流和短流存放流
4.扇區
5.短扇區
6.主扇區配置表,扇區配置表,短扇區配置表
簡單的關係整理如下:
1. 倉庫中包含流(可能是標準流,也可能是短流),就像D盤中有檔案一樣
2. 倉庫中可以包含倉庫 就像D盤中可以包含檔案夾一樣
3. 儲存的最小單位為扇區。流是一些扇區的組合,而扇區配置表指定了這些組合的關係
4. 短流是小於標準流大小的流,而短流同樣是一些扇區的組合,但是這些扇區又可以劃分到短扇區單元
5. 主扇區配置表,指定那些用於儲存扇區配置表的扇區
6. 扇區配置表和短扇區配置表,都是用來指定一個流所對應的扇區鏈
如果如上關係搞不清楚,可參看 http://blog.csdn.net/liangjingbo/archive/2008/09/03/2874959.aspx,這篇文章。
加密檢測
複合文檔的前512個位元組都是很有格式規律的,在這裡我們可以找到扇區大小,根倉庫的入口地址,主扇區配置表等。
進入分析之前,我們首先要找到根倉庫的入口地址(即目錄的入口地址)
每個目錄大小為128個位元組,開頭用64個位元組描述該目錄的名字
1.word檔案
首先在目錄中找到 “WordDocument”目錄,對應的二進位為:
- u_bits_8 word[23]={0x57,0x00,0x6F,0x00,0x72,0x00,0x64,0x00,0x44,0x00,0x6F,0x00,0x63,0x00,0x75,0x00,0x6D,0x00,0x65,0x00,0x6E,0x00,0x74}
注意:這裡的大小端問題
然後查看該目錄的流的入口sector,注意如果是該流的大小大於等於標準流的大小,則在 扇區配置表中(SAT)中查詢扇區鏈,如果 小於標準流的大小,則在 短扇區配置表中(SSAT)中查詢扇區鏈。定位到指定的扇區後,進行一定的位移,進行判斷。簡易的代碼示意如下:
- //judge whether .doc file is encrypted or not.
- int is_encrypted_doc(char* file_path)
- {
- ifstream ifs(file_path,ios_base::binary);
-
- if (ifs)
- {
- unsigned int stream_address;
- sid_32 stream_sector;
- int stream_length;
- bits_8 tmp[20];
- Header header(ifs); //read msat and sat chain
- DirectoryEntry d_entry(&header);
- if (!d_entry.get_stream_address("WordDocument",stream_address,stream_sector,stream_length))
- {
- ifs.close();
- return FILE_ERROR;
- }
- ifs.seekg(stream_address);
- ifs.read(&tmp[0],20);
- ifs.close();
- if(tmp[11]&0x01) return FILE_ENCRYPTED ;
- return FILE_COMMON;
- }
- else
- return FILE_NO_FOUND;
- }
2.excel檔案
excel檔案和word檔案的原理基本一致,它是尋找“workbook”目錄。excel的配置是採用“配置名稱 長度 內容”這種格式的,所以如果要找到加密的欄位,必須從前面一直向後讀,唯讀到加密的配置欄位,簡易代碼如下:
- //judge whether .xls file is encrypted or not.
- int is_encrypted_xls(char* file_path)
- {
- ifstream ifs(file_path,ios_base::binary);
- if (ifs)
- {
- unsigned int stream_address;
- sid_32 stream_sector;
- int stream_length;
- bits_8 tmp[64];
- Header header(ifs); //read msat and sat chain
- DirectoryEntry d_entry(&header);
- if (!d_entry.get_stream_address("WorkBook",stream_address,stream_sector,stream_length))
- {
- ifs.close();
- return FILE_ERROR;
- }
- ifs.seekg(stream_address);
- ifs.read(tmp,64);
- unsigned int count = 0;
- while (count+4< 64)
- {
- bits_16 flag = convert_chars_to_bits(tmp[count],tmp[count+1]);
- if (flag!=FILEPASS)
- {
- flag = convert_chars_to_bits(tmp[count+2],tmp[count+3]);
- count+=flag+4;
- }
- else
- return FILE_ENCRYPTED;
- }
- return FILE_COMMON;
- }
- else
- return FILE_NO_FOUND;
- }
3.ppt檔案
ppt檔案的設定比較讓人煩,在powerpoint2003中它的加密欄位值為0xF3D1C4DF表示加密,可是powerpoint2002,這個值又表示不加密。這就鬱悶了,後來發現了一個變通的方法,那就是加密的文檔中的欄位(0x0FF50000 -->RT_UserEditAtom. )的值不同,主要是加密文檔多出了一些加密的資訊,我們就是通過檢測這個欄位來完成加密檢測的,由於該欄位名字佔了四個位元組,所以就直接搜尋二進位檔案的內容就可以了,搜尋到後,檢測後面的一個位元組,如果是0x1C 則為common ,為 0x20 則為encrypted。
註:著作權,如有轉帖請註明出處。