• Программинг

Нужны источники бесперебойного питания?

Источники бесперебойного питания от дизельстор

Альтернативные потоки данных NTFS с примером использования на C#

В системах семейства Windows NT есть малоизвестная функция, которая позволяет скрывать какую-либо информацию. Называется она альтернативные потоки данных NTFS (далее АПД). АПД позволяют добавить к любому файлу или папке информацию, которая будет не видна при обычном просмотре. Это обусловлено тем, что файл NTFS состоит из потоков данных и в обычных условиях вы видите только один, основной поток данных. При этом альтернативный поток невидим, хотя в нем может содержаться информация. В тоже время операционная система никак не оповещает пользователя, что в файле есть альтернативный поток. Некоторые программы используют эту возможность для хранения служебной информации, касающейся этого файла, а хакеры организовывают атаки.

Данные, записанные в альтернативный поток, влияют на размер файла, т.к. они записаны в файл. Логично. В Windows XP это хорошо видно в свойствах файла, но Vista и Windows 7 почему-то не показывают размер с учетом содержания двух потоков.

Чтобы лучше понять вышеописанное, давайте перейдем к практике. Сначала поработаем в консоли. Создайте текстовый файл (например example.txt) и введите в него какую-либо информацию. Запустите консоль… Вы должны находиться в этой же папке, где находится файл. Выполните следующую команду:

1 echo hello world > example.txt:hwstream

С помощью команды echo и > вводим в файл запись «hello world», при этом через двоеточие даем название альтернативному потоку. В нашем случае поток называется hwstream.
Посмотреть что находится в потоке hwstream можно так:

1 more < example.txt:hwstream

Таким образом записывается текстовая информация. Для того, чтобы записать другой тип данных, нужно использовать команду type:

1 type calc.exe > example.txt:calc

После выполнения данной команды, в файле example.txt записан калькулятор, который можно запустить так:

1 start .\example.txt:calc

Еще пример с записью видео файла и последующего его открытия:

1 "C:\Program Files\Windows Media Player\wmplayer.exe" "example.txt:Просто какое-то название"

Теперь перейдем к C#. Стандартные функции библиотеки .NET не позволяют реализовать запись и чтение данных в альтернативном потоке. Для этого будем использовать функции WinApi – ReadFile, CreateFile и WriteFile.
Следующие два метода реализуют чтение и запись текста в альтернативный поток.

1 /// <summary>
2 /// Чтение из файла
3 /// </summary>
4 /// <param name="file">Имя файла</param>
5 /// <param name="stream">Название потока</param>
6 /// <returns>Данные потока</returns>
7 public string ReadFromFile(string file, string stream)
8 {
9     uint fHandle = CreateFile(file + ":" + stream, GENERIC_READ, FILE_SHARE_READ, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero);
10     if (fHandle != uint.MaxValue)
11     {
12         uint size = GetFileSize(fHandle, IntPtr.Zero);
13         byte[] buffer = new byte[size];
14         uint read = uint.MinValue;
15  
16         uint result = ReadFile(fHandle, buffer, size, ref read, IntPtr.Zero);
17  
18         CloseHandle(fHandle);
19         return System.Text.Encoding.Default.GetString(buffer);
20     }
21     else
22         return null;
23 }
24  
25 /// <summary>
26 /// Запись в файл
27 /// </summary>
28 /// <param name="text">Текст, который нужно вставить</param>
29 /// <param name="fileName">Имя файла</param>
30 /// <param name="stream">Имя потока</param>
31 /// <returns></returns>
32 public uint WriteToFile(string text, string fileName, string stream)
33 {
34     byte[] barData = System.Text.Encoding.Default.GetBytes(text);
35     uint nReturn = 0;
36  
37     uint fHandle = CreateFile(fileName + ":" + stream, GENERIC_WRITE, FILE_SHARE_WRITE, IntPtr.Zero, CREATE_ALWAYS, 0, IntPtr.Zero);
38  
39     bool bOK = WriteFile(fHandle, barData, (uint)barData.Length, ref nReturn, IntPtr.Zero);
40     CloseHandle(fHandle);
41  
42     if (!bOK)
43         MessageBox.Show("Не удалось записать в файл " + System.Runtime.InteropServices.Marshal.GetLastWin32Error());
44  
45     return nReturn;
46 }

Для статьи я создал тестовый проект, который наглядно показывает как это все дело можно реализовать с помощью C#.

Для выявления альтернативного потока в файле, существует ряд утилит, которые показывают что и где находится (от Sysinternals).