Крис Касперски - Восстановление данных. Практическое руководство
Наконец, возможна и такая ситуация, когда утилит восстановления просто не окажется под рукой в тот момент, когда вам срочно потребуется восстановить какой-нибудь ценный файл. Законов Мэрфи еще никто не отменял! В этом случае вам придется рассчитывать только на свои силы.
Ручное восстановление ошибочно удаленных файлов
Начнем с простейшего. Файл только что удален, и принадлежащая ему файловая запись еще не затерта. Как найти его на диске? Существует два способа — "теоретический" и "практический". Теоретический метод исключительно надежен, но требует дополнительных операций, выполнения которых можно избежать, приняв ряд практических допущений.
Теоретически грамотный и правильный подход состоит в следующем. Извлекаем из загрузочного сектора указатель на MFT, извлекаем из нее первую запись (она описывает $MFT), находим атрибут $DATA (80h), декодируем список отрезков (data runs) и последовательно читаем все записи в MFT, анализируя содержимое атрибута $FILE_NAME (30h) — имя файла. Обратите внимание, что таких атрибутов у файла может быть несколько. Этот же атрибут хранит ссылку на родительский каталог. Поэтому, если несколько одноименных файлов были удалены из различных каталогов, то необходимо выяснить, какой именно из них должен быть восстановлен.
Практический подход выглядит следующим образом. В девяти случаях из десяти файл $MFT не фрагментирован и располагается практически в самом начале диска. Имена файлов хранятся по смещению EAh от начала сектора, в начале которого расположена сигнатура FILE* (FILE0 — в NTFS 3.1). Поэтому можно просто запустить любой дисковый редактор (например, Disk Probe из комплекта Support Tools от Microsoft), ввести имя восстанавливаемого файла в кодировке UNICODE и дать редактору указание искать его по смещению EAh (в NTFS 3.1 — F0h) от начала сектора (рис. 7.2).
Рис. 7.2. Ручное восстановление удаленного файла с помощью Disk Probe
Когда же искомая строка будет найдена, необходимо проверить, находится ли в начале сектора сигнатура FILE*/FILE0. Если такой сигнатуры в начале сектора нет, следует продолжить поиск. Двухбайтное поле по смещению 16h от начала сектора содержит флаги записи: 00h — запись не используется или была удалена, 01h — запись используется, 02h — запись используется и описывает каталог. Встречаются и другие значения, например, 04h, 08h. Эти значения не документированы. Возможно, что именно вы сможете пролить свет на этот вопрос?
Исправляем 00h на 01h, записываем изменения и... Ничего не выходит?! А чего вы хотели! Ведь помимо этого необходимо выполнить еще несколько действий. Во-первых, следует сообщить файлу /$MFT:$BITMAP, что данная запись MFT вновь используется. Во-вторых, необходимо исключить из файла /$BITMAP номера кластеров, принадлежащие восстанавливаемому файлу. Наконец, необходимо перестроить двоичное дерево индексов, хранящее содержимое каталога. Первые два пункта не представляют серьезной проблемы, но вот над последней задачей придется повозиться. Хотя ее можно существенно упростить, просто запустив chkdsk с ключом /F. Утилита chkdsk самостоятельно найдет "потерянный" файл и внесет все необходимые изменения в файловую систему (листинг 7.1). От вас потребуется только установить флаг по смещению 16h в единицу, а все остальное сделает chkdsk. После этих нехитрых манипуляций восстановленный файл окажется в своем родном каталоге.
Листинг 7.1. Восстановление удаленного файла при помощи chkdsk
C:chkdsk D: /F
Тип файловой системы: NTFS.
Проверка файлов завершена.
Проверка индексов завершена.
Восстановление потерянных файлов.
Восстановление потерянного файла test.txt в файле каталога 5
Замена неправильного идентификатора безопасности для файла 29
Проверка дескрипторов безопасности завершена.
Исправление ошибок в атрибуте BITMAP основной таблицы файлов.
Windows сделала изменения в файловой системе.
1068290 КБ всего на диске.
20 КБ в 2 файлах.
4 КБ в 9 индексах.
0 КБ в поврежденных секторах.
7894 КБ используется системой.
7392 КБ занято под файл журнала.
1060372 КБ свободно на диске.
Размер кластера: 2048 байт.
Всего кластеров на диске: 534145.
530186 кластеров на диске.
Восстанавливаем руины
Рассмотрим более сложный случай восстановления, а именно — случай, когда файловая запись уже затерта. Если удаленный файл был резидентным (хранил свое тело в MFT), то восстанавливать уже нечего. Даже если на ранее занимаемом им месте создан нерезидентный файл (а файловая запись нерезидентного файла заканчивается там, где начинается резидентное тело), операционная система заботливо заполнит оставшийся "хвост" нулями, и для восстановления оригинального содержимого придется прибегнуть к дорогостоящему оборудованию, читающему поверхность жесткого диска на физическом уровне.
С нерезидентными файлами, хранящими свое тело вне MFT, ситуация обстоит не так плачевно, хотя и здесь проблем тоже хватает. Порядок размещения файла на диске хранится в списке отрезков (run-list) внутри файловой записи в MFT. При этом, поскольку файловая запись уже затерта, возможен лишь контекстный поиск по содержимому. Запускаем дисковый редактор, вводим последовательность, заведомо содержащуюся в удаленном файле, но не встречающуюся во всех остальных, и даем редактору команду начать поиск. Для ускорения поиска можно искать только в свободном дисковом пространстве (за это отвечает файл /$BITMAP). Известные мне редакторы напрасно пренебрегают этой возможностью, однако утилиту "продвинутого" поиска несложно написать и самостоятельно.
Восстановление нефрагментированных файлов осуществляется элементарно. Достаточно просто выделить группу секторов и записать ее содержимое на диск.
Внимание!Повторюсь еще раз — ни в коем случае не записывайте файлы не на сам восстанавливаемый том!
Единственная проблема заключается в определении оригинальной длины. Некоторые типы файлов допускают присутствие "мусора" в своем хвосте. В этом случае можно следовать правилу, гласящему, что перебор лучше недобора. Однако это справедливо не для всех файлов! Если конец файла не удается определить визуально (например, pdf-файлы завершаются сигнатурой %%EOF), проанализируйте заголовок файла. Как правило, наряду с прочей полезной информацией там присутствует и размер файла. В данном случае все зависит от структуры конкретного файла, и универсальных рекомендаций дать невозможно.
Если восстанавливаемый файл фрагментирован, то ситуация осложняется. По правде говоря, она практически безнадежна, поскольку, чтобы собрать разрозненные цепочки кластеров воедино, необходимо хорошо знать содержимое удаленного файла. В этом смысле NTFS восстанавливается намного хуже, чем FAT. Последовательность фрагментов файла, хранящаяся в FAT в виде однонаправленного списка, очень живуча. Если список не поврежден, достаточно лишь найти его первый элемент (а сделать это проще простого, поскольку он будет указывать на заголовок файла с вполне предсказуемым содержимым). Даже если список "разрубить" на несколько частей, они продолжат жить собственной жизнью, и останется лишь подобрать комбинацию, в которой их необходимо склеить воедино. Список гибнет лишь при полном затирании FAT, что случается, прямо скажем, не часто. В NTFS же порядок фрагментов файла хранится в крохотных списках отрезков, и их гибель — обычное дело, после чего мы остаемся один на один с миллионом беспорядочно разбросанных кластеров. С текстовыми файлами еще можно работать, но что делать, если файл представлял собой электронную таблицу, графическое изображение или архив? Без знания стратегии выделения дискового пространства восстановить такой файл невозможно. Порядок, в котором драйвер файловой системы находит подходящие свободные фрагменты, не предопределен. Он варьируется в зависимости от множества обстоятельств, однако некоторые закономерности в нем все же присутствуют.
В ходе анализа списков отрезков сильно фрагментированных дисков мне удалось установить следующие закономерности. Сначала заполняются самые большие "дыры", причем заполнение происходит в направлении от конца зоны MFT к концу диска. Затем драйвер файловой системы возвращается назад и начинает заполнять "дыры" поменьше. Так продолжается до тех пор, пока файл не оказывается на диске целиком. В последнюю очередь заполняются "дыры" размером в один кластер. Просматривая карту диска, представленную файлом /$BITMAP, мы можем в точности восстановить порядок размещения фрагментов удаленного файла, наскоро собрав их воедино. Во всяком случае, теоретически такая возможность существует. На практике же на этом пути нас ждут коварные препятствия. Дело в том, что с момента создания восстанавливаемого файла карта свободного дискового пространства могла радикально измениться. Всякая операция удаления файлов высвобождает одну или несколько "дыр", хаотично перемешивающихся с "дырами" восстанавливаемого файла. Как этому противостоять? Сканируем MFT в поисках записей, помеченных как удаленные, но еще не затертых. Декодируем списки отрезков и вычеркиваем соответствующие им фрагменты из списка кандидатов на восстановление. Это существенно сужает круг поиска, хотя количество комбинаций, в которые можно собрать фрагментированный файл, по- прежнему остается велико. Но это не самое главное.