Файловая система NTFS на сегодняшний день используется на большинстве компьютеров под управлением Microsoft Windows. Она заменила использовавшуюся в MS-DOS и ранних версиях Microsoft Windows файловую систему FAT. NTFS это восстанавливаемая, надёжная и эффективная файловая система. Помимо этого она поддерживает ряд дополнительных интересных возможностей:
- множественные потоки данных
- универсальный механизм индексации
- динамическое переназначение плохих кластеров
- сжатие и разреженные файлы
- протоколирование изменений
- квоты томов, индивидуальные для каждого пользователя
- шифрование
- отслеживание ссылок
- дефрагментация
- поддержка POSIX
- жесткие связи
Альтернативные потоки данных - что это?
Остановимся более подробно на множественных потоках данных(Alternate Data Streams или иногда альтернативные потоки данных). В NTFS каждая единица информации, сопоставленная с файлом реализована в виде атрибута файла. Каждый атрибут состоит из одного потока данных, т.е. из одной последовательности байтов. Это позволяет легко добавлять к файлу новые атрибуты(и новые потоки соответственно).

В любом файле NTFS всегда есть один безымянный поток данных. При создании альтернативного потока данных для несуществующего файла автоматически будет создан безымянный поток нулевой длины. Соответственно при удалении безымянного потока будет удалён весь файл.
При этом атрибуты файла принадлежат файлу целиком, не только безымянному потоку. Например, ни один поток нельзя открыть на запись если стоит атрибут только для чтения(read-only).
Когда приложение открывает какой-то файл оно на самом деле открывает его безымянный поток. Указать альтернативный поток можно следующим образом: file.ext:stream2 здесь file.ext это имя файла а stream2 имя альтернативного потока. Альтернативные потоки данных могут иметь также и папки. Доступ к ним осуществляется аналогичным образом. Единственное отличие состоит в том, что при попытке прочитать безымянный поток данных папки произойдёт ошибку Access denied error.
Поддержка ADS в системе
Windows Explorer поддерживает альтернативные потоки данных в том смысле, что он корректно копирует файлы, содержащие несколько потоков. Кроме того, когда вы щёлкаете правой кнопкой мыши и выбираете команду Properties а затем вкладку Summary Windows Explorer показывает информацию из альтернативного потока данных. На этом его возможности заканчиваются. Аналогичная ситуация и с консольной утилитой copy:

Единственные две команды, которые поддерживают такую функциональность это echo и more. Таким образом, самый простой способ что-нибудь сделать с потоками данных - создать именованный поток с помощью echo и прочитать его содержимое с помощью more.

Стоит заметить что при перечислении содержимого каталога не отражаются данные, содержащиеся в альтернативных потоках. Однако есть утилита Streams, которая анализирует указанные файлы и каталоги (у каталогов могут быть дополнительные потоки данных) и сообщает имена и размеры всех именованных потоков, встречающихся в этих файлах. Она основывается на недокументированной собственной функции извлечения данных о файловых потоках.
Программирование ADS
Как проверить поддерживает ли система альтернативные потоки данных?
#define MAX_PATH 100
void main( )
{
char szVolName[MAX_PATH], szFSName[MAX_PATH];
DWORD dwSN, dwMaxLen, dwVolFlags;
GetVolumeInformation("C:\\", szVolName, MAX_PATH, &dwSN, &dwMaxLen, &dwVolFlags, szFSName, MAX_PATH);
if (dwVolFlags & FILE_NAMED_STREAMS) {
printf("File system supports named streams");
}
else {
printf("Named streams are not supported");
}
}
Открыть или создать именованный поток можно с помощью функции CreateFile:
HANDLE hFile = CreateFile("file.txt:stream2", ...
Если файла с таким именем не существует, то вместе с именованным потоком будет создан также и безымянный. Удаление происходит аналогичным образом с помощью DeleteFile.
Гораздо больший интерес представляет копирование потоков. Самый простой способ - воспользоваться функцией CopyFile(или CopyFileEx). Однако эти функции предназначены для копирования файлов, поэтому существуют некоторые тонкости.
- Копирование из безымянного потока в безымянный. Рассматривается как файловая операция, т.е. все именованные потоки также будут скопированы. При этом если целевой файл уже существует, его содержимое будет заменено.
- Копирование из именованного потока в безымянный. Также рассматривается как файловая операция, однако скопирован будет только один поток. Если целевой файл уже существует, то он будет удалён.
Можно облегчить себе жизнь следующим образом:
void main( )
{
HANDLE hInFile = CreateFile("file.txt:stream2", GENERIC_READ, FILE_SHARE_READ, NULL,
OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
HANDLE hOutFile = CreateFile("new.txt:newstream", GENERIC_WRITE, FILE_SHARE_READ, NULL,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
BYTE buf[64*1024];
DWORD dwBytesRead, dwBytesWritten;
do {
ReadFile(hInFile, buf, sizeof(buf), &dwBytesRead, NULL);
if (dwBytesRead)
WriteFile(hOutFile, buf, dwBytesRead, &dwBytesWritten, NULL);
} while (dwBytesRead == sizeof(buf));
CloseHandle(hInFile);
CloseHandle(hOutFile);
}
Получить список потоков можно с помощью функции WinAPI NtQueryInformationFile.
// Открытие файла и получение информации о потоках данных
BYTE InfoBlock[64 * 1024];
PFILE_STREAM_INFORMATION pStreamInfo = (PFILE_STREAM_INFORMATION)InfoBlock;
IO_STATUS_BLOCK ioStatus;
HANDLE hFile = CreateFile(szPath, 0, FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, 0, NULL);
NtQueryInformationFile(hFile, &ioStatus, InfoBlock,
sizeof(InfoBlock), FileStreamInformation);
CloseHandle(hFile);
Хотя этот способ является недокументированным и не рекомендуется к использованию.
Прочие факты об альтернативных потоках данных
- Размер альтернативного потока не ограничен.
- В альтернативном потоке может храниться не только текстовая информация. Любой поток может содержать в себе бинарные данные, JPEG или MPEG и вообще всё что угодно. Эта возможность широко используется вирусописателями и прочими злонамеренными личностями.
- Альтернативные потоки сами по себе не имеют атрибутов. Это значит что если запись в файл запрещена, то и добавить альтернативный поток в этот файл не получится.
- Протоколы передачи данных(такие как SMTP или FTP) не поддерживают альтернативные потоки данных. Единственный способ передать файл с ADS по сети это использовать локальную сеть и пересылать файл с диска на диск NTFS.
Ссылки
Inside Win2k NTFS
Демонстрация возможностей альтернативных потоков данных для сокрытия информации
LADS - list alternate data streams