Witam.
Myślę, że najwyższa pora spróbować przybliżyć działanie systemów plików z jakimi spotykamy się na co dzień.
Na początek chyba najbardziej obecnie powszechny system plików NTFS.
Ogłoszenie pozostawiam otwarte gdyż liczę na sporo konkretnych pytań dotyczących pracy i postępowania w czasie awarii.
Mam nadzieję, że takie "interaktywne" ogłoszenie pozwoli na lepsze wyjaśnienie wszelkich pytań a co za tym idzie pozwoli na stworzenie możliwie najlepszego opisu.
No to może ja zacznę od pytania Takie podstawowe pytanie o logice dysku.
Jak na podstawie MBR wyliczyć booty partycji,
Chciałbym dokładny opis na co patrzeć w edytorze HEX (co za co odpowiedzialne) oraz informacje jak te informacje z HEX przeliczyć na konkretne LBA, w których jest boot i boot copy.
Dysk ma bady 62-63 LBA, chce znaleźć boot copy.
W załączniku 0-100 LBA.
Każdy dysk zaczyna się od MBR lba 0, który zawiera boot strap i partition table, a ostatni dwa bajty jest sygnatura AA55 systemowa.
Najważniejszą rzeczą dla odbudowania logiki dysku jest właśnie partition table
offset, którego 0x01BE. Na wpis dla każdej z partycji jest 16 bajt.
Tak to wygląda :
0x01BE-0x01CD,
0x01CE-0x01DD,
0x01DE-0x01ED,
0x01EE-0x01FD.
zobaczymy jeden konkretny wpis partition table (tablicy alokacji partycji).
1 bajt jest bajtem flagi aktywności partycji, jeżeli mamy zawartość 80 partycja jest aktywna i możemy z niej bootować system, jeżeli 00 partycja jest nieaktywna.
2 bajt to głowica początku partycji,
3-4 bajty sektor/cylinder początku partycji - tu podane są cylindry i sektory, najwyższą liczbą może być FFFF = /cyl/1111111111/sec/111111, /cyl/1111111111=3FF=1023, /sec/111111=3F=63.
5 bajt id partycji .
6 bajt głowica końca partycji.
7-8 bajty sektor/cylindr końca partycji.
9-12 bajty offset początku partycji,
13-16 bajty liczba sektorów partycji.
Z tych wszystkich (dla odzyskiwania danych) najważniejsze 9-12 i 13-16 bajty ( w większości nowoczesne dyski, żeby nawet nie powiedzieć wszystkie pracują w LBA i znaczenie CHS (dla CHS max. jest 8,4 GB) dla LBA ignoruje się, oprócz jednego ze partycja musi zaczynać się od początku cylindra (głowica 0 lub 1 i sektor 1) i zakończyć się na końcu cylindra ( głowica max.-1, 255-1=254 i sektor x gdzie x to liczba sektorów na track fizycznego dysku).
Teraz patrzymy na przykład kolegi Nirvanowca, co my tu mamy:
0x01BE 00 01 01 00 07 FE BF C2 3F 00 00 00C4 4E AD 00 mamy primary nie aktywną partycję z sygnaturą 07 NTFS boot sektor offset 3f=63 LBA, liczba sektorów AD4EC4= 11357892 LBA
0x01CE 00 00 81 C3 0F FE FF FF 03 4F AD 00F8 50 B5 01 extended sygnatura 0F , offset boot extended AD4F03= 11357955 LBA , liczba sektorów 1B550F8= 28659960 LBA .
Teraz patrzymy w 63 sektor primary czyli w boot NTFS, tu widzimy ze po offsetu 0x7E00- 0x7FF0 (to jest nasz 63 lba) z pliku 0-100lba co podał kolega idą same zera. To może oznaczać ze atof trafił na bada lub sektor został wyzerowany. Teraz żeby odbudować partycję NTFS wystarczy odbudować boot NTFS używając do tego boot NTFS copy, który jest ulokowany na końcu partycji w ostatnim sektorze i to będzie sektor 11357954 LBA. Wykorzystując komendy tof/atof odczytujemy ten sektor i zawartość tego odczytanego sektora wgrywamy do sektora 63 LBA używając komendy MHDD ff. Jasnym powinno być to że przed wgraniem sektora należy sprawdzić same sektory i uszkodzone remapować ( a najpewniejszy sposób to jest praca z kopią dysku, wtedy ewentualne zniszczenia, które mogą powstać w skutek błędów użytkownika nie uszkodzą zawartości dysku oryginała).
W sektorze obliczonym przez Okzo czyli 11357954 LBA faktycznie znajduje się boot copy.
Mogę go wgrać teraz przez MHDD komendę FF ale nie był bym sobą jak bym nie poprosił o dokładny opis bootu i na co w nim patrzeć, co można wyczytać z niego?
Dla odbudowania logiki dysku NTFS, w sektorze Boot NTFS najważniejszy będzie BIOS Parameter Block (BPB) na obrazku.
sam BPB składa się z :
offset(w bajtach)/rozmiar(w bajtach) :
0/3 - komenda JMP
3/8 - Nazwa firmy producenta i systemu operacyjnego( w tym przypadku NTFS )
B/2 - Rozmiar sektora w bajtach
D/1 - Liczba sektorów w klastrze
E/7 - Zarezerwowane
15/1 - Typ nośnika (dysk twardy dowolnej pojemności F8 )
16/2 - Zarezerwowane
18/2 - Liczba sektorów na tracku
1A/2 - Liczba głowic
1C/4 - hiden sectors (młodsze słowo hiden sectors ^1)
20/4 - Zarezerwowane (starsze słowo hiden sectors ^1)
24/2 - Zawiera liczba 0x80
26/2 - Zawiera liczba 0x80
28/4 - Młodsze słowo ilości sektorów partycji
2C/4 - Starsze słowo ilości sektorów partycji
30/4 - Młodsze słowo numeru pierwszego klastra $MFT
34/4 - Starsze słowo numeru pierwszego klastra $MFT
38/4 - Młodsze słowo numeru pierwszego klastra $MFTmirror
3C/4 - Starsze słowo numeru pierwszego klastra $MFTmirror
40/4 - Rozmiar zapisu MFT w klastrach
44/4 - Rozmiar buforu index'ow w klastrach
48/4 - Młodsze słowo numeru seryjnego dysku
4C/4 - Starsze słowo numeru seryjnego dysku
^1 -1C/4 -hiden sectors i 20/4 - te bajty teraz wszędzie są opisywane jako zarezerwowane, ale moim zdaniem szybko rosnąca pojemność dysków nie pozostawia innego przeznaczenia dla nich, niż ukazane w nawiasach.
Teraz kiedy mamy boot NTFS możemy przeanalizować BPB.
patrzymy na przykładu kolegi boot'a.
Ze wszystkich parametrów nas będą ciekawić najważniejsze:
1. liczba sektorów w klastrze
2. pierwsze klastry $MFT i $MFTmirror ( dla sprawdzenia parametrów BPB)
1. Mamy 8 sektorów w klastrze ( będzie potrzebny żeby wyliczyć pierwszy sektor $MFT i $MFTmirror dla sprawdzenia)
2. Pierwszy klaster $MFT 04h=4 sektor (4x8)+63= 95 -102
Pierwszy klaster $MFTmirror 80000h=524288 sektor (524288x8)+63= 4194367 - 4194374
Właśnie te obszary nie zaszkodziło by sprawdzić 95 -102 i 4194367 - 4194374 !
Cóż można powiedzieć, pierwsze zapisy MFT i MFTmirror są po swoich adresach, biorąc pod uwagę bardzo wielki odstęp 95 lba i 4194367 lba jakiekolwiek przesunięcie i błąd można wykluczyć.
Pozostaje tylko wgrać boot copy na miejsce boot NTFS !
Pierwszym co wykonałem było wykonanie kopii 1:1 dzięki temu nie musiałem się obawiać uszkodzenia oryginału dysku, bo wszystkie działania były wykonane na kopii.
Po wyliczeniu BOOTcopy, sprawdziłem dzięki wyliczeniu kolegi Okzo czy MFT i MFTmirror są na swoich miejscach, okazało się ze tak, wiec przystąpiłem do wgrania
znalezionego BOOT COPY w miejsce BOOT czyli w LBA63 programem MHDD komenda FF i partycja została naprawiona, 100% danych odzyskanych.
Potrzebne do wykonania tej operacji było:
- MHDD
- dowolny edytor HEX
- inny nośnik sformatowany w Fat 32 (dyskietka lub drugi dysk) – na skopiowanie fragmentów dysku, które zgraliśmy dzięki MHDD i jego komendzie TOF lub ATOF.
No i oczywiście pomoc z Forum, która bardzo często okazuje się bardziej skuteczniejsza niż stosowanie softu czasami bardzo kosztownego.
Reasumując dane odzyskaliśmy praktycznie za darmo bez użycia jakichkolwiek programów odzyskujących dane.
W załączniku 0-100 LBA po wgraniu BOOT.
Chciałem jeszcze podziękować Koledze Okzo za dogłębne odpowiedzi na moje pytania oraz Koledze Przemcio za wspaniały pomysł tematu.
Nie mam jak kliknąć pomógł, wiec po 100pkt wysyłam.
Mam jeszcze jedną prośbę, prosił bym o jakiś opis MFT, co to właściwie jest oraz na co w nim patrzeć
MFT kolegi Nirvanowca będzie jak przykład!
Każdy zapis zawiera nagłówek stałego formatu, dalej idzie spis atrybutów zmiennej długości.
nagłówek MFT:
offset(w bajtach)/rozmiar(w bajtach)
0/4 - sygnatura MFT - "FILE"
4/2 - offset masywu korygowania zapisu Update Sequence
6/2 - rozmiar masywu zapisów Update Sequence
8/8 - numer kolejności pliku transakcji($LogFile Sequence Number)
10/2 - ostatni numer sektora w zapisu MFT
12/2 - licznik linków
14/2 - offset początku spisu atrybutów
16/2 - flagi, zaznaczające stan zapisu MFT : zawartości
00 - zapis nie wykorzystuje się
01 - zapis wykorzystuje się i opisuje plik (file)
02 - zapis nie wykorzystuje się i opisuje katalog (directory)
03 - zapis wykorzystuje się i opisuje katalog (directory) 18/4 - realny rozmiar zapisu MFT
1C/4 - rozmiar pamięci zajętej zapisem MFT
20/8 - numer (File Reference) bazowy zapis MFT
28/2 - maksymalna zawartość identyfikatora atrybutu, powiększonego o 1
2A/2 - Masyw korygowania zapisu MFT rozmiarem2*(N-1), gdzie N - zawartość rozmiaru masywu korygowania z pola z offset'em 0x06
2C/4 - dla XP index danego zapisu (number of this MFT record)
/2 - dla wszystkich numer kolejności aktualizacji (update sequence number)
/2S-2 - dla wszystkich, masyw kolejności aktualizacji (update sequence number)
Atrybuty: zgodnie z zawartością 14/2=0x0030 offset spisu atrybutów to 30h
Atrybut składa się z nagłówka, w którym jest:
offset(w bajtach)/rozmiar(w bajtach)
0/4 - typ atrybutu n.p. 0x00000010=$10 $STANDARD_INFORMATION
4/4 - rozmiar atrybutu w bajtach n.p. 0x00000060 60h i dodając tą zawartość wyliczamy offset kolejnego atrybutu 30h+60h=90h
90h
0/4 - typ atrybutu 0x00000030 $30 $FILE_NAME
4/4 - rozmiar atrybutu 0x00000068 68h + 90h =F8
F8H
0/4 - typ atrybutu 0x00000080 $80 $DATA
4/4 - rozmiar atrybutu 0x00000048 48h + F8 = 140H
140H
0/4 - typ atrybutu 0x000000B0 $B0 $BITMAP
4/4 - rozmiar atrybutu 0x00000048 48 + 140 = 188H
188H FF FF FF FF sygnatura końca spisu atrybutów
Każdy z atrybutów rozpatrzymy osobno.. ale to trochę później, jak będę miał trochę czasu, opisze wszystkie zawartości i flagi.
Adresy i rozmiar atrybutów nauczyliśmy się już wyliczać, teraz o samych atrybutach. Każdy atrybut zawiera nagłówek i ciało (body) obszar danych, adresy typu i rozmiar już opisany, dlatego zaczniemy od kolejnych zawartości nagłówka.
offset(w bajtach)/rozmiar(w bajtach)
0/4 - typ
4/4 - rozmiar
8/1 - flaga nierezydentnego atrybutu (00 rezydentny, 01 nierezydentny)
9/1 - długość nazwy atrybutu (00 atrybut nie ma nazwy)
A/2 - offset obszaru danych (body) atrybutu
C/2 - flaga skompresowanego/zaszyfrowanego atrybutu
E/2 - identyfikator atrybutu
$STANDARD_INFORMATION 18/8 - Data i czas utworzenia pliku
20/8 - Data i czas ostatniej modyfikacji pliku
28/8 - Data i czas ostatniej zmiany zapisu MFT tego pliku
30/8 - Data i czas ostatniego zgłoszenia do pliku
38/4 - Flagi dostępu
3C/12 - Zarezerwowane
--
Data i czas: to liczba interwalów o długości 100ns od 1 stycznia 1601 roku, czasu UTC.
Flagi dostępu: to zbiór osobnych bitów, połączonych przy pomocy operacji logiczniej (OR - LUB)
Bity
0x0001 - dla pliku lub folderu dozwolone tylko czytanie
0x0002 - ukryty plik lub folder
0x0004 - plik lub folder systemowy
0x0020 - plik był zarchiwizowany
0x0400 - dowiązanie symboliczne (Symbolic Link)
0x0800 - plik lub folder skompresowany
$FILE_NAME Ten atrybut zawsze jest rezydentny.
Dla pliku lub folderu może być utworzono kilka takich atrybutów, zawierających imiona w rożnych przestrzeniach imion (Filename spaces).
1.imiona w standardzie POSIX - mogą być dowolne znaki oprócz 0 i "/"
2.imiona w standardzie o/s Mircrosoft Windows - ograniczenia MS WIN
3.imiona w standardzie "8.3' o/s MS-DOS - ograniczenia MS-DOS
offset(w bajtach)/rozmiar(w bajtach)
18/8 - numer zapisu MFT dla folderu, zawierającego ten plik
20/8 - Data i czas utworzenia pliku
28/8 - Data i czas ostatniej modyfikacji pliku
30/8 - Data i czas ostatniej zmiany zapisu MFT tego pliku
38/8 - Data i czas ostatniego zgłoszenia do pliku
40/8 - Rozmiar przestrzeni dyskowej wykorzystanej dla przechowywania pliku
48/8 - Realna długość pliku
50/8 - Flagi dostępu
58/1 - Długość imienia pliku N
59/1 - Kod przestrzeni imienia pliku
5A/2*N - Imię pliku. To pole ma długość 2*N, gdzie N - długość imienia pliku z pola po offset'u 58h
Informacja o dacie i czasie a także flagi dostępu dublują się, i są tak samo w $STANDARD_INFORMATION. Jeżeli flaga dostępu ma zawartość 0x1000000, to imię należy do folderu a nie do pliku.
$DATA W zależności od wielkości pliku, może być rezydentny lub nierezydentny ( jeżeli wielkość pliku pozwala ulokować dane pliku w samym MFT, to ten atrybut nazywa się rezydentny, jeżeli dla danych pliku wydzielone są klastry przestrzeni partycji NTFS wówczas ten atrybut nazywa się nierezydentny).
Rezydentny atrybut $DATA
offset(w bajtach)/rozmiar(w bajtach)
10/4 - Rozmiar bloku danych
14/2 - Offset bloku danych
16/2 - Flaga indeksowanego atrybutu
Tu najważniejszym (dla odzyskiwania danych) można liczyć rozmiar i offset bloku danych. Wyliczając je możemy odzyskać dane rezydentnego atrybutu.
Nierezydentny atrybut $DATA offset(w bajtach)/rozmiar(w bajtach)
10/8 - Początkowy numer VCN (starting VCN)
18/8 - Końcowy numer VCN (last VCN)
20/2 - Offset spisu ekstentow Runlist (data runs)
22/2 - Kod metody kompresowania( pakowania) atrybutu (compression unit size)
24/4 - 00h
28/8 - Rozmiar obszaru danych, zajętego przez plik na dysku (allocated size)
30/8 - Realna długość pliku (real size)
38/8 - Rozmiar inicjalizowanego obszaru pamięci dyskowej, wydzielonej dla przechowywania pliku
Z tego najbardziej nas będzie ciekawił spis ekstentow ( odcinkow "fragmentow") runlist ( data runs). Każdy element runlist opisuje rozmiar i ulokowanie jednego ekstenta ( odcinka) pliku.
A także metoda kompresowania, rozmiar obszaru danych, wydzielonego obszaru i realnie zajętego plikiem .
Offset runlist wyliczamy z pola 20/2 tu mamy 0040h to oznacza ze runlist jest po offsecie 40h od początku atrybutu. Teraz co do samego runlist, w tym konkretnym pliku kolegi Nirvanowca mamy runlist11 280400 . Jak to odczytać?
A tak: pierwszy bajt 11h w nim młodszy nibl 01h opisuje pole długości odcinku, a starszy nibl 01h rozmiar pola dla początkowego klastra. Z tego wynika ze nasz plik zaczyna się z klastra 04h i ma długość 28h klastrów. Sygnatura 00 oznacza ze to ostatni odcinek w runlist.
Teraz przykład wielu odcinkowego opisu runlist np. mamy 04h - 427h, 946h - 1078h, 1786h - 2899h temu będzie odpowiadał taki run-list 1223 04042232 0746 092213 1186 1700. tu widzimy ze pierwszy odcinek zawiera: młodszy nibl 02h to 0423h, starszy nibl 01h to 04h , to i jest nasz odcinek na dysku 04 - (0423h+04h) zaczyna się z 4 klastra i kończy się na 1063 klastrze i t.d.
Teraz co do kodu metody kompresowania, tu mamy 00 to oznacza ze atrybut nie używa ani kompresji ani szyfrowania. Jeżeli kod byłby równy 4 to atrybut może być kompresowany lub zaszyfrowany.
"Real size" tu jest równy 28000h = 163840bajt
To samo i w przypadku "allocated size"..