Security Lab

USN Journal и VSS против Timestomping в NTFS. Как увидеть подмену времени

1210
USN Journal и VSS против Timestomping в NTFS. Как увидеть подмену времени

Файл лежит в C:Windows и уверяет, что появился там пять лет назад. Проводник верит. PowerShell тоже показывает старую дату. Я бы не верил ни одному из них, пока не посмотрел на $MFT и историю файловой системы. В NTFS время файла хранится не в одном месте, а операция подмены даты оставляет следы, которые значительно сложнее согласованно переписать.

Timestomping в терминологии MITRE ATT&CK относится к технике T1070.006. Базовая проверка сравнивает временные метки $STANDARD_INFORMATION и $FILE_NAME. Но для нормального расследования я добавляю USN Journal и доступные снимки VSS. Причём есть важная ловушка. USN_REASON_BASIC_INFO_CHANGE сам по себе не доказывает вызов SetFileTime, а USN_RECORD_V4, вопреки иногда встречающимся схемам, вообще не содержит полей TimeStamp и FileAttributes.

Материал посвящён цифровой криминалистике и расследованию инцидентов на системах, к которым у исследователя есть законный доступ. Изменять метаданные чужих систем или уничтожать журналы ради сокрытия активности не следует.

Почему одного сравнения $SI и $FN уже мало

В записи $MFT у обычного файла есть два набора временных меток. $STANDARD_INFORMATION, сокращённо $SI, содержит время создания, изменения содержимого, доступа и изменения самой MFT-записи. Именно эти значения обычно видят Windows API и пользовательские программы.

SetFileTime позволяет приложению с правом FILE_WRITE_ATTRIBUTES менять время создания, последнего доступа и записи файла. Поэтому простейший timestomping выглядит почти банально. Вредоносная программа берёт даты старого системного файла и назначает их своему пейлоаду. В проводнике новый файл внезапно становится ровесником Windows.

Вторая копия временных меток находится в $FILE_NAME, сокращённо $FN. Обычный вызов SetFileTime напрямую её не переписывает. Поэтому ситуация вроде следующей выглядит подозрительно.

$STANDARD_INFORMATION
 Created: 2021-04-11 08:32:14
 
 $FILE_NAME
 Created: 2026-09-30 22:17:51

Файл как будто существовал в $SI за пять лет до появления, которое отражает $FN. Для классического timestomping такой разрыв очень характерен.

Но превращать любое несовпадение $SI и $FN в автоматический вердикт нельзя. Операции перемещения, переименования и работы с жёсткими ссылками могут обновлять $FN. Некоторые варианты так называемого double timestomping используют именно свойства NTFS при переименовании, чтобы добиться гораздо более правдоподобного набора метаданных. Резервное восстановление, синхронизация, миграция данных и специализированные программы тоже способны создавать необычные временные последовательности.

Поэтому я рассматриваю $SI/$FN как первый слой проверки, а не как последний.

Как я проверяю подозрительный файл через USN Journal

USN Change Journal хранит последовательность изменений объектов NTFS. Сначала полезно проверить, существует ли журнал и какой диапазон USN ещё сохранился.

fsutil usn queryjournal C:

Для первичного просмотра записей можно использовать встроенный fsutil. Я ограничиваю версии V2 и V3, если мне нужны обычные записи с временной меткой.

fsutil usn readjournal minver=2 maxver=3 startusn=0 C:

В реальном расследовании удобнее работать не с консольной простынёй, а с извлечёнными $J и $MFT. Например, MFTECmd умеет разобрать их вместе и восстановить пути по MFT.

MFTECmd.exe -f "C:Evidence$J" -m "C:Evidence$MFT" --csv "C:Evidenceout"
 
 MFTECmd.exe -f "C:Evidence$MFT" --csv "C:Evidenceout" --at

Ключевой для timestomping флаг имеет значение 0x00008000.

USN_REASON_BASIC_INFO_CHANGE = 0x00008000

Microsoft описывает BASIC_INFO_CHANGE как изменение одного или нескольких атрибутов файла либо временных меток. Причиной действительно может быть SetFileTime, но тем же флагом отмечаются изменения таких свойств, как read-only, hidden, system, archive или sparse. Поэтому логика «есть BASIC_INFO_CHANGE, значит злоумышленник скрутил дату» неверна.

Намного интереснее последовательность событий для одного FileReferenceNumber. Допустим, $MFT сообщает, что файл создан в 2021 году. В $J я нахожу его реальное появление на томе в сентябре 2026 года, а через несколько секунд для того же файлового объекта возникает BASIC_INFO_CHANGE. После операции $SI внезапно уезжает в 2021 год. Такая комбинация уже намного сильнее одиночного расхождения $SI/$FN.

Поле TimeStamp в USN_RECORD_V2 содержит UTC-время самой записи журнала. SetFileTime не позволяет приложению подставить туда желаемую дату файла. Но я не называл бы значение абсолютными часами истины. USN использует системное время компьютера, а системные часы тоже можно изменить. Кроме того, Reason-флаги могут накапливаться до закрытия объекта, поэтому время USN-записи не всегда равно моменту конкретного API-вызова с точностью до миллисекунды.

Отдельная ошибка встречается в описаниях USN_RECORD_V4. У структуры V4 есть Reason, SourceInfo и сведения о диапазонах изменений, но нет TimeStamp, FileAttributes и имени файла. V4 используется для USN range tracking и не является расширенной версией V2 со всеми прежними полями.

Артефакт Что показывает Насколько силён сигнал
$SI против $FN Несогласованные временные метки Хороший первичный индикатор
USN FILE_CREATE Появление объекта на томе Сильный элемент временной линии
USN BASIC_INFO_CHANGE Изменение метаданных или времени Требует контекста
EDR / API telemetry Вызов SetFileTime или NtSetInformationFile Очень сильная корреляция
VSS Предыдущее состояние MFT и файла Сильный независимый источник

Что добавляет VSS diffing

USN Journal не вечен. Журнал имеет ограниченный размер, старые записи со временем уходят, а сам журнал можно пересоздать. Поэтому второй независимый источник для меня гораздо ценнее красивого одиночного IOC.

Сначала проверяю, какие теневые копии вообще существуют.

vssadmin list shadows /for=C:

VSS представляет состояние тома в определённый момент времени. Встроенный системный провайдер Windows использует copy-on-write. Перед изменением блока исходное содержимое сохраняется в области различий, благодаря чему VSS может позднее представить старое состояние тома. Сам VSS как архитектура допускает и другие типы провайдеров, поэтому утверждение «любая VSS-копия представляет собой COW-дифф» слишком широкое.

Для расследования мне интересен не столько внутренний формат diff area, сколько результат. Я сравниваю MFT-запись исследуемого файла в историческом снимке и в текущем состоянии.

Представим временную линию. Файл сейчас заявляет Created = 2021-04-11. Существует снимок VSS от августа 2026 года, где файла ещё нет. В сентябре USN фиксирует появление соответствующего объекта, затем BASIC_INFO_CHANGE, после которого $SI показывает 2021 год. Подобная цепочка практически уничтожает доверие к текущей дате создания.

Но отсутствие файла в старом VSS я всё равно не называю самостоятельным доказательством атаки. Файл могли восстановить из резервной копии с сохранением исходных временных меток, перенести специализированной программой или развернуть из образа. VSS становится действительно ценным, когда совпадает с USN, $MFT и другой телеметрией.

Ещё интереснее случай, когда файл присутствует в двух снимках. В старой копии $SI содержит дату 2026 года, а в текущей записи та же метка неожиданно превращается в 2021 год. Тут уже можно непосредственно увидеть изменение метаданных между двумя состояниями тома.

Когда я считаю Timestomping подтверждённым

Я не строю детект на одном условии. Практическое правило выглядит примерно так.

  1. Нахожу подозрительную временную последовательность в $SI и $FN.
  2. Привязываю файл к FileReferenceNumber, а не только к имени и пути.
  3. Ищу в $J создание, переименование, перемещение и BASIC_INFO_CHANGE.
  4. Сравниваю временную линию USN с текущими значениями $MFT.
  5. Проверяю доступные VSS-снимки.
  6. При наличии EDR ищу процесс, который менял метаданные файла через SetFileTime, NtSetInformationFile или родственные механизмы.

Сильная картина выглядит не как «даты отличаются», а как причинная цепочка. Новый объект появляется на диске, через короткий промежуток меняет basic information, после чего приобретает временные метки старого легитимного бинарника. Исторический снимок подтверждает прежнее состояние, а процессная телеметрия связывает изменение с конкретным процессом.

Есть и пределы метода. Прямое офлайн-редактирование NTFS может обойти обычную последовательность USN. Очистка или переполнение журнала уничтожает старые записи. Удалённый файл может получить новую MFT-запись, а старые File Reference Numbers со временем переиспользуются. Подмена системных часов влияет на временную линию нескольких источников сразу. Продвинутый timestomping способен уменьшить различия $SI/$FN через операции с именами и ссылками.

Поэтому лучший детектор здесь не одна сигнатура, а независимые часы. $MFT рассказывает, что файл утверждает о себе сейчас. USN Journal показывает, какие операции NTFS видел раньше. VSS даёт состояние тома до изменения. EDR добавляет процесс, который инициировал операцию. Чем больше независимых линий сходятся в одной точке, тем меньше шансов объяснить аномалию обычной работой Windows.

FAQ

USN_REASON_BASIC_INFO_CHANGE точно означает SetFileTime?

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

Почему нельзя просто сравнить $STANDARD_INFORMATION и $FILE_NAME?

Несовпадение полезно как индикатор, но переименование, перемещение, восстановление данных и другие нормальные операции тоже меняют отношения между временными метками. Double timestomping дополнительно пытается устранить такой индикатор.

Есть ли TimeStamp в USN_RECORD_V4?

Нет. USN_RECORD_V4 содержит USN, Reason, SourceInfo и данные range tracking, но не содержит TimeStamp и FileAttributes. Временная метка присутствует в классических структурах V2 и V3.

Можно ли считать время USN абсолютно достоверным?

Нет. SetFileTime не управляет временем USN-записи, но сама запись зависит от системных часов Windows. При расследовании нужно учитывать возможную смену системного времени и особенности накопления Reason-флагов.

USN Journal хранит всю историю тома?

Нет. Размер журнала ограничен. NTFS постепенно удаляет старые записи, поэтому отсутствие события в текущем $J не доказывает, что события никогда не было.

Что делать, если VSS отсутствует?

Сопоставлять $MFT, $UsnJrnl, EDR, Sysmon, журналы Security, Prefetch, Amcache и другие доступные артефакты. VSS усиливает расследование, но не является обязательным условием.

Какой признак я бы проверил первым?

Сначала посмотрел бы все временные метки $SI и $FN, затем нашёл тот же файловый объект в USN Journal. Такая последовательность быстро показывает, есть ли смысл тратить время на VSS и глубокую корреляцию.

Мой вывод простой. Для старого примитивного timestomping сравнение $SI и $FN по-прежнему отлично работает, но современное расследование не должно на нём останавливаться. Самый полезный уровень начинается при корреляции $MFT, USN Journal и VSS. При этом BASIC_INFO_CHANGE нельзя выдавать за прямое доказательство SetFileTime, а поля V2 нельзя механически переносить на USN_RECORD_V4. Если временная линия из трёх независимых источников сходится, поддельной дате файла становится гораздо труднее притворяться историей.

NTFS timestomping USN VSS форензика
Alt text
Обращаем внимание, что все материалы в этом блоге представляют личное мнение их авторов. Редакция SecurityLab.ru не несет ответственности за точность, полноту и достоверность опубликованных данных. Вся информация предоставлена «как есть» и может не соответствовать официальной позиции компании.
Москва • 15 октября • Москва • 15 октября • Москва • 15 октября • Москва • 15 октября • Москва • 15 октября • Москва • 15 октября • Москва • 15 октября • Москва • 15 октября • ● 15.1015.10Большая играЕжегодная IT-конференция Orion SoftРегистрация→Реклама. 18+ ООО «Орион» ИНН 9704113582