Бесфайловое хранение данных: структура папок как шифр
Исследователи показывают, как спрятать слона в муравейнике.
Специалисты Trustedsec опубликовали исследование Hiding in Plain Sight, которое предлагает новый и необычный бесфайловый метод скрытия данных с использованием структуры папок.
Скрытие данных без файлов
Традиционно антивирусное ПО и DLP-решения (Data Loss Prevention) фокусируются на файлах, где и хранится информация. Однако новое открытие исследователей ставит под сомнение привычную парадигму. Специалисты предложили использовать папки как контейнеры для хранения данных. Папки сами по себе не содержат данных, но их имена могут использоваться для кодирования информации.
Как это работает?
Идея состоит в создании иерархической структуры папок (одна внутри другой), где каждая папка имеет уникальное имя, представляющее часть данных. Например, структура «папка1\папка2\папка3\папка4» может быть использована для кодирования строки данных. Если удалить разделители папок, получится непрерывная строка, содержащая информацию – «папка1папка2папка3папка4».
Для предотвращения использования специальных символов, которые могут вызвать подозрения, исследователи предлагают использовать GUID (Globally Unique Identifier) – стандартный формат идентификаторов, часто используемых в системах. GUID представляет собой строку из 32 символов, разделенных дефисами. Символы в такой записи случайны и не вызывают подозрений.
Для подтверждения концепции мы будем использовать небольшой фрагмент текста:
Пока мы используем текстовую строку для тестирования, легко заменить источник ввода на целевой файл. PowerShell легко читает из файла с помощью Get-Content. Сначала мы берем наши входные данные и преобразуем их в поток байтов. В этом случае мы можем преобразовать строку следующим образом:
$data_bytes = [System.Text.Encoding]::UTF8.GetBytes($example_data)
Затем поток байтов преобразуется в шестнадцатеричный:
$hexString = ($data_bytes | ForEach-Object { $_.ToString(“X2”) }) -join ‘’
Данные, преобразованные в шестнадцатеричную систему счисления
Теперь преобразуем нашу шестнадцатеричную строку в ряд путей, состоящих из папок с GUID в качестве имен, и создаем эти пути.
# Split the string into chunks
$chunks = [regex]::Matches($paddedString, ".{1,$chunkSize}") | ForEach-Object { $_.Value }
$chunkWithPrefix = $prefix + $chunk
# Split the chunk into 32-char segments and format as GUIDs
$guids = [regex]::Matches($chunkWithPrefix, ".{1,32}") | ForEach-Object {
$formattedGuid = ($segment -replace '(.{8})(.{4})(.{4})(.{4})(.{12})', '$1-$2-$3-$4-$5')
# array to hold our folders before we create them
$fifthline = "{0}\{1}\{2}\{3}\{4}" -f $tmp_path_array[0], $tmp_path_array[1], $tmp_path_array[2], $tmp_path_array[3], $tmp_path_array[4]
#this -p option creates any required parent folders
mkdir -p "$fifthline" | out-null
Ниже мы можем увидеть вывод кодировки. Это наш файл, закодированный в пути к папкам. Каждая строка представляет собой иерархию папок, содержащих часть нашей общей закодированной строки.
Вывод расширенных путей к папкам
У нас есть 44 папки на верхнем уровне. Первые шесть символов каждой строки — это рандомизированный 6-символьный шестнадцатеричный код, который был отсортирован в алфавитном порядке и добавлен к каждой строке. Это позволяет сортировать по имени и размещать каждую строку в том порядке, в котором она должна располагаться, при этом выглядя случайным образом.
Создание папок со значениями индекса
Ограничения и проблемы
Существует несколько ограничений, связанных с этим методом. Во-первых, в Windows существует ограничение на длину пути в 260 символов. Это значит, что имена папок должны быть достаточно короткими, чтобы избежать превышения лимита.
Во-вторых, использование чистого шестнадцатеричного кодирования может выглядеть подозрительно. Поэтому было решено сохранять имена папок в формате GUID, что делает их менее заметными.
Наша базовая папка занимает ноль байт на диске. Обратите внимание на количество – 220 папок.
Расшифровка
Для декодирования мы смотрим на папки верхнего уровня в нашем целевом каталоге. Затем, в отсортированном порядке, мы погружаемся в каждую папку верхнего уровня, извлекая весь путь структуры папок. Шестнадцатеричное число добавляется к строковой переменной «hex stream».
После того, как все пути к папкам верхнего уровня считаны, поток hex преобразуется в байты и может быть отображен на экране или записан в файл.
foreach ($f in (gci -Path $a -ad)) {
$c = (gci -Path $f.FullName -ad -r | sort { $_.FullName.Split('\').Count } -d)[0]
$d = ($c.Fullname.Split("\")[$a.Path.split('\').Count..($c.Fullname.Split("\").Length - 1)] -join '\')
$b += $d.Substring(6).replace("-","").replace("\","")
$e = [regex]::Matches($b, '..') | % { [Convert]::ToByte($_.Value, 16) }
$g = "$($a.Path)\decoded_output.txt"
sc -Path $g -Value $e -Encoding Byte
Декодированные данные. Внизу выведен расшифрованный текст
Практическое применение и сложности
Этот метод имеет несколько потенциальных применений:
- Скрытие полезных данных на системе без явного наличия файлов.
- Уход от статического анализа антивирусных программ.
- Создание сложных структур, которые сложно обнаружить или расшифровать без специального знания.
Однако, несмотря на свою креативность, метод имеет свои недостатки. Кодирование данных в структуре папок увеличивает общий размер данных при архивировании. Обычный текстовый файл может значительно вырасти в размере, увеличиваясь с 1 071 КБ до 21 688 КБ при использовании структуры папок.
Заключение
Идея использования папок для скрытия данных представляет собой интересный подход к проблеме защиты информации. Такой способ демонстрирует, что методы сокрытия данных ограничены только воображением исследователей. Однако реальная полезность метода в повседневной жизни вызывает сомнения, поскольку основная проблема заключается в обходе детектирования средств защиты, а не в самом скрытии данных. Проект, демонстрирующий метод, доступен на GitHub.