index.dat文件剖析
misterliwei
一. 前言
注重上网隐私和安全的人在每次上网后都会清除上网痕迹——“删除cookies”、“删除掉上网的临时缓存文件”以及“删除上网历史”。你觉得这样,所有的一切都会被擦除掉了。但是如果有人告诉你:这是不够的,系统中还有一些地方保存了你的上网信息,你是不是感到很恐慌?——这就是系统中的index.dat文件。
Windows系统中会存在三个index.dat文件。它们分别用来保存IE上网的cookies、临时文件和上网历史的索引信息(现在知道为什么这些文件名字是index.dat了吧J)。根据Windows系统版本不同,这些文件在系统中的位置也是不尽相同的。
在Windows 95/98/Me/ NT中,index.dat一般会存放在下面的位置中:
C:/Windows/Cookies/index.dat |
而在Window2000/XP系统中,index.dat一般会存在于下面的位置中:
C:/Documents and Settings/<username>/Cookies/index.dat /Temporary Internet Files/Content.IE5/index.dat |
这些index.dat文件是系统、隐藏的文件,它们不随IE浏览器中的cookies值、临时文件和历史记录的清除而删除——这就是它的可怕之处。下面来详细描述index.dat文件的结构。
二. Index.dat文件结构
Index.dat文件分为两部分,头部分和条目(Entry)部分。
所谓头部分,顾名思义就是文件开始部分。它记录着这个文件的总的信息,如文件文件格式版本、大小、子文件夹等等。每个index.dat文件仅有一个头部分。
其余的部分都是条目部分。Index.dat中的各种类型的条目数据结构不同,不过每个条目的前8个字节结构相同,系统就是用这两个DWORD字段来区分条目类型的。
下面我们来具体分析一下各个部分:
1. 头部分
index.dat的头部大小是固定的,为16K。其开始592个字节(0x250)为小(SMALL)的头部分。紧接着的空间是3948个DWORD,它用来作为分配MAP。数据结构如下:
struct CacheDir { DWORD nFileCount; CHAR sDirName[8]; };
typedef struct _MEMMAP_HEADER_SMALL { TCHAR FileSignature[28]; //”Client UrlCache MMF Ver 5.2” DWORD FileSize; //index.dat文件的大小 DWORD dwHashTableOffset; //第一个哈希表的偏移 DWORD NumUrlInternalEntries; DWORD NumUrlEntriesAlloced; // DWORD dwGarbage; // 无效数据,只在/Zp8编译使用 LONGLONG CacheLimit; LONGLONG CacheSize; LONGLONG ExemptUsage; DWORD nDirCount; //子目录个数 CacheDir DirArray[32]; //子目录名称 DWORD dwHeaderData[33]; } MEMMAP_HEADER_SMALL;
typedef struct _MEMMAP_HEADER : _MEMMAP_HEADER_SMALL { DWORD AllocationBitMap[3948]; } MEMMAP_HEADER, *LPMEMMAP_HEADER; |
2. 各种条目结构
上文说过每个条目都是以同样结构的2个DWORD开始的,这个结构如下:
typedef struct FILEMAP_ENTRY { DWORD dwSig; //条目标识 DWORD nBlocks; //条目占用多少个快(128字节) } *LPFILEMAP_ENTRY;
|
dwSig用来标识各种类型的标识。
表示字 |
值 |
说明 |
SIG_FREE |
0xbadf00d |
本条目空闲,只有此类条目没有nBlocks成员。 |
SIG_ALLOC |
0xdeadbeef |
已分配 |
SIG_URL |
' LRU' |
URL值 |
SIG_REDIR |
'RDER' |
REDIR |
SIG_LEAK |
'KAEL' |
LEAK |
SIG_GLIST |
'GLST' |
GLIST |
SIG_HASH |
'HSAH' |
哈希表 |
关于各种条目的结构我们下面会详细说明。
nBlocks用来描述此条目所占用的块数。注意index.dat中的块大小为128字节。
2.1哈希表条目
现在开始说明各种类型的条目。为什么先要说哈希表呢?这是因为index.dat使用一个哈希表链来作为目录,从而能够快速找到指定名称的条目。
Index.dat文件中每个哈希表大小都不能超过一个内存分页,即不能超过4K大小。每个哈希表部分是由下面的结构开始的,同时系统也是利用了这个结构,将index.dat中所有的哈希表部分链接起来的。
struct HASH_FILEMAP_ENTRY : FILEMAP_ENTRY { DWORD dwNext; // 下一个哈希表偏移(0表示为最后一个) //偏移以index.dat文件第0字节为基地址。 DWORD nBlock; // 本哈希表的序列号。从0,1,2……. }; |
紧接着这个结构就是一个哈希表,每个哈希表的关键是哈希函数,下面是这个哈希表的哈希函数:
PRIVATE DWORD HashKey (LPCSTR lpsz) { union { DWORD dw; BYTE c[4]; } Hash, Hash2;
const static BYTE bTranslate[256] = { 1, 14,110, 25, 97,174,132,119,138,170,125,118, 27,233,140, 51, 87,197,177,107,234,169, 56, 68, 30, 7,173, 73,188, 40, 36, 65, |