MFT
Den mest anmärkningsvärda källan till värdefull information för en analytiker från NTFS-filsystemet är Master File Table (MFT). Platsen för startsektorn för MFT finns i startsektorn på disken, och varje fil och katalog på volymen har en post i MFT. Varje MFT-post är 1024 byte stor, vilket gör MFT mycket enkel att analysera. Varje MFT-post börjar med ASCII-strängen ”FILE” (om det finns ett fel i posten börjar den med ”BAAD”) och består av ett eller flera (oftast flera) attribut, vart och ett med sin egen identifierare och struktur. Figur 4.1 illustrerar en del av en MFT-post.
De första 42 bytena i varje MFT-post består av en rubrikstruktur med 12 element, och de återstående 982 bytena beror till stor del på värdena i rubriken och de olika attributen som ingår i posten. Alla element i MFT-postens rubrik är inte omedelbart användbara för en kriminalteknisk analytiker, men i figur 4.2 illustreras fem av de element som är omedelbart användbara.
Som illustreras i figur 4.2 (som är ett utdrag ur figur 4.1) ser vi signaturen ”FILE” synlig i början av posten. Därefter ser vi sekvensnumret eller värdet, som ökas när posten allokeras eller avallokeras. Eftersom den här MFT-posten faktiskt är den första posten i MFT och hänvisar till filen ”$MFT”, är det logiskt att sekvensnumret är 1. Därefter visas länkantalet, som avser antalet kataloger som har poster för den här posten (hårda länkar gör att det här värdet ökas). Om du tittar på offset 0x38 i posten ser du att det första attributet har en identifierare på 0x10, eller 16. Slutligen ser vi flags-värdet, som berättar om posten är allokerad (om biten 0x01 är inställd) och om posten är en katalog (om biten 0x02 är inställd). Kort sagt kan vi med hjälp av dessa två värden avgöra om posten är allokerad eller raderad och om den gäller en fil eller en katalog. När huvudet analyseras kan pseudokoden för detta representeras på följande sätt:
if ($mft{flags} & 0x0001) – allocated; else unallocated/deleted
if ($mft{flags} & 0x0002) – folder/directory; else file
Det flaggningsvärde som syns i figur 4.2 är ”0x01”, vilket indikerar en allokerad fil. Ett värde på 0x00 skulle indikera en raderad fil och ett värde på 0x03 skulle indikera en allokerad katalog.
Tip
MFT-poster
MFT-poster raderas inte när de väl har skapats; nya poster läggs till i MFT:n vid behov och poster för raderade filer återanvänds.
Som tidigare nämnts är endast de första 42 bytena strukturerade; därefter består resten av MFT-posten av ett eller flera attributfält. Det finns ingen formell specifikation eller förklaring som säger att det måste finnas specifika attribut i en MFT-post, men för det mesta kan du förvänta dig att hitta ett $STANDARD_INFORMATION- och ett $FILE_NAME-attribut i de flesta MFT-poster. I det här avsnittet behandlas dessa två attribut, eftersom de ger information om tidsstämpel, vilket är värdefullt för kriminaltekniska analytiker. Vi kommer också att ta en kort titt på attributet $DATA och lämna de återstående attributen som en övning för den intresserade och nyfikna läsaren.
Huvudet för varje attribut innehåller ett 16-byte-huvud som bland annat identifierar typen av attribut, attributets totala längd och om attributet är resident i MFT-posten eller inte.
Note
MFT Metadatafiler
De första 16 posterna i MFT innehåller information om metadatafiler; alla kan dock inte användas. De som inte används lämnas i ett allokerat tillstånd och innehåller endast grundläggande information.
Med hjälp av denna huvudinformation kan vi analysera MFT-posten och extrahera värdefull information från varje attribut. Till exempel finns attributet $STANDARD_INFORMATION (som alltid är resident) för varje fil och katalogpost och har en identifierare på 0x10 (dvs. 16). Detta attribut innehåller filtiderna för MFT-posten (tre av dem i alla fall) som vi ser när vi skriver ”dir” i kommandotolken; den modifierade tiden, tiden för den senaste åtkomsten och datumet för skapandet (född) av filen eller katalogen, även kallade ”MAC”-tider. Attributet innehåller ett fjärde tidsvärde som anger när MFT-posten senast ändrades. Tillsammans kallas dessa tider för ”MACE”-tider (där ”E” hänvisar till ändringstiden för MFT-posten) eller ”MACB”-tider (där ”C” hänvisar till ändringstiden för MFT-posten).
Varning
Filtider
NTFS-filtiderna registreras i UTC-format (Universal Coordinated Time), vilket är analogt med Greenwich Mean Time. Detta gäller för alla tider; i varje MFT-post kommer en filpost troligen att ha minst 8 tider associerade med den; många gånger 12 eller fler. I FAT-filsystemet upprätthålls filtiderna i formatet lokal systemtid.
Attributet $FILE_NAME (identifierare 0x30, eller 48) återfinns också i de flesta MFT-poster för filer och kataloger; faktum är att många MFT-poster kommer att ha mer än ett $FILE_NAME-attribut. Liksom attributet $STANDARD_INFORMATION är det här attributet alltid resident och innehåller också fyra tidsvärden, men dessa tidsvärden sätts vanligtvis när filen skapas i systemet. Till skillnad från filtiderna i attributet $STANDARD_INFORMATION påverkas inte dessa filtider av normal systemaktivitet eller skadlig manipulering och kan därför användas för att fastställa indikatorer på skändlig aktivitet, och åtgärder kan vidtas för att dölja den tidpunkt då ett system infekterades. Följande kodprov (funktionen parseSIAttr()) är ett exempel på hur attributet $STANDARD_INFORMATION kan analyseras:
sub parseSIAttr {
my $si = shift;
my %si;
my ($type,$len,$res,$name_len,$name_ofs,$flags,$id,$sz_content,$ofs_content)
= unpack(”VVCCvvvvvVv”,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($content,24,8));
$si{a_time} = getTime($t0,$t1);
$si{flags} = unpack(”V”,substr($content,32,4));
return %si;
}
Tip
GetTime
Funktionen getTime() som syns i kodlistan för attributet parseSIAttr() som nyss gavs består av kod som lånats från Andreas Schuster och som översätter 64-bitars FILETIME-objektets tidsstämplar till en 32-bitars Unix-tid som kan översättas ytterligare till en tid som kan läsas av människor med hjälp av den i Perl inbyggda funktionen gmtime(). Koden ser ut på följande sätt:
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;
}
Den här koden är mycket användbar för att analysera och översätta vilket FILETIME-objekt som helst, oavsett varifrån det hämtas.
På ett normalt system kan många MFT-poster ha två $FILE_NAME-attribut: ett som innehåller filens (eller katalogens) fullständiga namn och ett som innehåller DOS, 8.3-filnamnet. Om en fil till exempel heter ”myreallylongfile.txt” kommer 8.3-filnamnet att visas som ”myreal~1.txt”. Detta behålls för kompatibilitet med äldre filsystem och sådana som inte stöder långa filnamn. Så det är inte ovanligt på ett normalt Windows-system att ha ett antal MFT-poster med två $FILE_NAME-attribut med nästan identiskt innehåll. Följande kodprov (funktionen parseFNAttr()) ger ett exempel på hur ett $FILE_NAME-attribut från en MFT-post kan analyseras och tillgängliga data extraheras:
sub parseFNAttr {
my $fn = shift;
my %fn;
my ($type,$len,$res,$name_len,$name_ofs,$flags,$id,$sz_content,$ofs_content)
= unpack(”VVCCvvvvvVv”,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($content,16,8));
$fn{m_time} = getTime($t0,$t1);
my ($t0,$t1) = unpack(”VV”,substr($content,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;
}
Det sista attributet som vi diskuterar är attributet $DATA (identifierare 0x80, eller 128). Detta attribut innehåller eller hänvisar till det faktiska innehållet i filen. Om flaggan ”nonresident” i attributhuvudet inte är inställd, finns filens innehåll i attributet $DATA i MFT-posten, efter huvudet och två ytterligare strukturer. Detta gäller i allmänhet för korta textfiler, till exempel, eller andra filer som är mindre än 700 byte. Om data inte är residenta måste ”datakörningar”, eller var data finns på disken, översättas.
Exempelkod för parsning av datakörningar i $DATA-attributet är mycket komplicerad och presenteras inte här. På samma sätt är koden för att extrahera information från residenta $DATA-attribut trivial och består av att analysera viss ytterligare information (storlek på innehållet och offset till innehållet) efter attributhuvudet.
En del verktyg med öppen källkod finns tillgängliga för att analysera MFT (särskilt attributen $STANDARD_INFORMATION och $FILE_NAME) och göra tidsstämplade data tillgängliga för analytikern. Ett av dem är David Kovars Python-skript analyzemft.py, som finns på webben på http://www.integriography.com/projects/analyzeMFT. Ett annat är mft.pl Perl-skriptet, från vilket funktionerna parseSIAttr() och parseFNAttr() hämtades, som finns tillgängligt i WinForensicAnalysis Google Code projected, som finns på webben på http://code.google.com/p/winforensicaanalysis.
Brian Carriers ”The SleuthKit” (TSK)-verktyg är troligen de mest kända verktygen för att samla in ett brett spektrum av information om filsystem och filsystemsmetadata från förvärvade bilder och till och med från levande system. För att till exempel samla in en lista över filsystemets $STANDARD_INFORMATION attributfiltider från en förvärvad bild kan en analytiker använda ett kommando som liknar följande:
C:\tsk>fls -f ntfs -m C:/ -p -r G:\case\xp.img > G:\case\files\bodyfile.txt
Detta kommando producerar vad som är känt som en ”bodyfile”, vilket är ett mellanliggande filformat som används för att lagra denna information innan den konverteras till en tidslinje för filsystemaktivitet. I vissa fall kan analytikern behöva lägga till ”-o” för att identifiera förskjutningen till den partition som på det levande systemet framstod som enheten ”C:\”; denna förskjutningsinformation kan bestämmas manuellt med hjälp av en hexeditor eller genom att använda mmls.exe.
En analytiker kan också samla in samma information från ett levande, fjärrsystem med hjälp av F-Response. Om analytikern har anslutit till fjärrsystemet på rätt sätt och har monterat systemets C:\-enhet som F:\ på sitt eget system kan han/hon sedan använda ett kommando som liknar följande för att samla in filtider för attributet $STANDARD_INFORMATION för filerna i C:\-partitionen:
C:\tsk>fls -f ntfs -m C:/ -p -r \\.\F: > g:\case\files\bodyfile.txt
Den kompletta uppsättningen TSK-verktyg, tillsammans med dokumentation och användningsinformation, finns på webben på SleuthKit-webbplatsen, http://www.sleuthkit.org.