відновлення NTFS – undelete своїми руками

продовжуючи говорити про NTFS, сьогодні ми розглянемо техніку відновлення вилучених файлів за допомогою найпростішого дискового редактора (типу Disk Probe) і утиліти chkdsk, а так само дамо кілька порад із приводу створення власного інструментарію, що може бути запрограмований на будь-якій мові, що має доступ до win32 API.

Надійність NTFS – це одне, а помилково вилучені файли – зовсім інше. Файлова система, навіть така потужна як NTFS, неспроможна захистити користувача від себе самого. Але от передбачити "відкіт" останніх виконаних дій вона цілком може (тим більше, що транзакції й журналирование в NTFS уже реалізовані). До досконалості залишається всього лише крок. На жаль! Microsoft тупцює на місці, всі ніяк не вирішуючись його зробити (зачепив, залишених для майбутніх версій?) "Захист" від ненавмисного видалення реалізована винятково на интерфейсном рівні, а це не тільки незручно, але й ненадійно.

Добре, якщо вилучений файл зберігся в "Кошику", але що робити, якщо там його немає? Ця стаття розповідає про методи ручного відновлення файлів, у тому числі й з відсутнім файловим записом, коли "небіжчика" доводиться збирати по кластерах.

IRP_MJ_SET_INFORMATION/ FILE_DISPOSITION_INFORMATION – це пакет, що посилає драйверу при видаленні файлу (майте це через при дизасемблюванні). Щоб уміти відновлювати вилучені файли, необхідно чітко представляти, що відбувається в процесі видалення файлу з NTFS-розділу, а відбувається при цьому наступне:

НЕ нашли? Не то? Что вы ищете?

q коректується файл /$MFT:$BITMAP, кожний біт якого визначає "зайнятість" відповідного файлового запису (FILE Record) в MFT ("0" – запис не використається);

q коректується файл /$BITMAP, кожний біт якого визначає "зайнятість" відповідного кластера ("0" – кластер не використається);

q файлові записи, що відповідають файлу, позначаються як вилучені (поле FLAG, що перебуває по зсуві 16h від початку FILE Record скидається в нуль);

q посилання на файл віддаляються із двійкового дерева індексів (технічні подробиці цього животрепетного процесу тут опускаються, оскільки відновити таблицю індексів вручну зможе тільки гуру, та й навіщо? в NTFS індекси відіграють допоміжну роль – простіше переіндексувати директорію заново, чим відновлювати збалансоване B*tree дерево);

q обновляється атрибут $STANDART_INFORMATION каталогу, що хранили видаляє файл, що (час останнього доступу й т. д.);

q в /$LogFile обновляється Sequence Number (зміни, що відбуваються в журналі транзакцій ми не розглядаємо);

q Update Sequence Number наступних файлових записів збільшується на одиницю: сам віддаля файл, що, що текет каталог, /$MAF, /$MFT:$BITMAP, /$BITMAP, /$BOOT, /$TRACKING. LOG

Каталоги віддаляються практично точно так само, як і файли (з погляду файлової системи, каталог теж файл, тільки особливий – із двійковим B*tree деревом індексів усередині).

Ні в тім, ні в іншому випадку фізичного видалення файлу не відбувається й він може бути легко відновлений доти, поки не буде затерта приналежна йому FILE Record, що зберігає резидентне тіло файлу або список відрізків (run-list) нерезидентного вмісту. Втрата FILE Record дуже неприємна, оскільки в цьому випадку файл прийде збирати по шматочках руками й чим сильніше він фрагментирован – тим складніше це завдання. У відмінності від FAT, NTFS не затирає першого символу ім'ям файлу, чим значно спрощує своє відновлення.

Утиліти, що відновлюють вилучені файли, не входить у комплект штатної поставки Windows NT і їх доводиться здобувати окремо (але ж в MS-DOS така утиліта була!). Побоюючись угробити файлову систему остаточно, більшість із них уникає прямого запису на диск – замість цього вам пропонується вважати вилучений файл і переписати його в інше місце (але тільки на сам відновлюваний розділ). Не занадто-те вдале рішення! А якщо на інших дисках вільного місця немає або відновлюваний диск має всього лише один логічний розділ? Припустимо, вам необхідно відновити базу даних у трохи гігабайт. Можна, звичайно, підключити другий вінчестер, скопіювати її туди, а потім назад, але скільки ж це займе часу, не говорячи вже про те, що сервер краще не виключати, а гарячу заміну підтримують далеко не всі жорсткі диски! Інший недолік подібних утиліт – занадто повільна робота. Замість того, щоб знайти один-єдиний файл, ім'я якого нам відомо, вони проводять повномасштабні маневри, скануючи весь розділ цілком. При роботі з більшими дисками на це йде від одного до декількох годин впустую витраченого часу.

З іншого боку, утиліти, що вносять зміни безпосередньо в саму NTFS, ризикують серйозно ушкодити дисковий тім, після чого йому не допоможуть навіть професіонали. Дійсні хакеры [адміністратори] не довірять ніякому коду, крім свого власного, особливо, якщо вихідні тексти недоступні, а документація мрячна й двозначна. Різні версії NTFS відрізняються друг від друга. Останні радикальні зміни відбулися в Windows XP (NTFS версії 3.1) – масив послідовності відновлення (Update Sequence Number-n-Array) перемістився на шість байтів уперед, а його місце було віддано під вирівнювання й поле номера поточного файлового запису (Number of this MFT Record). утиліта, Що Відновлює, повинна не тільки підтримувати вашу версію файлової системи, але й безпомилково відрізняти її від всіх інших (при відновленні Windows 2000 до Windows XP відновлення файлової системи не відбувається аж до переформатування диска). Спробуй, потім поясни начальству "це не я, це вона все зіпсувала!".

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

Малюнок 1 утиліта GetDataBack за відновленням вилучених файлів

Почнемо з найпростішого. Файл тільки що вилучений і приналежна йому FILE Record ще не затерта. Як знайти його на диску? Існує два способи – "теоретичний" і "практичний". Теоретичний винятково надійний, але вимагає додаткових телодвижений, яких можна уникнути, прийнявши ряд практичних допущень.

Теоретично: витягаємо з boot-сектора покажчик на MFT, витягаємо з її перший запис (вона описує $MFT), знаходимо атрибут $DATA (80h), декодируем список відрізків (data runs) і послідовно читаємо всі записи в MFT, аналізуючи вміст атрибута $FILE_NAME (30h) – ім'я файлу (до речі, таких атрибутів у файлу може бути трохи). Цей же атрибут зберігає посилання на материнську директорію – якщо кілька однойменних файлів вилучені з різних директорій, ми повинні розібратися який з них наш.

Практично: у дев'ятьох з десяти випадків $MFT файл не фрагментирован і розташовується практично на самому початку диска. Імена файлів зберігаються по зсуві EAh від початку сектора, на початку якого розташована сигнатура "FILE*" ("FILE0" – в NTFS 3.1). Тому, ми просто запускаємо будь-який дисковий редактор (наприклад, Disk Probe з комплекту Support Tools від Microsoft), уводимо ім'я відновлюваного файлу в уникоде й говоримо шукати його по зсуві EAh (в NTFS 3.1 – F0h) від початку сектора.

Коли ж шукане входження буде знайдено, дивимося: чи перебуває на початку сектора сигнатура "FILE*"/"FILE0" і якщо немає – продовжуємо пошук. Двухбайтовое поле по зсуві 16h від початку сектора містить прапори запису: 00h – запис не використається або був вилучений, 01h – запис використається й описує каталог, 02h – запис використається й описує директорію. Зустрічаються й інші значення (04h, 08h…що вони позначають – невідомо. може бути, ви, читач, зможете пролити світло на це питання?).

Малюнок 2 ручне відновлення файлу за допомогою Disk Probe

Виправляємо 00h на 01h, записуємо зміни й…Нічого не виходить?! А чого ви хотіли! Адже крім цього необхідно ще: а) повідомити файлу /$MFT:$BITMAP, що даний MFT-запис знову використається; б) відібрати у файлу /$BITMAP номера кластерів, що належать відновлюваному файлу; с) перешикувати двійкове дерево індексів, що зберігає вміст каталогу. Перші два пункти не проблема, але от над останнім прийде попыхтеть. Або…просто запустити chkdsk із ключем /F. Він самостійно знайде "загублений" файл і внесе всі необхідні зміни у файлову систему. Від нас буде потрібно тільки встановити прапор по зсуві 16h в одиницю, а інше – його турбота. Після цих нехитрих маніпуляцій файл виявляється у своєму рідному каталозі. Відновлений!

C:\chkdsk D: /F

Тип файлової системи: NTFS.

Перевірка файлів завершена.

Перевірка індексів завершена.

Відновлення загублених файлів.

Відновлення загубленого файлу test. txt у файлі каталогу 5

Заміна неправильного ідентифікатора безпеки для файлу 29

Перевірка дескрипторів безпеки завершена.

Виправлення помилок в атрибуті BITMAP основної таблиці файлів.

Windows зробила зміни у файловій системі.

1068290 КБ усього на диску.

20 КБ в 2 файлах.

4 КБ в 9 індексах.

0 КБ в ушкоджених секторах.

7894 КБ використається системою.

7392 КБ зайнято під файл журналу.

1060372 КБ вільно на диску.

Розмір кластера: 2048 байт.

Усього кластерів на диску: 534145.

530186 кластерів на диску.

Листинг 2 відновлення вилученого файлу за допомогою chkdsk

Розглянемо більше складний випадок відновлення, коли файловий запис уже затертий. Якщо вилучений файл був резидентним (тобто  зберігав своє тіло в MFT), то відновлювати вже нема чого. Навіть якщо на його місці створений нерезидентний файл (а файловий запис нерезидентного файлу закінчується там, де починається резидентне тіло), операційна система дбайливо заповнить "хвіст, що залишився," нулями й для відновлення оригінального вмісту прийде вдатися до дорогого встаткування, що читає поверхню "млинців" жорсткого диска на фізичному рівні.

З нерезидентними файлами, що зберігають своє тіло поза MFT, ситуація обстоит не так жалюгідно, хоча проблем теж вистачає. Порядок розміщення файлу на диску зберігається в run-list'e усередині файлового запису в MFT (тепер уже затертої) і тому, можливий лише контекстний пошук по вмісту. Запускаем диск-редактор, уводимо послідовність, що свідомо втримується у вилученому файлі, але не зустрічається у всіх іншим і натискаємо "search". Для прискорення пошуку можна шукати тільки у вільному дисковому просторі (за це відповідає файл /$BITMAP). Відомі мені редактори зневажають цією можливістю (а зрячи!), однак, утиліту "просунутого" пошуку нескладно написати й самостійно.

Нефрагментированные файли відновлюються елементарно. Просто виділяємо групу секторів і записуємо її на диск (тільки в жодному разі не на сам відновлюваний тім!). Єдина проблема – як визначити оригінальну довжину? Деякі типи файлів допускають присутність "сміття" у своєму хвості (і тоді нам залишається додержуватися правила "краще перебрати, чим недобрати"), а деякі немає! Якщо кінець не вдається визначити візуально (наприклад, pdf-файли завершуються сигнатурою "%%EOF"), проаналізуйте заголовок файлу – серед іншої корисної інформації звичайно там є присутнім і його розміром. Отут все залежить від структури конкретного файлу й універсальних рекомендацій дати неможливо.

Если файл фрагментирован – справа набагато гірше. Ситуація практично безнадійна, оскільки, щоб зібрати розрізнені ланцюжки кластерів воєдино, необхідно добре знати вміст вилученого файлу. У цьому змісті, NTFS відновлюється набагато гірше, ніж FAT. Послідовність фрагментів файлу, що зберігається в File Allocation Table у вигляді односпрямованого списку дуже живуча. Якщо список не ушкоджений, досить лише знайти його перший елемент (а зробити це простіше простого, оскільки він буде вказувати на заголовок файлу із цілком передбачуваним умістом). Навіть якщо список "розрубити" на кілька частин, вони продовжувати жити власним життям і нам залишиться лише підібрати комбінацію як їх правильно склеїти воєдино. Список гине лише при повнім затиранні FTA'а, що трапляється прямо скажемо не часто. В NTFS же порядок фрагментів файлу зберігається в крихітних списках відрізків і їхня загибель – звичайна справа, після чого ми залишається один на один з мільйоном безладно розкиданих кластерів. З текстовими файлами ще куди б те не йшло, але що робити, якщо це електронна таблиця, графічне зображення або архів який? Без знання стратегії виділення дискового простору тут нікуди. Порядок, у якому драйвер файлової системи знаходить підходящі вільні фрагменти, не визначений і варіюється залежно від безлічі обставин, однак, деякі закономірності в ньому все-таки присутні.

Аналізуючи списки відрізків сильно фрагментированных дисків мені вдалося встановити наступне: спочатку заповнюються самі більші "діри", рухаючись від кінця MFT-зони до кінця диска. Потім, драйвер файлової системи вертається назад і починає заповнювати діри поменше й так триває доти, поки файл не виявляється на диску цілком. Останніми заповнюються діри розміром в один кластер. Переглядаючи карту диска, представлену файлом /$BITMAP, ми можемо в точності відновити порядок розміщення фрагментів вилученого файлу, нашвидку зібравши їх воєдино. У всякому разі, теоретично. Практично ж на цьому шляху нас чекають підступні перешкоди. З моменту створення відновлюваного файлу карта вільного дискового простору могла капітально перетворити. Усяке видалення файлів вивільняє одну або кілька дір, що хаотично перемішуються з дірами відновлюваного файлу, спотворюючи картину. Як цьому протистояти? Скануємо MFT у пошуках записів, позначених як вилучені, але ще не затертих. Декодируем run-list'ы й викреслюємо відповідні їм фрагменти зі списку кандидатів на відновлення. Це істотно звужує коло пошуку, хоча кількість комбінацій у які можна зібрати фрагментированный файл як і раніше залишається велико. Але це ще що...

Саме "цікаве" починається, коли на диск одночасно записуються кілька файлів (наприклад, скачиваемых ReGet'ом з Інтернету) або файл поступово збільшує свій розмір (набираєте дипломну роботу в Word'е?), а в цей час на диск записуються інші файли. Коли до існуючого файлу дописується малюсінька порція даних, файлова система знаходить найменшу діру, що потім випливає найменшу діру й т. д., аж до тих пор поки маленькі діри не вичерпаються й тоді наступає черга дір побільше. Як наслідок, файл виходить сильно фрагментированным – це раз. Файл заповнюється не від більших дір до менших, а навпаки (тобто  відбувається інверсія стратегії розміщення) – це два. Маленькі фрагменти одного файлу перемішуються з маленькими фрагментами інших файлів – це три.

Гірше всього піддаються відновленню документи, створені в MS Office і от чому: додаток створює велика кількість резервних копій файлу, що редагує, як у поточному каталозі, так і в каталозі %TEMP%. От і розберися який фрагмент якому файлу належить!

Пгаю всього відновлюватися ZIP-архіви. Для цього вам навіть не буде потрібно запускати дисковий редактор. Відкрийте тимчасовий файл на запис, зробіть seek на розмір вільного дискового простору, закрийте файл. А тепер обробіть його утилітою pkzipfix. exe (або запустите стандартний pkzip. exe із ключем Fix). В "виправленому" файлі чарівним образом з'являться всі вцілілі ZIP-архіви! Внутрішня структура ZIP-архіву така, що pkzipfix легко розпізнає навіть із блоки, тому високий ступінь фрагментації йому не перешкода.

Дефрагментация теж відбувається цікаво. Стандартне API дефрагментации в силу малозрозумілих обмежень оперує не одиничними кластерами, а блоками! Мінімальний розмір блоку становить 16 кластерів, причому початок блоку повинне бути кратне 16 кластерам у файлі! Як наслідок – кількість дрібних дір після дефрагментации тільки зростає, а безперервних областей вільного простору практично зовсім не залишається. До речі кажучи, переміщати усередину MFT-зони теж нічого не можна. "На томі З: вільно 17%, але тільки 5% доступно для використання дефргаментатора диска. Для ефективної роботи дефрагментатор вимагає принаймні 15% доступного вільного місця" – знайоме повідомлення, не чи правда? "Недоступне" для дефрагментатора місце перебуває усередині MFT-зони (як ми пам'ятаємо, при форматуванні диска під $MFT-файл резервується 10% від ємності тому, а потім у міру вичерпання дискового простору, $MFT-файл усікається наполовину й простір, що звільнилося, заселяється користувальницькими файлами). Таким чином, для гарантованої роботи дефргаментатора йому потрібно 10% + 15% == 25% вільного дискового простору. Чи не занадто висока плата за дефргаментацию? Якщо ж у вас вільно понад 25%, настійно рекомендується створити на диску тимчасовий файл і виконати seek, щоб заповнити усе більш-менш великі діри, не даючи їх изородовать дефрагментатору (природно, після дефрагментации цей файл потрібно видалити). До речі кажучи, на стислі файли обмеження в 16 кластерів не поширюються, тому дрібні файли дуже вигідно тримати в стислому стані – це істотно зменшує фрагменацию тому. Частіше дефрагментируйте свій диск! Це не тільки збільшить швидкодію, але й спростить відновлення вилучених файлів із затертої FILE Record.

Існують щонайменше дві методики дослідження стратегії виділення дискового простору: статична й динамічна. У першому випадку ми просто запускаємо дисковий редактор (переважно Disk Explorer від Runtime Software) і аналізуємо run-list'ы вже існуючих файлів, записаних у різний час і різні способи (можна, наприклад, скопіювати файл із одного місця в інше або поперемінно збільшувати розмір декількох файлів – стратегії виділення вільного простору в обох випадках будуть різні). Статичний підхід корисний тим, що дає безцінний статистичний результат для всього тому цілком, однак, визначає лише кінцевий результат, але не шлях, яким він був досягнутий.

Малюнок 3 статичний аналіз стратегії виділення дискового простору, виконуваний за допомогою Disk Explorer від Runtime Software

Дисковий монітор Марка Руссиновичка (http://www. ) дозволяє заглянути в "свята святих" файлової системи й побачити як саме вона виділять дисковий простір для файлів. Особливо цікаво запускати його паралельно з дефрагментатором і chkdsk'ом – таємне відразу стає явним.

Малюнок 4 динамічний аналіз стратегії виділення дискового простору, виконуваний за допомогою Дискового Монітора Марка Руссиновича

Якщо незважаючи на всі зусилля відновити вилучений файл так і не вдається, спробуйте відшукати його резервну копію. Багато додатків створюють такі копії, але не всі афішують їхню присутність. Не варто так само забувати про файл підкачування, тимчасових файлах, дампе пам'яті й інших джерелах, які можуть зберігати фрагменти відновлюваного файлу (а іноді й весь файл цілком). Навіть якщо вони вже були вилучені, можливо, що належить їм файловий запис ще не був затертий і відновлення не займе багато часу.

Відновлення файлів – операція нескладна, але нудотна й кропітка. Якщо з обов'язку служби або в силу інших обставин вам доводиться займатися відновленням постійно, – процес можна "механізувати", написавши кілька простих утиліт. Щоб одержати доступ до логічного розділу в Windows NT досить відкрити однойменний пристрій за допомогою функції CreateFile("\\.\X:", GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0), де "X:", де "X:" – буква логічного диска (подробиці – в MSDN або, як нині модно його називати – Platform SDK).

Не думайте, що всі вже написано задовго до вас! Утиліт, придатних для професійного відновлення даних, під NTFS дотепер немає (у всякому разі у відкритому продажі). Ті ж, що їсти страждають масою безглуздих обмежень (наприклад, не можуть обмежити діапазон секторного пошуку тільки вільним/зайнятим простором). Так що дерзайте!

У наступній статті цього циклу ми розглянемо техніку відновлення відформатованих дисків, у тому числі й тих, на які після форматування щось писалося.