Master File Table

MFT

Az NTFS fájlrendszerből származó értékes információk legjelentősebb forrása az elemző számára a Master File Table (MFT). Az MFT kezdőszektorának helye a lemez indítószektorában található, és a kötetben lévő minden fájlnak és könyvtárnak van bejegyzése az MFT-ben. Minden egyes MFT-bejegyzés 1024 bájt méretű, így az MFT-t nagyon egyszerű elemezni. Minden MFT rekord vagy bejegyzés a “FILE” ASCII karakterlánccal kezdődik (ha hiba van a bejegyzésben, akkor “BAAD”-dal kezdődik), és egy vagy több (leggyakrabban több) attribútumból áll, mindegyiknek saját azonosítója és szerkezete van. A 4.1. ábra egy MFT-bejegyzés egy részét szemlélteti.

4.1. ábra. Egy MFT rekord vagy bejegyzés részlete.

Az egyes MFT-bejegyzések első 42 bájtja egy 12 elemet tartalmazó fejlécstruktúrát tartalmaz, a fennmaradó 982 bájt pedig nagyrészt a fejlécen belüli értékektől és a bejegyzésben szereplő különböző attribútumoktól függ. Az MFT-bejegyzés fejlécében található elemek közül nem mindegyik hasznos azonnal a törvényszéki elemző számára; a 4.2. ábra azonban öt olyan elemet mutat be, amelyek azonnal hasznosak.

4.2. ábra. Az MFT rekord fejlécének elemei (little Endian sorrendben).

A 4.2. ábrán (amely a 4.1. ábrából kiragadott rész) látható, hogy a rekord elején látható a “FILE” aláírás. Ezután látjuk a sorszámot vagy értéket, amely a bejegyzés kiosztásakor vagy feloldásakor növekszik. Mivel ez a konkrét MFT-bejegyzés valójában az első rekord az MFT-n belül, és a “$MFT” fájlra utal, logikus, hogy a sorszám 1. Ezután következik a linkek száma, amely arra utal, hogy hány könyvtárban van bejegyzés ehhez a rekordhoz (a kemény linkek miatt ez az érték növekszik). Ezután következik a rekordon belüli eltolás az első attribútumhoz; ha megnézzük a rekordon belüli 0x38-as eltolást, akkor láthatjuk, hogy az első attribútum azonosítója 0x10, azaz 16-os. Végül a flags értéket látjuk, amely megmondja, hogy a bejegyzés ki van-e osztva (ha a 0x01 bit be van állítva), és hogy a bejegyzés könyvtár-e (ha a 0x02 bit be van állítva). Röviden, ebből a két értékből megállapíthatjuk, hogy a bejegyzés ki van-e osztva vagy törölve, és hogy fájlhoz vagy könyvtárhoz tartozik-e. A fejléc elemzésekor ennek pszeudokódja a következőképpen ábrázolható:

if ($mft{flags} & 0x0001) – allocated; else unallocated/deleted

if ($mft{flags} & 0x0002) – folder/directory; else file

A 4.2. ábrán látható flags érték “0x01”, ami egy allokált fájlt jelöl. A 0x00-as érték törölt fájlt, a 0x03-as érték pedig kiosztott könyvtárat jelezne.

Tipp

MFT rekordok

A MFT rekordok létrehozása után nem törlődnek; szükség szerint új rekordok kerülnek az MFT-be, és a törölt fájlok rekordjai újra felhasználásra kerülnek.

Mint már említettük, csak az első 42 bájt strukturált; ezután az MFT-bejegyzés többi része egy vagy több attribútummezőből áll. Nincs olyan formális előírás vagy kijelentés, amely kimondja, hogy egy MFT-bejegyzésben meghatározott attribútumoknak kell lenniük, de a legtöbb MFT-bejegyzésben várhatóan egy $STANDARD_INFORMATION és egy $FILE_NAME attribútumot találunk. Ez a szakasz ezt a két attribútumot vizsgálja, mivel ezek időbélyeginformációt szolgáltatnak, ami értékes a törvényszéki elemzők számára. Röviden megvizsgáljuk a $DATA attribútumot is, a többi attribútumot pedig az érdeklődő és kíváncsi olvasónak hagyjuk feladatul.

Az egyes attribútumok fejléce egy 16 bájtos fejlécet tartalmaz, amely többek között azonosítja az attribútum típusát, az attribútum teljes hosszát, valamint azt, hogy az attribútum rezidens-e az MFT-bejegyzésben vagy sem.

Jegyzet

MFT metaadatfájlok

Az MFT első 16 bejegyzése a metaadatfájlokra vonatkozó információkat tartalmazza, azonban nem biztos, hogy mindet használják. Azok, amelyeket nem használnak, kiosztott állapotban maradnak, és csak alapvető információkat tartalmaznak.

Ezeket a fejlécinformációkat felhasználva elemezhetjük az MFT-bejegyzéseket, és minden egyes attribútumból értékes információkat nyerhetünk ki. Például a $STANDARD_INFORMATION attribútum (amely mindig rezidens) minden fájl- és könyvtárbejegyzéshez létezik, és 0x10 (azaz 16) azonosítóval rendelkezik. Ez az attribútum tartalmazza az MFT-bejegyzéshez tartozó fájlidőket (legalábbis hármat), amelyeket akkor látunk, amikor a parancssorba beírjuk a “dir” szót; a fájl vagy könyvtár módosítási idejét, utolsó hozzáférési idejét és létrehozási (születési) dátumát, más néven “MAC” időket. Az attribútum tartalmaz egy negyedik időértéket, amely az MFT-bejegyzés utolsó módosításának időpontját adja meg. Ezeket az időpontokat együttesen “MACE” (az “E” az MFT-bejegyzés módosítási idejére utal) vagy “MACB” (a “C” az MFT-bejegyzés módosítási idejére utal) időpontoknak nevezik.

Figyelmeztetés

File Times

Az NTFS-fájlok időpontjai az egyetemes koordinált idő (UTC) formátumában kerülnek rögzítésre, ami a greenwichi középidővel analóg. Ez minden időpontra igaz; minden MFT-bejegyzésben egy fájlrekordhoz valószínűleg legalább 8 időpont tartozik; sokszor 12 vagy több. A FAT fájlrendszeren a fájlidők a helyi rendszeridő formátumban vannak tárolva.

A $FILE_NAME attribútum (0x30-as vagy 48-as azonosító) szintén megtalálható a legtöbb fájl- és könyvtár MFT-bejegyzésnél; valójában sok MFT-bejegyzésnek egynél több $FILE_NAME attribútuma van. A $STANDARD_INFORMATION attribútumhoz hasonlóan ez az attribútum is mindig rezidens, és négy időértéket is tartalmaz; ezek az időértékek azonban általában a fájl létrehozásakor kerülnek beállításra a rendszerben. A $STANDARD_INFORMATION attribútumban szereplő fájlidőkkel ellentétben ezeket a fájlidőket nem befolyásolja a normál rendszertevékenység vagy a rosszindulatú manipuláció, ezért felhasználhatók a rosszindulatú tevékenység mutatóinak meghatározására, és lépéseket lehet tenni a rendszer fertőzésének időpontjának elfedésére. A következő kódminta (parseSIAttr() függvény) példát mutat arra, hogyan lehet a $STANDARD_INFORMATION attribútumot elemezni:

sub parseSIAttr {

my $si = shift;

my %si;

my ($type,$len,$res,$name_len,$name_ofs,$flags,$id,$sz_content,$ofs_content)

= unpack(“VVCCvvvvVv”,substr($si,0,22));

my $content = substr($si,$ofs_content,$sz_content);

my ($t0,$t1) = unpack(“VV”,substr($tartalom,0,8));

$si{c_time} = getTime($t0,$t1);

my ($t0,$t1) = unpack(“VV”,substr($tartalom,8,8));

$si{m_time} = getTime($t0,$t1);

my ($t0,$t1) = unpack(“VV”,substr($content,16,8));

$si{mft_m_time} = getTime($t0,$t1);

my ($t0,$t1) = unpack(“VV”,substr($tartalom,24,8));

$si{a_time} = getTime($t0,$t1);

$si{flags} = unpack(“V”,substr($tartalom,32,4));

return %si;

}

Tipp

GetTime

A most megadott parseSIAttr() attribútum kódlistájában látható getTime() függvény egy Andreas Schustertől kölcsönzött kódból áll, amely a 64 bites FILETIME objektum időbélyegeit 32 bites Unix időre fordítja, amely a Perl beépített gmtime() függvényével tovább fordítható ember által olvasható időre. Ez a kód a következőképpen néz ki:

sub getTime($$) {

my $lo = shift;

my $hi = shift;

my $t;

if ($lo == 0 && $hi == 0) {

$t = 0;

} else {

$lo -= 0xd53e8000;

$hi -= 0x019db1de;

$t = int($hi*429.4967296 + $lo/1e7);

};

$t = 0 if ($t < 0);

return $t;

}

Ez a kód nagyon hasznos bármely FILETIME objektum elemzésére és fordítására, függetlenül attól, hogy honnan származik.

Egy normál rendszeren sok MFT-bejegyzésnek két $FILE_NAME attribútuma lehet: egy a fájl (vagy könyvtár) teljes nevének és egy a DOS, 8.3 fájlnévnek a tárolására. Ha például egy fájl neve “myreallylongfile.txt”, akkor a 8.3-as fájlnév “myreal~1.txt”. Ezt a régebbi és a hosszú fájlneveket nem támogató fájlrendszerekkel való kompatibilitás érdekében tartjuk fenn. Így egy normál Windows rendszeren nem szokatlan, hogy számos MFT-bejegyzés van két $FILE_NAME attribútummal, közel azonos tartalommal. A következő kódminta (parseFNAttr() függvény) példát mutat arra, hogyan lehet egy MFT-bejegyzés $FILE_NAME attribútumát elemezni és a rendelkezésre álló adatokat kinyerni:

sub parseFNAttr {

my $fn = shift;

my %fn;

my ($type,$len,$res,$name_len,$name_ofs,$flags,$id,$sz_content,$ofs_content)

= unpack(“VVCCvvvVv”,substr($fn,0,22));

my $content = substr($fn,$ofs_content,$sz_content);

$fn{parent_ref} = unpack(“V”,substr($content,0,4));

$fn{parent_seq} = unpack(“v”,substr($content,6,2));

my ($t0,$t1) = unpack(“VV”,substr($content,8,8));

$fn{c_time} = getTime($t0,$t1);

my ($t0,$t1) = unpack(“VV”,substr($tartalom,16,8));

$fn{m_time} = getTime($t0,$t1);

my ($t0,$t1) = unpack(“VV”,substr($tartalom,24,8));

$fn{mft_m_time} = getTime($t0,$t1);

my ($t0,$t1) = unpack(“VV”,substr($content,32,8));

$fn{a_time} = getTime($t0,$t1);

$fn{flags} = unpack(“V”,substr($content,56,4));

$fn{len_name} = unpack(“C”,substr($content,64,1));

$fn{namespace} = unpack(“C”,substr($content,65,1));

$fn{len_név} = $fn{len_név} * 2 if ($fn{namespace} > 0);

$fn{név} = substr($content,66,$fn{len_név});

$fn{név} = cleanStr($fn{név}) if ($fn{namespace} > 0);

$fn{név} =~ s/\x0c/\x2e/g;

$fn{név} =~ s///g;

return %fn;

}

Az utolsó attribútum, amit tárgyalunk, a $DATA attribútum (azonosító 0x80, vagy 128). Ez az attribútum a fájl tényleges tartalmát tartalmazza, illetve arra utal. Ha az attribútum fejlécében a nem rezidens jelző nincs beállítva, akkor a fájl tartalma az MFT-bejegyzés $DATA attribútumában található, a fejléc és két további struktúra után. Ez általában igaz például a rövid szövegfájlokra vagy más, 700 bájtnál kisebb fájlokra. Ha az adatok nem rezidensek, akkor az “adatfutásokat”, vagyis azt, hogy az adatok hol találhatók a lemezen, le kell fordítani.

A $DATA attribútum adatfutásainak elemzésére szolgáló példakód nagyon bonyolult, és itt nem mutatjuk be. Hasonlóképpen, a rezidens $DATA attribútumokból származó információk kinyerésére szolgáló kód triviális, és néhány további információ (a tartalom mérete és a tartalomhoz való eltolás) elemzése az attribútum fejléc után.

Az MFT elemzésére (különösen a $STANDARD_INFORMATION és a $FILE_NAME attribútumok) és az időbélyegzett adatok elemző számára történő rendelkezésre bocsátására néhány nyílt forráskódú eszköz áll rendelkezésre. Az egyik ilyen David Kovar analyzemft.py Python szkriptje, amely megtalálható a weben a http://www.integriography.com/projects/analyzeMFT címen. A másik az mft.pl Perl szkript, amelyből a parseSIAttr() és parseFNAttr() függvények kerültek ki, és amely elérhető a WinForensicAnalysis Google Code projektben, a weben a http://code.google.com/p/winforensicaanalysis címen.

Brian Carrier “The SleuthKit” (TSK) eszközei valószínűleg a legismertebbek a fájlrendszer és fájlrendszer metaadatok széles körének gyűjtésére a megszerzett képekről és akár élő rendszerekről. Például a fájlrendszer $STANDARD_INFORMATION attribútumú fájlidők listájának összegyűjtéséhez egy megszerzett képről az elemző a következőhöz hasonló parancsot használhatja:

C:\tsk>fls -f ntfs -m C:/ -p -r G:\case\xp.img > G:\case\files\bodyfile.txt

Ez a parancs egy úgynevezett “bodyfile”-t hoz létre, amely egy köztes fájlformátum, amelyet ezen információk tárolására használnak, mielőtt azokat a fájlrendszeri tevékenység idővonalává alakítanák. Bizonyos esetekben az elemzőnek hozzá kell adnia a “-o” kapcsolót annak érdekében, hogy azonosítsa az élő rendszerben “C:\” meghajtóként megjelenő partíció eltolását; ez az eltolási információ manuálisan is meghatározható hexaszerkesztővel vagy az mmls.exe segítségével.

Az elemző ugyanezt az információt egy élő, távoli rendszerről is összegyűjtheti az F-Response segítségével. Ha az elemző megfelelően csatlakozott a távoli rendszerhez, és a rendszer C:\ meghajtóját a saját rendszerén F:\-ként csatlakoztatta, akkor a következőhöz hasonló parancsot használhat a C:\ partícióban lévő fájlok $STANDARD_INFORMATION attribútumú fájlidejének összegyűjtéséhez:

C:\tsk>fls -f ntfs -m C:/ -p -r \\\.\F: > g:\case\files\bodyfile.txt

A teljes TSK eszközkészlet, valamint a dokumentáció és a használati információk megtalálhatók a weben a SleuthKit weboldalán, .

Vélemény, hozzászólás?

Az e-mail-címet nem tesszük közzé.