Удаление файлов

Права доступа к этому каталогу, отображаемые командой Is -1, будут отображаться так: drwxrwxrwt. Последний символ t как раз и указывает на наличие дополнительных прав (или ограничений) доступа. Но если задать права доступа к этому же каталогу в виде команды chmod 1776 /tmp, то отображаемые права доступа будут выглядеть уже так: drwxrwxrwT. Прописной символ Т указывает на противоречие в предоставленных правах: Sticky-бит установлен, но прав на исполнение (поиск в каталоге) для всех пользователей не предоставлено.

Универсальные операционные системы семейств UNIX и Windows* по умолчанию не предусматривают физического удаления файлов. Для гарантированного стирания файлов пользователям рекомендуется использовать специальные утилиты, которые именуются шредерами (от англ. shred - кромсать, резать). Утилита с таким названием имеется в штатной инсталляции современных операционных систем Linux. Она многократно (по умолчанию 25 раз) перезаписывает 128-байтный фрагмент inode и каждый из выделенных файлу блоков данных. При удалении данных записываемые комбинации бит меняются случайным образом, чтобы каждый элементарный домен на поверхности диска многократно перемагничивался противоположно направленными силовыми линиями магнитного поля. Синтаксис команды shred приведен в кратком справочнике по командам Linux в прил. 1.

Восстановление удаленных файлов в файловых системах Linux затрудняется рядом обстоятельств. Файл, как известно, состоит из трех частей: совокупности имен - «жестких» ссылок на индексный дескриптор одного индексного дескриптора, и определенного количества блоков. При создании файла системной функции creat передается символьное имя файла в файловой системе и устанавливаемые права доступа к нему. Система в соответствии с заложенным алгоритмом выделяет для этого имени свободный inode и необходимое количество свободных блоков.

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

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

Проверим, как очищается блок перед его заполнением новыми данными. Для этого воспользуемся специально написанной М.Э.Пономаревым утилитой fillfile, которая создает файл нужного размера, заполняет его выбранными символами и обозначает имя файла таким же символом. Пример: команда fill-file 600 b создает в текущем каталоге файл с именем b и объемом 600 байт, который содержит одни символы Ь. С помощью таких файлов с определенным наполнением весьма удобно наблюдать за выделением дискового пространства.

  1. Перейдем в каталог /home и командой f illf ile 3000 а создадим в нем файл размером 3000 байт (около ЪА размера логического блока) с именем «а», заполненный этими же буквами. Далее с помощью команды Is -И выведем список файлов текущего каталога, найдем в списке файл «а», удостоверимся в том, что его размер составляет 3000 байт, и прочитаем его inode. Допустим, его inode = 234567. С помощью редактора файловой системы lde -i 234567 /dev/hdc3 (в данном случае /dev/hdc3 - логический раздел Linux) выведем информацию, содержащуюся в этом индексном дескрипторе.

  2. Найдем в inode = 234567 прямую ссылку на единственный логический блок, отведенный файлу. Допустим, номер этого блока 0x000167А8. Заглянем с помощью команды lde -b 0xl67A8 /dev/hdc3 в этот блок и обнаружим, что он от начала до смещения 3000 байт (BB8h) заполнен символами «а».

  3. Удалим с помощью команды rm -f а созданный файл. Просматривая его inode и единственный адресуемый блок, убеждаемся, что никакого удаления не произошло. Два изменения, произошедшие в записях inode, указывают на неиспользуемый файл (NOT USERS в заголовке дескриптора и реальное время удаления файла).

  4. С помощью утилиты fillfile создадим файл "Ь" размером 300 байт и заполненный символами "Ь". Просматривая каталог /home с помощью команды Is -ali /home, мы можем увидеть этот файл и прочитать его индексный дескриптор. Не вызывает особого удивления, что система выделила новому файлу номер, ранее закрепленный за старым файлом. Как видно, inode после удаления файла сохраняют прежнюю информацию недолго.

  5. Выведя для осмотра inode файла "Ь", можно убедиться также в том, что ему отведен для размещения данных блок только что удаленного файла "а". Просмотр содержимого блока данных позволил установить различные результаты этой записи в различных версиях одной и той же операционной системы. Так, для систем с ядром Linux не выше 2.3 блок при перезаписи предварительно не очищается. 300 байт от начала блока занимают символы Ъ", затем следуют 212 нулевых байт (дополнение до длины сектора), а оставшаяся часть блока до размера 3000 байт заполнена символами "а". Как видно, системы старых версий не перезаписывают полностью логический блок, благодаря чему можно обнаружить «технологический мусор» от прежних файлов. Но в системах с ядром 2.4 и выше подобного «мусора» уже не наблюдается: системы очищает все логические блоки, выделяемые файлам.

Механизм журнализации, реализованный в файловых системах Linux, чрезвычайно затрудняет подобные наблюдения. Создание новых файлов, удаление существующих, использование освобожденных inode и логических блоков происходит иногда с заметной задержкой, и у исследователя может создаться впечатление, что никаких изменений в файловой системе не происходит. Подобные наблюдения можно производить, монтируя логические разделы EXT3FS как EXT2FS (т.е. без журнализации).

Теперь рассмотрим, что происходит с данными каталога при удалении файла. На листинге 17 изображен фрагмент логического блока с номером 0x00100203, содержащего каталог /home. В данном каталоге был удален файл с именем Рг Linux.doc.

0x00203000 01 04 08 00 ОС 00 01 02 : 2Е 00 00 00 02 00 00 00

0x00203010 20 00 02 02 2Е 2Е 00 00 : 65 0D 08 00 14 00 ОС 01 е...

0x00203020 50 72 5F 4С 69 бЕ 75 78 : 2Е 64 6F 63 66 0D 08 00 Pr_Linux.docf...

0x00203030 14 00 09 01 72 69 73 5F : 66 73 74 61 62 00 00 00 ris_fstab...

0x00203040 67 0D 08 00 14 00 0В 01 : 72 69 73 5F 66 64 69 73 g ris_fdis

0x00203050 6B 5F 6C 00 68 0D 08 00 : 14 00 0A 01 72 69 73 5F k_l.h ris_

0x00203060 6C 73 5F 6C 69 31 00 00 : 5A 07 08 00 18 00 0D 01 ls_lil..Z

0x00203070 72 69 73 5F 69 6E 6F 64 : 65 5F 62 69 6E 00 00 00 ris_inode_bin...

0x00203080 6A 0D 08 00 18 00 OD 01 : 72 69 73 5F 62 6C 6F 63 j ris_bloc

Листинг 17. Фрагмент дампа логического блока, содержащего каталог /home (до удаления файловой записи Pr_Linux.doc)

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

0x00203000 01 04 08 00 ОС 00 01 02 : 2Е 00 00 00 02 00 00 00

0x00203010 20 00 02 02 2Е 2Е 00 00 : 7D 0D 08 00 14 00 02 01 }

0x00203020 30 30 30 30 30 30 75 78 : 2Е 64 6F 63 66 0D 08 00 000000ux.docf...

0x00203030 14 00 09 01 72 69 73 5F : 66 73 74 61 62 00 00 00 ris_fstab...

0x00203040 67 0D 08 00 14 00 0В 01 : 72 69 73 5F 66 64 69 73 g ris_fdis

0x00203050 6B 5F 6C 00 68 0D 08 00 : 14 00 0A 01 72 69 73 5F k_l.h ris_

0x00203060 6C 73 5F 6C 69 31 00 00 : 5A 07 08 00 18 00 0D 01 ls_lil..Z

0x00203070 72 69 73 5F 69 6E 6F 64 : 65 5F 62 69 6E 00 00 00 ris_inode_bin...

0x00203080 6A 0D 08 00 18 00 0D 01 : 72 69 73 5F 62 6C 6F 63 j ris_bloc

Листинг 18. Фрагмент дампа логического блока, содержащего каталог /home (после удаления файловой записи Pr_Liimx.doc)

Рассмотрим содержание файловой записи до ее удаления (листинг 17). Разбор строки будем производить в обратном порядке, начиная от имени Pr_Linux.doc. Байт, стоящий левее (01h), указывает, что перед нами обычный файл, стоящий перед ним (OCh) определяет длину имени - 12 байт (в этом нетрудно убедиться). Два байта, стоящие левее (00 14h), также безошибочно определяют длину записи - 20 байт. Наконец, 4-байтная последовательность 00 08 0D 65h в десятичном представлении соответствует номеру inode = 527717, который был присвоен данному файлу при его создании или копировании.

Теперь посмотрим, что произошло с этой записью после логического удаления файла (листинг 18). Запись полностью не исчезла, от нее осталось окончание «ux.doc». Первая часть имени файла заменена нулями, индексный дескриптор поменялся на 00 08 0D 7Dh = 527741, но проверка показывает, что такой inode ни одному файлу еще не выделялся. Длина записи и длина имени файла не соответствуют друг другу. Можно сделать вывод, что мы стали свидетелями не замены записей одного файла другим, а его затирания произвольным кодом. Вероятно, если имя файла имеет какую-то значимость, по имеющемуся остатку его можно попытаться восстановить. Однако сказать, какому индексному дескриптору это имя соответствовало и, тем более, где располагаются блоки данных удаленного файла, невозможно.

Вывод списка удаленных файлов

Авторы одной из методик] рекомендуют при наличии логически удаленных файлов все же попытаться восстановить их по еще существующим (не перезаписанным) индексным дескрипторам. Они уверяют, что таким путем удается спасти до 80% информации.

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

Во-первых, в файл текущего каталога (назовем его lsdel.out) выводятся номера всех удаленных inode на данном логическом разделе:

lsdel I debugfs /dev/hdc3 > lsdel.out

Затем, предполагая, что список удаленных inode, сформированный командой lsdel, находится в файле lsdel.out, можно сделать так:

cut -cl-6 lsdel.out I grep "[0-9]" I tr -d " " > inodes

Новый файл с именем inodes содержит номера inode, подлежащих восстановлению, по одному в строке. Он используется в следующей команде:

sed 's/A.*$/stat <\0>/' inodes I debugfs /dev/hda5 > stats

результирующий файл stats содержит данные всех команд stat.

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

Для восстановления данных нужно найти их на устройстве и сделать так, чтобы они снова стали восприниматься операционной системе. Для этого существует два способа. Первый - изменить существующую файловую систему так, чтобы в удаленных inode был снят флаг удаления (число ссылок на индексный дескриптор и обнуление времени удаления файла), после чего довериться утилите автоматической проверки и восстановления файловой системы fsck. Другой способ, намного более безопасный, но медленный, - выяснить, где именно в разделе лежат данные, после чего записать их в новый файл в другой файловой системе.

Для реализации восстановления по первому варианту следует воспользоваться возможностями утилиты fsck (filesystem consistency check - проверка целостности файловой системы). Эта утилита способна в автоматическом режиме распознать следующие повреждения:

индексные дескрипторы, на которые нет ссылок в каталогах, либо содержащие большое число (более сотни) ссылок,

блоки данных, поименованные в индексных дескрипторах, но обозначенные в битовой карте блоков как свободные,

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

блоки данных, на которые имеются ссылки в нескольких inode,

>- каталоги, содержащие ссылки на индексные дескрипторы, значащиеся свободными.

При обнаружении файла, у которого нет имени (отсутствуют ссылки в каталогах) утилита помещает такой файл в каталог /lost+found, присваивая ему новое имя, совпадающее с именем индексного дескриптора.

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

Восстановление удаленных файлов

Практические рекомендации по восстановлению удаленных и поврежденных файлов на исследуемом логическом разделе Linux сводятся к следующему:

Логический раздел Linux с поврежденными или логически удаленными файлами не следует монтировать к дереву каталогов своей системы до ликвидации всех повреждений. В крайнем случае следует ограничиться монтированием «только для чтения».

Поиск удаленных файлов по их именам - занятие бесперспективное, поскольку имена файлов затираются в первую очередь. Искать следует удаленные индексные дескрипторы, т.е. inode с нулевым числом ссылок и установленной датой удаления. Inode сохраняют свою ценность до тех пор, пока содержат ссылки на номера блоков данных.

Каждый найденный удаленный inode следует модифицировать. Модификацию можно провести с помощью отладчика debugfs. Для этого следует последовательно выполнить следующие команды (более подробное описание этих команд содержится в приложении):

debugfs

Входим в командную среду отладчика.

open -w /dev/hdc3

Открываем исследуемый раздел в режиме чтения/записи. lsdel

Выводим на экран список удаленных inode.

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

дальнейшую работу с ним.

stat <inode>

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

dump <inode> out_file

Сохраняем содержимое индексного дескриптора в файл.

ncheck inode_number

Пытаемся найти имя файла по его индексному дескриптору.

seti <inode>

Бит, соответствующий данному inode в битовой карте индексных дескрипторов, устанавливаем в «1». Тем самым указываем системе, что индексный дескриптор вновь занят.

mi <inode>

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

close

Закрываем логический раздел. quit

Выходим из отладчика.

Если удаленные индексные дескрипторы не были найдены, это не означает, что на данном логическом разделе нечего искать. Индексные дескрипторы и логические блоки, как правило, адресуются независимо друг от друга, a inode удаленных файлов затираются новыми данными в первую очередь. Поэтому следующим этапом будет являться поиск свободных блоков данных, содержащих утерянную информацию. Однако никаких утилит, позволяющих искать ранее освобожденные блоки данных, не существует. Это можно делать только после визуального просмотра битовой карты блоков, выявляя в ней байты, отличные от FF. Затем, последовательно копируя свободные блоки из нужного диапазона номеров (принадлежащих каталогу, из которого предположительно производилось удаление), можно создать файл, который затем можно посмотреть (он наверняка будет состоять из склеенных фрагментов различных файлов). Есть альтернатива - запустить одну из известных утилит контекстного поиска. Эти утилиты очень хорошо работают с англоязычным текстом, но с чтением кириллицы будут проблемы, особенно в кодировке UNICODE.

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

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