Master File Table

MFT

NTFS-tiedostojärjestelmän merkittävin arvokkaan tiedon lähde on Master File Table (MFT). MFT:n aloitussektorin sijainti löytyy levyn käynnistyssektorista, ja jokaisella tiedostolla ja hakemistolla on merkintä MFT:ssä. Kukin MFT-merkintä on kooltaan 1024 tavua, joten MFT:tä on erittäin helppo analysoida. Jokainen MFT-tietue tai merkintä alkaa ASCII-merkkijonolla ”FILE” (jos merkinnässä on virhe, se alkaa merkinnällä ”BAAD”) ja koostuu yhdestä tai useammasta (useimmiten useammasta) attribuutista, joilla kullakin on oma tunnisteensa ja rakenteensa. Kuvassa 4.1 on esitetty osa MFT-merkinnästä.

Kuva 4.1. MFT-merkintä. Ote MFT-tietueesta eli merkinnästä.

Kunkin MFT-merkinnän ensimmäiset 42 tavua käsittävät 12 elementtiä sisältävän otsikkorakenteen, ja loput 982 tavua riippuvat suurelta osin otsikossa olevista arvoista ja merkinnän sisältämistä eri attribuuteista. Kaikki MFT-merkinnän otsikon sisältämät elementit eivät ole välittömästi hyödyllisiä rikostekniselle analyytikolle; kuvassa 4.2 on kuitenkin esitetty viisi välittömästi hyödyllistä elementtiä.

Kuva 4.2. MFT-merkinnän otsikon elementit. MFT-tietueen otsikon elementit (pienessä endiaanisessa järjestyksessä).

Kuten kuviossa 4.2 (joka on osa kuviosta 4.1 poimittua kuviota) näkyy ”FILE”-allekirjoitus tietueen alussa. Sen jälkeen näemme järjestysnumeron tai arvon, jota kasvatetaan, kun tietue varataan tai vapautetaan. Koska tämä MFT-tietue on itse asiassa ensimmäinen tietue MFT:ssä ja viittaa tiedostoon ”$MFT”, on selvää, että järjestysnumero on 1. Seuraavaksi on linkkien määrä, joka viittaa niiden hakemistojen lukumäärään, joissa on tietueeseen liittyviä merkintöjä (kovien linkkien vuoksi tätä arvoa kasvatetaan). Seuraavaksi on tietueen siirtymä ensimmäiseen attribuuttiin; jos katsot tietueen siirtymää 0x38, näet, että ensimmäisen attribuutin tunniste on 0x10 eli 16. Lopuksi nähdään flags-arvo, joka kertoo, onko merkintä varattu (jos 0x01-bitti on asetettu) ja onko merkintä hakemisto (jos 0x02-bitti on asetettu). Lyhyesti sanottuna näistä kahdesta arvosta voimme määrittää, onko merkintä varattu vai poistettu ja onko se tiedosto vai hakemisto. Kun otsikkoa jäsennetään, pseudokoodi voidaan esittää seuraavasti:

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

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

Kuvassa 4.2 näkyvä flags-arvo on ”0x01”, mikä viittaa allokoituun tiedostoon. Arvo 0x00 osoittaisi poistettua tiedostoa ja arvo 0x03 osoittaisi varattua hakemistoa.

Vinkki

MFT-tietueet

MFT-tietueita ei poisteta sen jälkeen, kun ne on luotu; uusia tietueita lisätään MFT-tietueeseen tarpeen mukaan, ja poistettujen tiedostojen tietueita käytetään uudelleen.

Kuten aiemmin mainittiin, vain ensimmäiset 42 tavua ovat strukturoituja; sen jälkeen MFT-merkinnän loppuosa koostuu yhdestä tai useammasta attribuuttikentästä. Ei ole olemassa mitään virallista määrittelyä tai lauseketta, jossa sanotaan, että MFT-tietueessa on oltava tiettyjä attribuutteja, mutta useimmiten useimmissa MFT-tietueissa voi odottaa olevan $STANDARD_INFORMATION- ja $FILE_NAME-attribuutti. Tässä jaksossa tarkastellaan näitä kahta attribuuttia, koska ne antavat aikaleimatietoja, jotka ovat arvokkaita rikosteknisille analyytikoille. Tarkastelemme lyhyesti myös $DATA-attribuuttia ja jätämme loput attribuutit kiinnostuneen ja uteliaan lukijan tehtäväksi.

Kunkin attribuutin otsakkeessa on 16 tavun otsikko, joka määrittää muun muassa attribuutin tyypin, attribuutin kokonaispituuden ja sen, kuuluuko attribuutti MFT-merkintään vai ei.

Huomautus

MFT-metatietotiedostot

MFT:n 16 ensimmäistä merkintää sisältävät tietoa metatietotiedostoista; niitä kaikkia ei kuitenkaan välttämättä käytetä. Ne, joita ei käytetä, jätetään varattuun tilaan, ja ne sisältävät vain perustiedot.

Tämän otsikkotiedon avulla voimme analysoida MFT-merkinnän läpi ja poimia arvokasta tietoa jokaisesta attribuutista. Esimerkiksi attribuutti $STANDARD_INFORMATION (joka on aina residentti) on olemassa jokaisessa tiedosto- ja hakemistomerkinnässä, ja sen tunniste on 0x10 (eli 16). Tämä attribuutti sisältää MFT-merkinnän tiedostoajat (ainakin kolme niistä), jotka näemme, kun kirjoitamme komentokehotteeseen ”dir”; tiedoston tai hakemiston muutetun ajan, viimeisimmän käyttökerran ajan ja luontipäivämäärän (syntymäpäivämäärän), joihin viitataan myös nimellä ”MAC”-ajat. Attribuutti sisältää neljännen aika-arvon, joka määrittää viimeisimmän kerran, jolloin MFT-merkintää muutettiin. Kaikkiaan näitä aikoja kutsutaan ”MACE”- (jossa ”E” viittaa MFT-merkinnän muutosajankohtaan) tai ”MACB”- (jossa ”C” viittaa MFT-merkinnän muutosajankohtaan) -ajankohdiksi.

Varoitus

Tiedostoajat

NTFS-tiedostojen ajat tallennetaan UTC-muodossa (Universal Coordinated Time, koordinoitu universaaliaika), joka vastaa Greenwichin keskiyön aikaa. Tämä pätee kaikkiin kellonaikoihin; jokaisessa MFT-merkinnässä tiedostotietueeseen liittyy todennäköisesti vähintään 8 kellonaikaa; monesti 12 tai enemmän. FAT-tiedostojärjestelmässä tiedostojen kellonajat säilytetään paikallisen järjestelmän aikamuodossa.

$FILE_NAME-attribuutti (tunniste 0x30 eli 48) esiintyy myös useimmissa tiedostojen ja hakemistojen MFT-merkinnöissä; itse asiassa monissa MFT-merkinnöissä on useampi kuin yksi $FILE_NAME-attribuutti. Kuten attribuutti $STANDARD_INFORMATION, tämäkin attribuutti on aina residentti, ja se sisältää myös neljä aika-arvoa; nämä aika-arvot asetetaan kuitenkin yleensä silloin, kun tiedosto luodaan järjestelmään. Toisin kuin $STANDARD_INFORMATION-attribuutin tiedostoaikojen kohdalla, näihin tiedostoaikoihin ei vaikuta normaali järjestelmätoiminta tai ilkivaltainen manipulointi, joten niitä voidaan käyttää ilkivaltaisen toiminnan indikaattoreiden määrittämiseen, ja voidaan ryhtyä toimenpiteisiin järjestelmän saastumisajankohdan häivyttämiseksi. Seuraava koodinäyte (parseSIAttr()-funktio) on esimerkki siitä, miten $STANDARD_INFORMATION-attribuutti voidaan jäsentää:

sub parseSIAttr {

my $si = shift;

my %si;

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

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

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

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

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

my ($t0,$t1) = unpack(”VV”,substr($content,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($sisältö,24,8));

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

$si{flags} = unpack(”V”,substr($sisältö,32,4));

return %si;

}

Vinkki

GetTime

Juuri annetussa parseSIAttr()-attribuutin koodilistauksessa näkyvä getTime()-funktio koostuu Andreas Schusterilta lainatusta koodista, joka kääntää 64-bittiset FILETIME-objektien aikaleimat 32-bittiseksi Unix-ajaksi, joka voidaan edelleen kääntää ihmiselle luettavaksi kellonajaksi Perl:iin sisäänrakennetulla funktiolla gmtime(). Koodi näyttää seuraavalta:

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;

}

Tämä koodi on erittäin käyttökelpoinen, kun halutaan jäsennellä ja kääntää mikä tahansa FILETIME-objekti riippumatta siitä, mistä se on otettu.

Normaalissa järjestelmässä monilla MFT-merkinnöillä voi olla kaksi $FILE_NAME-attribuuttia: yksi tiedoston (tai hakemiston) täydellistä nimeä varten ja toinen DOS-, 8.3-tiedostonimeä varten. Jos tiedoston nimi on esimerkiksi ”myreallylongfile.txt”, 8.3-tiedoston nimi on ”myreal~1.txt”. Tämä säilytetään yhteensopivuuden vuoksi vanhempien tiedostojärjestelmien kanssa ja niiden kanssa, jotka eivät tue pitkiä tiedostonimiä. Ei siis ole epätavallista, että tavallisessa Windows-järjestelmässä on useita MFT-merkintöjä, joissa on kaksi $FILE_NAME-attribuuttia, joiden sisältö on lähes identtinen. Seuraavassa koodiesimerkissä (parseFNAttr()-funktio) on esimerkki siitä, miten MFT-merkinnän $FILE_NAME-attribuutti voidaan jäsentää ja käytettävissä olevat tiedot poimia:

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($sisältö,16,8));

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

my ($t0,$t1) = unpack(”VV”,substr($sisältö,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_name} = $fn{len_name} * 2 if ($fn{namespace} > 0);

$fn{name} = substr($content,66,$fn{len_name});

$fn{name} = cleanStr($fn{name}) if ($fn{namespace} > 0);

$fn{name} =~ s/\x0c/\x2e/g;

$fn{name} =~ s///g;

return %fn;

}

}

Keskustelemme viimeisenä käsiteltävästä attribuutista $DATA-attribuuttia (tunniste 0x80 eli 128). Tämä attribuutti sisältää tiedoston varsinaisen sisällön tai viittaa siihen. Jos attribuutin otsikon nonresident-lippua ei ole asetettu, tiedoston sisältö sijaitsee MFT-merkinnän $DATA-attribuutissa otsikon ja kahden muun rakenteen jälkeen. Tämä pätee yleensä esimerkiksi lyhyisiin tekstitiedostoihin tai muihin alle 700 tavun tiedostoihin. Jos tiedot eivät ole residenttejä, on käännettävä ”data-juoksut” eli se, missä tiedot sijaitsevat levyllä.

Esimerkkikoodi $DATA-attribuutin data-juoksujen jäsentämiseen on hyvin monimutkainen, eikä sitä esitetä tässä. Vastaavasti koodi tietojen poimimiseksi maassa asuvista $DATA-attribuuteista on triviaalia ja koostuu attribuuttiotsikon jälkeisen lisätiedon (sisällön koko ja siirtymä sisältöön) jäsentämisestä.

Joitakin avoimen lähdekoodin työkaluja on saatavilla MFT:n (erityisesti $STANDARD_INFORMATION- ja $FILE_NAME-attribuuttien) jäsentämistä varten ja aikaleimattujen tietojen saamiseksi analyytikon käyttöön. Yksi niistä on David Kovarin analyzemft.py Python-skripti, joka löytyy verkosta osoitteesta http://www.integriography.com/projects/analyzeMFT. Toinen on mft.pl-perl-skripti, josta on poimittu parseSIAttr()- ja parseFNAttr()-funktiot, ja se on saatavilla WinForensicAnalysis Google Code -projektissa, joka löytyy WWW-osoitteesta http://code.google.com/p/winforensicaanalysis.

Brian Carrierin ”The SleuthKit”-työkalut (TSK) ovat luultavasti tunnetuimpia työkaluja, joiden avulla voidaan kerätä monenlaista tiedostojärjestelmä- ja tiedostojärjestelmämetadatatietoa talteen otetuista kuvista ja jopa elävistä järjestelmistä. Esimerkiksi kerätäkseen luettelon tiedostojärjestelmän $STANDARD_INFORMATION -attribuutin tiedostoajoista hankitusta kuvasta analyytikko voi käyttää seuraavan kaltaista komentoa:

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

Tämä komento tuottaa niin sanotun bodyfile-tiedoston, joka on välitiedostomuoto, jota käytetään näiden tietojen tallentamiseen ennen niiden muuntamista tiedostojärjestelmän aikajanaksi. Joissakin tapauksissa analyytikko voi joutua lisäämään ”-o”-kytkimen tunnistaakseen siirtymän osioon, joka näkyi elävässä järjestelmässä ”C:\”-asemana; tämä siirtymätieto voidaan määrittää manuaalisesti hex-editorilla tai käyttämällä mmls.exe:tä.

Analyytikko voi myös kerätä näitä samoja tietoja elävästä etäkäytössä olevasta järjestelmästä F-Response-ohjelmalla. Jos analyytikko on muodostanut asianmukaisen yhteyden etäjärjestelmään ja asentanut järjestelmän C:\-aseman F:\:ksi omassa järjestelmässään, hän voi käyttää seuraavaa komentoa vastaavaa komentoa kerätäkseen $STANDARD_INFORMATION-attribuutin tiedostoaikoja C:\-osiossa oleville tiedostoille:

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

Täydelliset TSK-työkalut sekä dokumentaatio ja käyttötiedot löytyvät verkosta SleuthKit-verkkosivustolta, http://www.sleuthkit.org.

Vastaa

Sähköpostiosoitettasi ei julkaista.