LINUX.undelete

второе рождение утерянных данных\\ восстановление удаленных файлов под LINUX'ом

крис касперски ака мыщъх, no-email

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

Почему гибнут файлы? Карма у них такая. А если серьезно, то существуют тысячи причин — от вирусов до ошибок оператора. Основным способом общения с пользователям в LINUX остается командная строка, легко удаляющая все без разбора. Стоит только отдать слегка неверный приказ и… куда это подевались все мои файлы?

В MS-DOS существовала замечательная утилита undelete, регулярно вытаскивающая из небытия многие мегабайты данных. В популярной оболочке MidnightCommander так же имеется похожая команда. К сожалению, она срабатывает не всегда (или обнаруживает не все файлы) и тогда приходится прибегать к ручному восстановлению. Не пугайтесь! Это намного проще, чем может показаться на неискушенный взгляд!

Рисунок 1 автоматическое восстановление удаленных файлов средствами MidnightCommander'a

В противовес Windows NT, поддерживающей только NTFS и FAT, операционные системы семейства LINUX предлагают довольно широкий ассортимент файловых систем на любой вкус: ext2fs, ext3fs, reiserfs, xfs, jfs и т. д. При внешней схожести «потребительских» возможностях, их «физическое» устройство сильно неодинаково и каждая из них требует своей техники восстановления. В рамках одной-единственной статьи поднять эту глыбу нереально, поэтому мы решили остановится на ext2fs/ext3fs как на самой популярной файловой системе, устанавливаемой по умолчанию большинством дистрибьютивов.

Рисунок 2 восстановление удаленных файлов с ext2fs раздела с помощью Windows-утилиты R-Studio — есть файлы, но нету имен

Файловые системы ext2fs и ext3fs очень похожи друг на друга. Фактически, ext3fs это ext2fs с поддержкой журналирования. Отличия базовых структур минимальны, но вот процесс удаления файлов в них протекает по разному. В ext2fs при удалении файла теряется его имя (хотя и не затирается до поры до времени), поэтому автоматическое восстановление имен в ней невозможно, зато само содержимое файла остается нетронутым. Ext3fs поступает с точностью до наоборот — сохраняет имя файла, но частично уничтожает схему его размещения на диске, в результате чего техника восстановления колоссально усложняется. К тому же ext3fs намного менее производительна, так что для домашних компьютеров лучше всего использовать ext2fs. Как она устроена?

Рисунок 3 восстановление удаленных файлов с ext3fs раздела — есть имена, но нету файлов (поле размера равно нулю, что означает отсутствие данных)

В начале раздела расположен boot-сектор, за ним, по смещению 1024 байта находится супер-блок (super-block), отвечающий за хранение ключевой информации о структуре файловой системы (в ext2fs/ext3fs он играет точно такую же роль, что и boot-сектор в FAT и NTFS). В нем много всяких полей, но нас будет интересовать лишь одно: s_log_block_size. Это 32-разрядное поле, расположенное по смещению 18h байт от начала супер-блока. Как и следует из его названия, оно определяет размер одного блока (block) или, в терминологии MS-DOS/Windows, кластера. Размер задается в виде показателя степени на которую сдвигается размер одного сектора, равный 200h (512) байт. В переводе на программистский язык это звучит так:block_size = 200h « s_log_block_size (байт). Например, если s_log_block_size равен нулю, размер одного блока будет 400h байт, то есть два сектора.

смещение размер описание

——- ——- ———–

0 1 bootrecord; загрузочный сектор

blockgroup 0 –; группа блоков 0

(1024 bytes) 1 superblock; суперблок

2 1 groupdescriptors; дескриптор группы

3 1 blockbitmap; карта свободных блоков

4 1 inodebitmap; карта свободных inode

5 214 inodetable; массив inode (сведения о файлах)

219 7974 datablocks; блоки данных (файлы, директории)

blockgroup 1 –; группа блоков 1

8193 1 superblock backup; копиясуперблока

8194 1 group descriptors backup ; копиядескрпиорагруппы

8195 1 blockbitmap; карта свободных блоков

8196 1 inodebitmap; карта свободных inode

8197 214 inodetable; массив inode (сведения о файлах)

8408 7974 datablocks; блоки данных (файлы, директории)

blockgroup 2 –; группа блоков 2

16385 1 blockbitmap; карта свободных блоков

16386 1 inodebitmap; карта свободных inode

16387 214 inodetable; массив inode (сведения о файлах)

16601 3879 datablocks; блоки данных (файлы, директории)

Листинг 1 структура дискового тома, размеченного под ext2fs

За супер-блоком идут так называемые дескрипторы групп (groupdescriptors), и карты свободного пространства, в просторечии — битмапы (blockbitmap/inodebitmap), которые нам малоинтересны, а вот примыкающую к ним indoe-таблицу, мы рассмотрим поподробнее, поскольку без знания ее структуры ручное восстановление данных просто немыслимо.

Таблица представляет собой массив записей типа inode, каждая из которых хранит всю информацию об одном файле: тип (обычный файл, директория, символьная ссылка и т. д.), схема размещения на диске, логический/физический размер, дата/время создания/ модификации/последнего доступа/удаления, количество ссылок на файл и правда доступа (см. листинг 2).

смещение размер описание

——- ——- ———–

0 2 i_mode; формат представления описание

2 2 i_uid; uid пользователя

4 4 i_size; размер файла в байтах

8 4 i_atime; время последнего доступа к файлу

12 4 i_ctime; время создания файла

16 4 i_mtime; время модификации файла

20 4 i_dtime; время удаления файла

24 2 i_gid; gid группы

26 2 i_links_count; количество ссылок на файл (0 – файл удален)

28 4 i_blocks; количество блоков, принадлежащих файлу

32 4 i_flags; разные флаги

36 4 i_osd1; OS dependant value

40 12 x 4 i_block; 12 DIRECTBLOCKS (ссылки на первые 12 блоков файла)

88 4 i_iblock; 1x INDIRECT BLOCK

92 4 i_2iblock; 2x INDIRECT BLOCK

96 4 i_3iblock; 3x INDIRECT BLOCK

100 4 i_generation; поколение файла (используется NFS)

104 4 i_file_acl; внешниеатрибуты

108 4 i_dir_acl; higer size

112 4 i_faddr; положение последнего фрагмента

116 12 i_osd2; OS dependant structure

Листинг 2 формат представления inode

Схема размещения файла на диске организована намного проще, чем в NTFS и FAT. Каждый файл занимает один или несколько блоков. Даже если блок занят только частично, он выделяется файлу целиком (в остальных файловых системах, таких например, как UFS, предусмотрена возможность выделения файлу только части блока, а в NTFS и ReiserFS мелкие файлы могут храниться непосредственно в самой inode, что существенно уменьшает фрагментацию и увеличивает производительность), но вернемся к ext2fs/ext3fs.

Указатели на 12 первых блоков, занимаемых файлом, хранятся прямо в inod'е, а точнее — в массиве DIRECT BLOCKS, так же называемом массивом непосредственных блоков. Каждый элемент массива представляет собой 32-битный номер блока. Поскольку, типичный размер блока составляет ~4 Кбайт (конкретное значение зависит от емкости диска и опций форматирования), то массив непосредственных блоков «переваривает» файлы до 4 12 == 48 Кбайт. Если длина файла превышает эту величину (а у подавляющего большинства файлов она превышает), приходится прибегать к блокам косвенной адресации. (или по-английски INDIRECT BLOCK). Файловые системы ext2fs/ext3fs поддерживают три уровня вложенности. Первый блок косвенной адресации (1x INDIRECT BLOCK или просто INDIRECT BLOCK) хранит уже не указатели на блоки занятые файлов, а указатели на дополнительные непосредственные блоки и может адресовать до BLOCK_SIZE/sizeof(DWORD) * BLOCK_SIZE = 4096/4 *4 Мбайт данных. Что ж! Полвека назад это была очень большая величина, но сейчас ею никого не удивишь и большинству из нас требуется обрабатывать намного более «толстые» файлы. На этот случай предусмотрен блок двойной косвенной адресации (2x INDIRECT BLOCK) или DOUBLE INDIRECT BLOCK, хранящий указатели на косвенные блоки, которые в свою очередь хранят ссылки на непосредственные блоки, что позволяет адресовать (BLOCK_SIZE/sizeof(DWORD))2* BLOCK_SIZE =4096/4  4096 == 4 Гбайт данных. Это уже внушительная величина, при которой размер файла занимает всю разрядную сетку 32-битной переменной. Большинство приложений ограничивают верхний размер обрабатываемых файлов 2 или 4 Гбайтами, тем не менее, файловая система способна хранить файлы намного большего размера. Это осуществляется с помощью трижды косвенного блока (3x INDIRECT BLOCK или TRIPLE INDIRECT BLOCK), указывающего на дважды косвенные блоки, каждый из которых указывает на косвенные блоки, ссылающиеся на блоки непосредственной адресации. Так что возможности ext2fs/ext3fs намного превышают емкости жестких дисков настоящего и будущего.

По сравнению с FAT, такая схема хранения информации об размещении, является намного более устойчивой к разрушениям. Она как бы «размазывается» по всему диску и уничтожить все блоки адресации можно разве что динамитом. К тому же, номера блоков хранятся в прямом виде «как есть», а это значит, что для каждого блока файла мы может быстро найти соответствующий ему косвенный блок, даже если inod'а полностью разрушена.

Рисунок 4 описание порядка размещения файла на диске, иерархия непосредственных и косвенных блоков

Имена файлов хранятся в директориях и в inode их нет. Директории представляют собой обычные файлы… ну, хорошо, не совсем обычные, а специальные служебные файлы, содержащие массив записей типа:

смещение размер описание

——- ——- ———–

0 4 inode; ссылка на inod'у

4 2 rec_len; длина данной записи

6 1 name_len; длина имени файла

7 1 file_type; типфайла

8 … name; имя файла

Листинг 3 формат представления массива директорий

Поле inode содержит порядковый номер inode, которому соответствует данное имя файла; поле rec_len задает длину текущей записи, а name_len – длину имени файла. Само имя хранится в ASCII виде сразу после длины.

При удалении файла в системе происходит множество изменений. Опишем лишь самые важные из них. Прежде всего, система определяет номер принадлежащей ему inod'ы. Затем, счетчик ссылок (i_links_count) уменьшается на единицу и если при этом он не обращается в нуль, то никакого удаления не происходит, поскольку у файла еще остались ссылки. Нас этот случай не интересует. Если же ссылок больше нет, то все блоки, ранее принадлежащие файлу, в карте свободного пространства (blockbitmap) помечаются как неиспользуемые, обновляется поле времени удаления (i_dtime), а сама inod'а освобождается, что осуществляется путем модификации inodebitmap. В ext3fs в дополнении к этому обнуляются указатели на 12 блоков непосредственной адресации и 3 блока косвенной адресации, в результате чего схема размещения файла оказывается частично утраченной.

Файл директорий так же затрагивают перемены. ext2fs обнуляет поле inode и увеличивает размер предшествующей записи (поле ren_len) на величину удаляемой. Предшествующая запись как бы «поглощает» последующую, а связь между именем файла и соответствующей ему inode необратимо теряется. То есть, мы можем восстановить файл, но бессильны вернуть ему прежнее имя. Правда, можно получить список всех удаленных имен, и тем или иным способом попробовать угадать какое из них «наше». При восстановлении небольшого количества файлов это срабатывает, но если удален весь корневой каталог, то ситуация ласты. А вот ext3fs оставляет поле inode неизменным, благодаря чему задача восстановления имени становится тривиальной. Проблема в том, что на ext3fs утрачивается схема размещения файла, что чрезвычайно затрудняет восстановление его содержимого.

Короче, нет в мире совершенства!

Рисунок 5 один шаг отдаляет эти четыре файла от небытия, но они не умрут! после удаления их еще будет можно восстановить!

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

Первым делом размонтируете (unmount) дисковый раздел или перемонтируете его «только на чтение». Лечение активных разделов обычно заканчивается очень печально. Если восстанавливаемые файлы находятся на системном разделе, в этом случае можно прибегнуть к LiveCD. Лучше всего использовать KNOPPIX. Он поддерживает большое количество оборудования, не требователен к ресурсам (достаточно всего 128 Мбайт памяти) и содержит все необходимые утилиты для восстановления. Опытные пользователи могут сформировать загрузочный CD или даже дискету самостоятельно.

Редактируя диск напрямую, его легко испортить. Одно неверное движение руки — и гигабайты данных обращаются в прах. Поэтому, при наличии свободного места, рекомендуется создать копию раздела и все дальнейшие опыты проводить уже над ней. В мире Windows для этой цели требуется специальные утилиты (например, NortonGhost), которые, кстати говоря, стоят нехилых денег, но LINUX – совсем другое дело. Здесь все необходимое находится под рукой. Копию раздела проще всего создать командой cp /dev/sdb1 dump, где sdb1 – имя устройства, а dump — имя файла-дампа.

В графических оболочках типа KDE имя устройства можно узнать просто щелкнув по иконке жесткого диска (хотя на самом деле это не диск, а раздел) и открыв вкладку «свойства»:

Рисунок 6 определение наименования восстанавливаемого раздела через графический интерфейс

Файл-дамп можно разместить на любом свободном разделе или даже перегнать на соседнюю машину по сети. Все дисковые утилиты (lde, debugsf, fschk) не заметят подвоха и будут работать с ним как с «настоящим» разделом. При желании его даже можно смонтировать как файловую систему: mount dump mount_point –o loop, чтобы убедиться, что восстановление прошло успешно. Команда cp dump /dev/sdb1 копирует восстановленный дамп обратно в раздел.

Чаще всего линуксоиды редактируют диски при помощи lde(расшифровывается как LinuxDiskEditor), представляющий собой профессиональный редактор консольного типа, переваривающий ext2fs, minix, xiafs и отчасти FAT. Бесплатен, распространяется в исходных текстах (http://lde.sourceforge.net/) и работает практически под любой UNIX-совместимой операционной системой.

Рисунок 7 внешний вид редактора lde

Как с ним работать? Сначала открываем восстанавливаемый раздел или файл-дамп: «lde /dev/sdb1» или «lde dump» соответственно. lde самостоятельно определяет тип файловой системы и после нажатия клавиши (какой не критично), переходит в режим отображения супер-блока. Теперь клавиша <I> переводит нас в режим inode, а <B> в блочный режим (block-mode). Жмем <I> и редактор переходит к первой inod'e, принадлежащей корневому каталогу. Для перехода к следующей inod'е служит клавиша <Page Dowd>, а <Page Up>, соответственно, к предыдущей. Таким образом, можно пролистать все inod'ы. Как отличить какие из них принадлежат удаленным файлам? В этом нам поможет поле LINKS. Если файл удален оно равно нулю, и тогда «DELETIONTIME» содержит время последнего удаления (мы же ведь помним когда удаляли файл?). Хорошая идея — проскандировать таблицу inod'е и отсортировать файлы по дате удаления. Файлы, удаленные последними, окажутся в конце списка. Как вариант, можно искать дату удаления контекстным поиском.

Рисунок 8 запуск редактора lde

Обнаружив подходящую inod'у, перемещаем курсор к первому блоку в списке DIRECT BLOCKS (где он и находится по умолчанию) и жмем <F2>. В появившемся меню выбираем пункт «Block mode, viewingblockundercursor», (которому, кстати говоря, соответствует горячая клавиша <Shift-B>). Редактор перемещает нас на первый блок удаленного файла. Просматривая его содержимое в hex-режиме, пытаемся определить «на глаз», похож ли он на наш файл или нет? Для возврата к просмотру списка inod'ы, можно нажать <I>, а для восстановления файла: <Shift-R>, затем еще раз <R> и имя файла-приемника. Все! Файл восстановлен! На этом нашу миссию можно считать законченной и пить пиво, наслаждаясь проделанной работой.

Рисунок 9 просмотр содержимого inod'е

В некоторых случаях предпочтительнее восстанавливать файлы по их содержимому. Предположим, удаленный файл содержал строку «hello, world». Нажимаем <f> (search), азатем <A> (Search all block). Если забыть нажать <A>, то редактор будет пропускать блоки, принадлежащие удаленным файлам при поиске, что явно не входит в наши планы. Как вариант, можно запустить редактор с ключом «–all».

Рисунок 10 восстановление файла по содержимому

Теперь нажимаем <B> для перевода lde в block-mode, давим </> и вводим ASCII-строку для поиска. Редактор, пошуршав некоторое время жестким диском, находит нужный блок. Смотрим — действительно или это тот блок, который нам нужен или произошло недоразумение. Ложное срабатывание в смысле. Если блок действительно наш, ждем <Ctrl-R> и редактор сообщает номер inod'ы, которой этот блок принадлежит (он отображается внизу экрана, не спутайте его с номером последней просмотренной inod'у, отображаемой вверху). Клавиша <I> переводит нас в режим inode, после чего остается нажать <#> и ввести номер inod'ы, которую мы хотим просмотреть. Если дата удаления выгладит вполне правдоподобно, нажимаем <Shift-R>/<R> и сбрасываем файла на диск.

Все это работает только с ext2fs, и не пригодно для ext3fs, поскольку, как уже говорилась, она затирает схему размещения файлов на диске и данные приходится восстанавливать буквально по кусочкам. Это довольно сложная работа и лучше поручить ее профессионалам. Из личного опыта мог порекомендовать две фирмы: Ростовскую ACE-Labs (www.acelab.ru) и Киевский ЕПОС (http://www.epos.kiev.ua/). Впрочем, они наверняка потребуют денег…

Ручное восстановление файлов под ext2fs – совсем несложное дело и этому может научиться любой желающий. Не стоит доверять никаким автоматизированным утилитам (таким, например, как R-Studio), поскольку очень часто они только добивают файл без всякой надежды на его излечение.

Конечно, на остальных файловых системах ext3fs, ReiserFS описываемая техника скидывает ласты, но… Что же еще можно ждать от простой журнальной статьи. Восстановление данных — это искусство, которому учатся годами и если вы захотите узнать больше — залезайте на мой ftp-сервер nezumi.org.ru. Здесь можно найти уйму интересных материалов по восстановлению. А еще у меня запланирована книжка, которая так и называется «техника восстановления данных под Windows и UNIX» — ищите ее на прилавках магазинах ну или в парнокопытных. Парнокопытные —это рулез!

  1. Design and Implementation of the Second Extended File system:
    1. подробное описание файловой системы ext2fs от самих разработчиков проекта. на английском языке. http:e2fsprogs.sourceforge.net/ext2intro.html; - Linux Ext2fs Undeletion mini-HOWTO: - краткая, но доходчивая инструкция по восстановлению удаленных файлов на ext2fs разделах. на английском языке. http:www.praeclarus.demon.co.uk/tech/e2-undel/howto.txt;
  2. Ext2fs Undeletion of Directory Structures mini-HOWTO:
    1. краткое руководство по восстановлению удаленных директорий на ext2fs разделах. на английском языке: http:www.faqs.org/docs/Linux-mini/Ext2fs-Undeletion-Dir-Struct.html; - HOWTO-undelete: - еще одно руководство по восстановлению удаленных файлов на ext2fs разделах с помощью редактора lde. на английском языке. http:lde.sourceforge.net/UNERASE.txt;

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

Чтобы чего-нибудь не испортить, никогда не редактируйте диск напрямую. Работайте с его копией! Копию можно создать командой cp /dev/sdb1 my_dump, где sdb1 – имя устройства, а my_dump — имя файла-дампа. Файл-дамп можно разместить на любом свободном разделе или перегнать на другую машину по сети. Все дисковые утилиты (lde, debugsf, fschk) не заметят подвоха и будут работать с ним как с «настоящим» разделом. При необходимости его даже можно смонтировать на файловую систему: mount my_dump mount_point –o loop, чтобы убедиться, что восстановление прошло успешно. Команда cp my_dump /dev/sdb1 копирует восстановленный файл-дамп обратно в раздел, хотя делать это совсем необязательно. Проще (и безопаснее) копировать только восстанавливаемые файлы.