Многие могли слышать о таких файлах, как rarjpeg'и. Это особый вид файлов, представляющий собой склеенную вплотную jpeg-картинку и rar-архив. Он является прекрасным контейнером для скрытия факта передачи информации. Создать rarjpeg можно с помощью следующих команд:

UNIX: cat image1.jpg archive.rar > image2.jpg
WINDOWS: copy /b image1.jpg+archive.rar image2.jpg

Или же при наличии hex-редактора.

Разумеется, для скрытия факта передачи информации можно использовать не только формат JPEG, но и многие другие. Каждый формат имеет свои особенности, благодаря которым он может подходить или нет для роли контейнера. Я опишу, как можно найти приклеенные файлы в наиболее популярных форматах или же указать на факт склейки.

Методы детектирования склеенных файлов можно разделить на три группы:

  1. Метод проверки области после EOF-маркера. Множество популярных форматов файлов имеют так называемый маркер конца файла, который отвечает за отображение нужных данных. Например, программы для просмотра фотографий считывают все байты вплоть до этого маркера, однако, область после него остается игнорируемой. Этот метод идеально подходит для форматов: JPEG, PNG, GIF, ZIP, RAR, PDF.
  2. Метод проверки размера файла. Структура некоторых форматов (аудио- и видеоконтейнеры) позволяет вычислить реальный размер файла и сравнить его с исходным размером. Форматы: AVI, WAV, MP4, MOV.
  3. Метод проверки CFB-файлов. CFB или Compound File Binary Format — формат документов, разработанный в Microsoft, представляющий собой контейнер с собственной файловой системой. Этот метод основан на обнаружении аномалий в файле.

Есть ли жизнь после конца файла?


JPEG


Для нахождения ответа на этот вопрос, необходимо углубиться в спецификации формата, который является «родоначальником» склеенных файлов и понять его структуру. Любой JPEG начинается с сигнатуры 0xFF 0xD8.

После этой сигнатуры находится служебная информация, опционально иконка изображения и, наконец, само сжатое изображение. В этом формате конец изображения отмечается двухбайтной сигнатурой 0xFF 0xD9.

PNG


Первые восемь байт PNG-файла занимает следующая сигнатура: 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A. Сигнатура конца, которая заканчивает поток данных: 0x49, 0x45, 0x4E, 0x44, 0xAE, 0x42, 0x60, 0x82.

RAR


Общая сигнатура для всех rar-архивов: 0x52 0x61 0x72 0x21 (Rar!). После неё идет информация о версии архива и прочие сопутствующие данные. Опытным путем было установлено, что архив заканчивается сигнатурой 0x0A, 0x25, 0x25, 0x45, 0x4F, 0x46.

Таблица форматов и их сигнатур:
Формат Начальная сигнатура Конечная сигнатура
JPEG 0xFF 0xD8 0xFF 0xD9
PNG 0x89 0x50 0x4E 0x47 0x0D 0x0A 0x1A 0x0A 0x49 0x45 0x4E 0x44 0xAE 0x42 0x60 0x82
RAR 0x52 0x61 0x72 0x21 0x0A 0x25 0x25 0x45 0x4F 0x46
Алгоритм проверки на склейку в данных форматах предельно прост:

  1. Найти начальную сигнатуру;
  2. Найти конечную сигнатуру;
  3. Если после конечной сигнатуры нет данных — ваш файл чист и не содержит вложений! В ином случае необходимо искать после конечной сигнатуры другие форматы.

GIF и PDF

Формат Начальная сигнатура Конечная сигнатура
GIF 0x47 0x49 0x46 0x38 0x00 0x3B
PDF 0x25 0x50 0x44 0x46 0x0A 0x25 0x25 0x45 0x4F 0x46
PDF документ может иметь более одного EOF-маркера, например, из-за неправильной генерации документа. Количество конечных сигнатур в GIF-файле равно количеству кадров в нем. Исходя из особенностей этих форматов, можно улучшить алгоритм проверки наличия приклеенных файлов.

  1. Пункт 1 повторяется из предыдущего алгоритма.
  2. Пункт 2 повторяется из предыдущего алгоритма.
  3. При нахождении конечной сигнатуры запомнить её расположение и искать дальше;
  4. Если таким образом дошли до последнего EOF-маркера — файл чист.
  5. Если файл не заканчивается конечной сигнатурой — goto место последней найденной конечной сигнатуры.

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

ZIP


Особенность ZIP-архивов заключается в наличие трех различных сигнатур:
Сигнатуры Описание
0x50 0x4B 0x03 0x04 Сигнатура обычного архива
0x50 0x4B 0x05 0x06 Сигнатура пустого архива
0x50 0x4B 0x07 0x08 Сигнатура архива, разделенного на части
Структура архива такова:
Local File Header 1
File Data 1
Data Descriptor 1
Local File Header 2
File Data 2
Data Descriptor 2
...
Local File Header n
File Data n
Data Descriptor n
Archive decryption header
Archive extra data record
Central directory
Больше всего интересна центральная директория, которая содержит метаданные о файлах в архиве. Центральная директория всегда начинается с сигнатуры 0x50 0x4b 0x01 0x02 и заканчивается сигнатурой 0x50 0x4b 0x05 0x06, после которых следует 18 байт метаданных. Что интересно, пустые архивы состоят только из конечной сигнатуры и 18 нулевых байт. После 18 байт следует область комментария к архиву, которая является идеальным контейнером для скрытия файла.

Для проверки ZIP-архива необходимо найти конечную сигнатуру центральной директории, пропустить 18 байт и искать сигнатуры известных форматов в области комментария. Большой размер комментария также свидетельствует о факте склейки.

Размер имеет значение


AVI


Структура AVI-файла следующая: каждый файл начинается с сигнатуры RIFF (0x52 0x49 0x46 0x46). На 8 байте идет уточняющая формат сигнатура AVI (0x41 0x56 0x49 0x20). Блок на смещении 4, состоящий из 4 байт, содержит начальный размер блока данных (порядок байт — little endian). Чтобы узнать номер блока, содержащего следующий размер, необходимо сложить размер заголовка (8 байт) и размер, полученный в блоке 4-8 байт. Таким образом вычисляется полный размер файла. Допускается, что вычисленный размер может быть меньше, чем реальный размер файла. После вычисленного размера файл будет содержать только нулевые байты (необходимо для выравнивания границы в 1 Кб).

Пример вычисления размера:


Смещение Размер Следующее смещение
4 31442 8+31442=31450

WAV


Как и AVI, WAV-файл начинается с сигнатуры RIFF, однако, у этого файла сигнатура с 8 байта — WAVE (0x57 0x41 0x56 0x45). Размер файла вычисляется таким же образом, как и AVI. Реальный размер должен полностью совпадать с вычисленным.

MP4


MP4 или MPEG-4 – формат медиаконтейнера, используемый для хранения видео- и аудиопотоков, также предусматривает хранение субтитров и изображений.
На смещении 4 байта расположены сигнатуры: тип файла ftyp (66 74 79 70) (QuickTime Container File Type) и подтип файла mmp4 (6D 6D 70 34). Для распознания скрытых файлов, нас интересует возможность вычисления размера файла.



Рассмотрим пример. Размер первого блока находится на нулевом смещении, и он равен 28 (00 00 00 1С, порядок байт Big Endian); он же указывает на смещение, где находится размер второго блока данных. На 28 смещении находим следующий размер блока равный 8 (00 00 00 08). Чтобы найти следующий размер блока, необходимо складывать размеры найденных предыдущих блоков. Таким образом, вычисляется размер файла:
Смещение Значение Следующее смещение
0 28 28+0=28
28 8 28+8=36
36 303739 36+303739=303775
303775 6202 303775+6202=309977

MOV


Этот широко используемый формат является также контейнером MPEG-4. MOV использует проприетарный алгоритм сжатия данных, имеет похожую на MP4 структуру и используется в тех же целях — для хранения аудио и видеоданных, а также сопутствующих материалов.
Как и MP4, любой mov-файл имеет на 4 смещении 4-х байтную сигнатуру ftyp, однако, следующая сигнатура имеет значение qt__ (71 74 20 20). Правило вычисления размера файла не изменилось: начиная с начала файла вычисляем размер следующего блока и складываем.

Метод проверки этой группы форматов на наличие «приклеенных» файлов заключается в вычислении размера по заданным выше правилам и сравнении его с размером проверяемого файла. Если текущий размер файла много меньше вычисленного, то это указывает на факт склейки. При проверке AVI-файлов допускается, что вычисленный размер может быть меньше размера файла из-за наличия добавленных нулей для выравнивания границы. В таком случае, необходимо проверять нули после вычисленного размера файла.

Проверяем Compound File Binary Format


Этот формат файла, разработанный в Microsoft, также известен под названием OLE (Object Linking and Embedding) или COM (Component Object Model). Файлы DOC, XLS, PPT принадлежат к группе CFB-форматов.

CFB-файл состоит из 512-байтного заголовка и секторов одинаковой длины, хранящих потоки данных или служебную информацию. Каждый сектор имеет свой собственный неотрицательный номер, исключение составляют специальные номера: «-1» — нумерует свободный сектор, «-2» — нумерует сектор, замыкающий цепочку. Все цепочки секторов определены в FAT-таблице.



Предположим, что злоумышленник модифицировал некий doc-файл и вклеил в его конец другой файл. Есть несколько различных способов его обнаружить или указать на аномалию в документе.

Аномальный размер файла


Как было сказано выше, любой CFB-файл состоит из заголовка и секторов равной длины. Чтобы узнать размер сектора, необходимо считать двухбайтное число на 30 смещении от начала файла и возвести 2 в степень этого числа. Данное число должно быть равно или 9 (0x0009), или 12 (0x000C), соответственно, размер сектора файла равен 512 или 4096 байт. После нахождения сектора необходимо проверить следующее равенство:

(FileSize — 512) mod SectorSize = 0

Если это равенство не выполняется, то можно указать на факт склейки файлов. Однако этот метод имеет существенный недостаток. Если злоумышленник знает размер сектора, то ему достаточно приклеить свой файл и ещё n байт, чтобы величина приклеенных данных была кратна размеру сектора.

Неизвестный тип сектора


Если злоумышленник знает о методе обхода предыдущей проверки, то данный метод может детектировать наличие секторов с неопределенными типами.

Определим равенство:

FileSize = 512 + CountReal * SectorSize, где FileSize — размер файла, SectorSize — размер сектора, CountReal — количество секторов.

Определим также следующие переменные:

  1. CountFat – количество секторов FAT. Находится на 44 смещении от начала файла (4 байта);
  2. CountMiniFAT – количество секторов MiniFAT. Находится на 64 смещении от начала файла (4 байта);
  3. CountDIFAT – количество секторов DIFAT. Находится на 72 смещении от начала файла (4 байта);
  4. CountDE – количество секторов Directory Entry. Для нахождения этой переменной необходимо найти первый сектор DE, который находится на 48 смещении. Затем необходимо получить полное представление DE из FAT и посчитать число DE-секторов;
  5. CountStreams – количество секторов с датастримами;
  6. CountFree – количество свободных секторов;
  7. CountClassified – количество секторов с определенным типом;

CountClassified = CountFAT + CountMiniFAT + CountDIFAT + CountDE + CountStreams + CountFree

Очевидно, что при неравенстве CountClassified и CountReal можно сделать вывод о возможной склейке файлов.

Использованные источники:


Разбор структуры MP4
Разбор структуры AVI
Разбор структуры MOV
Разбор структуры WAV
O-checker: Detection of Malicious Documents through Deviation from File Format Specifications
Спецификации формата GIF
Спецификации формата PDF
Статья про JPEG на Википедии
Разбор структуры ZIP

Комментарии (27)


  1. teecat
    04.09.2017 13:05

    Эх чуть бы пораньше. Буквально пару дней назад искал такую информацию, чтобы объяснить подобное на пальцах.
    Но все равно спасибо!


    1. Tsyganov_M Автор
      04.09.2017 14:26

      Надеюсь, материал вам пригодится.


  1. al_sh
    04.09.2017 13:35

    В jpeg далеко не всегда файл заканчивается 0xFF 0xD9. Можете снести их и файл откроется в большинстве смотрелок. Этим грешат некоторые мобилки.


    1. Tsyganov_M Автор
      04.09.2017 14:34

      Ценное замечание. Однако сделан расчет на то, что злоумышленник не будет каким-либо образом модифицировать файл исходного формата, кроме как приклеивать вложение. Если же конечная сигнатура была удалена, то можно попробовать найти вложение простым сигнатурным поиском по файлу.


      1. qw1
        04.09.2017 23:06

        А не будет ли наоборот, ложных срабатываний, потому что маркер FF D9 просто статистически встретится внутри huffman-потока? Я взял несколько больших jpeg и пару раз нашёл FF D9 в середине файла


        1. Tsyganov_M Автор
          05.09.2017 00:59

          Если FF D9 встречается несколько раз, то можно проверять jpeg по принципу pdf и gif, где их "конечные" сигнатуры могут повторяться. Даже если будет не последний FF D9 будет найден, то после него область файла будет проверяться поиском сигнатур, длина которых от 4 байт и выше. Вероятность ЛПС в таком случае крайне невысокая.


  1. nvv
    04.09.2017 16:58

    Что делать если «злоумышленник» приклеит «нагрузку» к обычному файлу TXT, который по определению не имеет заранее заданного формата?
    Просматривать всё содержимое таких файлов, независимо от размера, на предмет поиска известных сигнатур и пытаться выделить файлы по сигнатурам для подтверждения гипотезы?


    1. al_sh
      04.09.2017 17:02

      ну конкретно для тхт ИМХО индикатором может служить символ не входящий в кодировку


      1. lostpassword
        05.09.2017 07:48

        Перегнать предварительно данные в Base64 — и нет проблем.)
        Хотя это тоже можно будет детектировать, конечно. Но есть и другие способы кодирования.


  1. nvv
    04.09.2017 17:09

    В кодировку чего?
    txt может быть и в UTF и в ANSI и в др.кодировке кодировке.


    1. al_sh
      04.09.2017 17:21

      Ок. В случае, если Вы знаете или можете определить в какой кодировке у Вас файл. Более того, в качестве гипотезы, вполне вероятно, что существует сочетания, которых нет ни в одной распространенной кодировке.


      1. qw1
        04.09.2017 23:04

        К текстам надо приклеивать base64-encoded данные.
        Или, чтобы не было подозрений на слишком длинные строки, кодировать в UUE


    1. vesper-bot
      04.09.2017 18:07

      Если при парсинге в мультибитовую кодировку в массиве символов оказываются 0х00-0x1F, исключая 0x0D и 0x0A, это скорее всего бинарник. При этом проверять имеет смысл всего три — UTF8LE, UTF8BE, UTF16 (она ЕМНИП только LE).


      1. nvv
        04.09.2017 20:28

        А если это win1251 или koi8-r окажется?


        1. vesper-bot
          05.09.2017 09:09

          А разве в них как в массиве байт в нормальном виде есть 0х00-0x1F, исключая 0x0D и 0x0A? Другое дело, если этот текстовик будет на каком-нибудь 05AB1E, где уже вполне могут попадаться символы из этого диапазона. Однако процент текстовых файлов на всяких экзотических ЯП вроде этого позволяет им пренебречь при анализе потенциально склеенных файлов.


  1. thelongrunsmoke
    04.09.2017 21:28
    +1

    С точки зрения борьбы с zip-бомбой такие проверки подойдут, но есть более изящные средства. С точки зрения поиска стеганографических весселов, существует много способов сокрытия, и создать графический файл содержащий в себе, скажем, архив и проходящей проверки на структуру вполне возможно.
    Однако, для хранения, изображения и видео всё равно надо перекодировать, при определённых настройках, любая сокрытая информация будет потеряна.


  1. qw1
    04.09.2017 23:07

    Предположим, что злоумышленник модифицировал некий doc-файл и вклеил в его конец другой файл
    Разумнее класть новый файл сразу в файловую систему Compound. Или даже не в новый файл, а по принципу rarjpeg в один из объектов контейнера.


    1. Tsyganov_M Автор
      05.09.2017 01:08

      В данной статье я описал не способы сокрытия файлов, но методы обнаружения вложений, которые приклеены к концу файла, а не внедрены в его структуру в качестве составной части.


  1. impfromliga
    05.09.2017 05:16

    Это интересно, но мой стеганограф написанный еще в лохматом году на бейсике не возьмет.

    Не кидайте кирпичи, я не критикую статью, сам такие методы поиска не знал, просто дополняю что есть способы спрятать и по лучше.

    На мой взгляд такой вид сокрытия даты слишком наивен.
    Я складывал в младшие значащие биты png (визуально незаметно, к тому же если это фото там есть естественный шум матрицы) к слову сказать спрятать дату можно абсолютно в любой медийный формат допускающий субъективно незаметные огрехи.

    Для jpeg'а только пришлось бы внедриться в формат кодирования. Найти в нем парные взаимоисключающие условия и на стадии кодирования подменять их в обход правильного кодирования (только в местах мало влияющих на визуальный результат) своим выбором

    И в jpeg конечно можно внедрить значительно меньше даты без видимых артефактов

    Я видал стеганографф даже для mp3
    В простейшем случае для mp3 берется малораспространенный ABR (Avarage Bit Rate) — его суть в том, что он берет для фрейма строго заданный размер. (И чем же это отличается от CBR спросите вы) Дело в том, что он продолжает пытаться сжать сильнее (например тишину), и оставшееся место накапливает, для расширения следующих фреймов. (Само собой это означало бы невозможность реалтаймового кодирования с трансляцией, ведь данные для будущих фреймов должны были бы содержаться в уже переданных) Но еще он ограничивает возможность подключать оставшееся место дальше чем условно на время t. Таким образом он все таки может передаваться почти реалтаймово, с «пингом» воспроизведения в несколько секунд. (Естественно это юзалось в основном при потоковом прослушивании напрмер радиостанций, но не колл-войса)

    Так вот, в связи с тем, что периодически этот формат теряет «запасы» слишком далеких полупустых фреймов, туда можно свободно записать что угодно.

    Хотя даже этот метод с mp3 ближе к вашему описанию, и послабее защищен чем кодирование «со специальными ошибками» (естественно и для классического cbr/vbr можно реализовать мудреный алг «ошибочного кодирования», но это потребует разбираться в формате досконально)


    1. thelongrunsmoke
      05.09.2017 07:16

      Речь идёт не о полноценной стеганографии, а исключительно о составных файлах.


    1. Tsyganov_M Автор
      05.09.2017 17:40

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


  1. DimonSmart
    05.09.2017 07:16

    Приложу ссылочку на ещё одну интересную методику сокрытия информации:
    http://old.computerra.ru/gid/rtfm/office/327832/
    Было бы очень интересно услышать комментарии авторов на эту тему.


    1. DimonSmart
      05.09.2017 07:21
      +1

      Склеивание файлов
      Возможно ссылка не совсем точная. Но суть в том, что используя особенности контейнера можно сделать файл, котрый будет _одновременно_ и word и excel и при открытии соответствующей программой будет работать и так и так. Но по расширению то это один файл! и сложно догадаться проверить например word на предмет возможности открытия его как excel.
      Было бы очень интересно услышать комментарии авторов на эту тему.


    1. Tsyganov_M Автор
      05.09.2017 17:46

      В материале по данной ссылке не описана подробная методика сокрытия doc файла в xls, а скорее гайд, как пользоваться готовой программой, принцип работы которой не раскрывается.


  1. Andrew1411
    07.09.2017 11:51

    Формат CFB позволяет внедрить в его внутреннюю файловую систему «нагрузку». Лет 6 назад проверял, запихифая из плагина для фар в doc файл и .zip и .exe. Word при открытии «нагруженных» документов молчал, никак не замечая нагрузку.


    1. Tsyganov_M Автор
      07.09.2017 11:51

      Как именно происходило внедрение «нагрузки»?


      1. qw1
        07.09.2017 20:18

        API предоставляет Windows
        habrahabr.ru/post/254541