枚举备用数据流






3.82/5 (9投票s)
2006年4月3日
5分钟阅读

70963

2369
枚举 NTFS 文件中包含的备用数据流。
引言
备用数据流 (ADS) 有点争议。虽然我从未遇到过这个问题,但我见过不少网站明确表示 ADS 是邪恶的!
如果您以前没听过备用数据流这个词,那么这篇内容就是为您准备的:通常,当您将内容存储在文件中(例如文本文件)时,文件中就只有这些内容。然而,在 NTFS 中,存在一种功能,可以通过它将一套完全不同的数据保存为备用流。更糟糕的是,这种“备用”流不会被 Explorer 或 'dir' 等 DOS 命令报告。
因此,可以存在一个文件,其中有一个备用数据流,大小可能有数百兆字节,但主数据流中却没有任何数据。哦,我忘了提“主数据流”。这是您将数据保存到文件时通常写入/读取的默认流。
您可能会发现备用数据流的一些新颖用途,例如存储文件的元数据。虽然 Windows 不直接显示备用数据流,但可以使用一些 Win32 API 调用来获取它们。这就是我将在本文中讨论的内容。另外:网上有一些类似的文章,但大多数是用 C# 写的,我认为当我们想在 Win32 API 层面工作时,C++ 是最合适的,所以这是一篇完全基于 MFC 的文章。
基础知识
有两种 API 集可用于读取数据流。第一种包括调用 API - FindFirstStreamW()
和 FindNextStreamW()
。这一组函数与 FindFirstFile
类型的 API 非常相似。但是,问题在于它仅适用于 Windows 2003!
下一组函数属于 Backup API。它们是 BackupRead()
和 BackupSeek()
。这就是我们将在程序中使用的。
在我们深入了解更多细节之前,让我们快速看一下如何创建一个包含备用数据流的文件。输入以下命令:'notepad.exe c:\a_new_file.txt:TheStream' 将创建一个名为 'TheStream' 的备用数据流。
在记事本中,输入一些内容并保存文件。然后,转到 Windows Explorer 查看文件属性,文件大小将为零。
输入相同的内容,瞧,您将在记事本中看到内容。
主文件
- AltDataStream.h 和 AltDataStream.h.cpp - 定义了一个名为
CAltDataStream
的小型类,该类负责枚举文件的流数据。
该类的主要函数是 GetStreams()
,它返回指向字节数组的指针列表。
该函数的工作原理如下:每个流(数据)之前都有一个流头。此头包含流的名称和大小等信息。因此,如果我们有两个备用数据流,我们将首先遇到第一个流的流头,然后是它的数据。紧接着第一个流的数据之后,我们将遇到第二个流的流头,然后是它的数据。因此,只需读取重要部分并跳过我们不需要的实际数据即可,因为我们只想获取流的名称和大小。然而,我们类中的函数确实会读取一部分数据,精确地说 64 字节,这充当了实际数据的预览。
因此,首先,我们需要打开一个文件并获取一个文件句柄;我们通过使用旧的 CreateFile()
API 来实现此目的。
紧接着是对 BackupRead()
函数的调用。重要的是要读取比 winbase.h 中定义的 WIN32_STREAM_ID
结构(只需包含 Windows.h)更大的大小。
以下是 BackupRead()
的参数:
HANDLE hFile
- 我们打开的文件的句柄。LPBYTE lpBuffer
- 数据将存储的缓冲区。DWORD nNumberOfBytesToRead
- 我们想读取多少字节。LPDWORD lpNumberOfBytesRead
- 实际读取了多少字节。BOOL bAbort
- 最初传递FALSE
;读取完成后,传递TRUE
。BOOL bProcessSecurity
- 我们不需要这个。LPVOID* lpContext
- 帮助 API 跟踪其使用情况。确保在第一次调用BackupRead()
之前将其初始化为NULL
。保存此指针并将其传递给所有后续的BackupRead
和BackupSeek()
调用。
现在我们已经读取了第一个流头,我们存储元数据,即流的名称和流的大小。然后我们可以使用 BackupSeek()
(BackupSeek()
)定位到数据流的末尾。紧接着是下一个流头,所以我们重复这个过程。当没有更多数据可读时,BackupRead()
返回 FALSE
。
运行演示
要运行演示应用程序,请创建一个包含一个或多个备用数据流的文件。从 demo.zip 文件中解压缩 ADS.EXE 文件,然后以“ads.exe c:\stream.txt”的形式运行它。
重要提示 - 备用数据流仅在 NTFS 卷上工作,因此这一切在 FAT32 卷上将不起作用。
请将您的评论发送至 siddharth_b@yahoo.com。我很高兴收到您的来信。