waqur: (Евро)
[personal profile] waqur
Официальная спецификация файловой системы FAT от фирмы Microsoft (когда-то бывшая доступной для скачивания с сайта microsoft.com, а сейчас циркулирующая по сети под именем fatgen103.{doc,pdf}) обозначает как "зарезервированные для Windows NT" некоторые поля и флаги дисковых структур файловой системы. Действительно, Windows NT всех версий использует их.



Впрочем, исходные коды драйвера файловой системы FAT (fastfat.sys) публиковались неоднократно. Так, они вошли в утечку исходных кодов Windows NT 4.0 и Windows 2000, они есть в Windows 2003 IFS DDK, а в составе Windows 7 WDK присутствует целая коллекция разных версий этого драйвера: для Windows XP; для невыпущенной Windows .NET, примерно соответствующей Windows 2003 Server; для Windows Longhorn, которая была выпущена под именем Vista SP1; и для Windows 7). Насколько я могу судить, никаких изменений в этом драйвере на интервале между Windows 2000 и Windows 10 не было. В fastfat.sys из релизной версии Windows NT 4.0 не было поддержки FAT32, но позже её добавили сервис-паком.

Итак, недокументированные особенности файловой системы FAT, которые реализует Microsoft`овский драйвер этой файловой системы, но упускает официальная спецификация:

1. В загрузочном секторе однобайтовое поле BS_Reserved1 (сразу за BIOSовским номером диска) содержит флаг грязной файловой системы (бит 0) и флаг необходимости проверки поверхности (бит 1). Грязная файловая система — это та, которая не была корректно размонтирована (например, резко выдернутая флешка или раздел жёсткого диска после незапланированной перезагрузки). Перед монтированием для такой файловой системы вызывается chkdsk, если это возможно. chkdsk может попутно проверить и поверхность диска, если для него был установлен бит 1 (который взводится, когда драйвер натыкается на бэдблоки).

2. В случае FAT32, элемент таблицы размещения файлов под индексом 1 (считая от нуля), для которого не существует соответствующего кластера, тоже используется как флаг грязной файловой системы для совместимости с Windows 95/98 (значение 0xF0000000 = ФС чистая, значение 0xF0000001 = ФС грязная). В остальных элементах этой таблицы, старшие 4 бита обнуляются при считывании, и бережно сохраняются при обновлении младших 28 бит (как и требует спецификация).

3. Требование официальной спецификации маскировать файловые атрибуты в элементах каталога AND-маской 0x3F наводит на соображения о существовании недокументированных атрибутов. Так и есть, 0x40 — это устройство. Драйвер fastfat сам такое не создаёт, но и не даёт доступа к существующим элементам каталога с этим атрибутом. Так что, действуя в обход драйвера, можно создать неудаляемый файл. Но и читаться он тоже не будет. Откуда оно вообще взялось — ума не приложу, потому что ни SFU/SUA/Interix, ни WSL/LXSS/ProjectDrawbridge/ProjectAstoria не имеют к этому никакого отношения. Наверное, ещё из Xenix. Программисты из Microsoft'а могли бы хранить расширенные атрибуты (EA) в таком файле вместо создания уродца под неудаляемым названием "EA DATA. SF", "але маємо те що маємо" (c).

4. Однобайтовое поле по смещению 0x0C в элементах каталога (DIR_NTRes) используется для хранения двух дополнительных флагов. Бит 3 означает, что короткое 8-символьное имя из SFN-записи каталога подлежит переводу на нижний регистр в контексте драйвера. Бит 4 означает, что с коротким 3-символьным расширением нужно сделать то же самое. Эти биты позволяют экономить место в каталоге на несоздании LFN-записей, в случае монорегистровых имён формата 8.3. По этой же причине Linux и другие независимые от Microsoft операционные системы вечно не могут "угадать" регистр коротких ASCII-имён формата 8.3.

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

Во-первых, если очередной символ из имени файла не поддаётся Unicode-to-OemCodePage-перекодированию, тогда он просто выбрасывается с установкой флага наличия потерь, а не заменяется на "_". Хотя замена на "_" по-прежнему применяется для ASCII-символов, допустимых в длинных именах, но недопустимых в коротких именах ("+,;=[]").

Во-вторых, в природе иногда встречается такой феномен, как 16-битная LFN контрольная сумма, которая цепляется перед тильдой с цифрой в SFN-записях файлов (например "TextFile.Mine.txt" -> "TE021F~1.TXT"). Правда, эта контрольная сумма вычисляется не драйвером FAT, а runtime-библиотекой ядра Windows NT, а конкретно функцией RtlComputeLfnChecksum(), по общему для FAT и NTFS алгоритму. 16-битная LFN контрольная сумма вставляется в короткое имя в двух случаях: либо когда с четвёртой попытки не удаётся подобрать уникализирующую SFN-имя цифру после тильды, либо когда количество символов короткого имени файла после перекодирования Unicode-to-OemCodePage стало меньше трёх и при этом само перекодирование произошло с потерями (теми самими потерями, которые по спецификации требуют замены на "_", а на практике влекут пропуски).

Алгоритмов для этой 16-битной контрольной суммы LFN вообще-то существует два: старый (весьма коллизионный), который использовался до Windows 7 (есть в исходниках утечки, также легко дизассемблируется из статической библиотеки в составе Windows Research Kernel); и новый (получше), который применяется, начиная с Windows 7 — и он тоже был успешно дизассемблирован. Алгоритм для 16-битной контрольной суммы LFN из ReactOS не совпадает ни с одним из этих двух Microsoft'овских.


Другие особенности:

1. Несмотря на наличие номера ведущей копии FAT в загрузочном секторе FAT32, драйвер FASTFAT не поддерживает copy-on-write семантику обновления диска, т.е. запись изменённых метаданных в свободное место диска и в ведомую копию FAT с последующим атомарным переключением номера ведущей копии FAT и номера стартового кластера корневого каталога. Хотя поддержка такой фичи (под названием "TFAT") когда-то была в Windows CE. Рождённый ползать летать не может. Нечего требовать от FAT фич уровня ZFS или UFS+SoftUpdates. Хотя, может быть, такие фичи были бы полезны с учётом того, что в ближайшие десятилетия нам никуда не деться от файловой системы FAT в EFI System Partition.

2. Также мне всегда было интересно, как официально называется режим драйвера файловой системы FAT, когда драйвер (не) поддерживает длинные имена файлов.

В Linux это различие именуется vfat/msdos, потому что в Windows 95, откуда пингвинятники в своё время позаимствовали терминологию, вариант без поддержки длинных имён был реализован в MSDOS.SYS, а вариант с поддержкой длинных имён — в VFAT.VXD. Впрочем, Virtual FAT (из версионной информации последнего) указывает скорее на использование драйвером режима виртуальной памяти 386-го процессора, чем на особенность формата файловой системы. Так и есть.

В официальной Microsoft'овской спецификации на файловую систему FAT этот режим никак специально не называется. "Поддержка длинных имён файлов" и всё. Точно так же и в драйвере файловой систем FAT для BSD-систем (там все виды FAT именуются msdosfs): опция именуется longnames и всё.

А вот NT-драйвер файловой системы FAT внутренне именует этот режим "Chicago Mode". Всё просто: Chicago — это предрелизное имя операционной системы Windows 95.

Date: 2016-08-10 09:58 pm (UTC)
From: [identity profile] dibrov-s.livejournal.com
Давным-давно, в 1990-91 учебном году, я, тогда еще студент-второкурсник, изучал недокументированные особенности fat в msdod. Винчестеры тогда были маленькие (10 мбайт), а центы на сменные носители - большие (1$/360к). Поэтому целью исследований был поиск возможностей незаметного для санитаров преподов и лаборантов способов хранения личной информации (курсовики и лабораторки) на институтских машинах, которые нещадно чистили от чужих файлов и после каждой пары беспощадно проверяли Нортон Диск Доктором.

После ряда экспериментов я установил, что записи в каталогах, имеющие атрибут "метка диска", могут на самом деле соответствовать файлам, которые не отображаются штатными (dir) и нештатными (nc) инструментами, не опознаются как потерянные через ndd и chkdsk.com. Если при этом обозначить их как hidden, они не были видны и как метки диска. То есть вообще никак не давали о себе знать.

Скрывать таким образом каталоги было нельзя, потому что содержимое таких каталогов ndd опознавал как потерянные цепочки и удалял. Поэтому я написал простенькую консольную утилиту, которая превращала подкаталог корневого каталога со всем его содержимым в одну длинную цепочку с EOF на конце, цепляла к записи в корневом каталоге и ставила ему атрибуты hidden и volume_label.

Затем я оснастил утилиту инсталлятором, который генерировал для каждой копии уникальный ключ (512 байт! правда, с 16-разрядного программного ГСЧ :) ), которым через банальный XOR шифровалось содержимое этой цепочки. Целью была, во-первых, какая-никакая криптозащита (чтобы преподы и лаборанты, раскопав это безобразие, по содержимому не вычислили злоумышленника). Во-вторых, обеспечивалась приватность: каждый владелец экземпляра программы видел только "свои" закрытые каталоги и не подозревал об активности других. Наконец, это был правильный маркетинговый ход: владельцы экземпляров не делились ими, чтобы сохранить свои данные. Это обеспечило стабильный спрос и приток новых клиентов :) Черный рынок расцвел; я продал штук пять экземпляров, не считая розданных бесплатно (по дружбе и в маркетинговых целях). Доход получился в размере одной повышенной стипендии. :)

Афера так и осталась незамеченной: хотя размеры полезного пространства на винчестерах странным образом таяли, ndd (истина в последней инстанции для сотрудников) говорил, что все нормально, а форматировка с переустановкой системы как способ лечения проблем в те времена особо не практиковалась. Однако вскоре на кафедре появились новые компы с огромными винтами на 40 и 80 мбайт и дисководами на 1,44", и моя программа потеряла актуальность.

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

Кстати, недавно я нашел студенческую коробку для дискет, можно бы глянуть, что там сохранилось. Правда, остается вопрос, куда их сейчас совать и что с ними стало за четверть века :)

July 2017

S M T W T F S
      1
2345 678
9101112131415
16171819202122
23242526272829
3031     

На этой странице

Автор стиля

Развернуть

No cut tags
Page generated 2017-07-23 04:31 pm
Powered by Dreamwidth Studios