MFT
A fonte mais notável de informações valiosas para um analista do sistema de arquivos NTFS é a Tabela de arquivo mestre (MFT). A localização do sector de arranque do MFT pode ser encontrada no sector de arranque do disco, e cada ficheiro e directório no volume tem uma entrada no MFT. Cada entrada MFT tem um tamanho de 1024 bytes, tornando o MFT muito simples de analisar. Cada registro MFT, ou entrada, começa com a string ASCII “FILE” (se houver um erro na entrada, ela começará com “BAAD”) e consiste em um ou mais (na maioria das vezes, mais) atributos, cada um com seu próprio identificador e estrutura. A Figura 4.1 ilustra uma parte de uma entrada MFT.
Os primeiros 42 bytes de cada entrada MFT compreendem uma estrutura de cabeçalho com 12 elementos, e os 982 bytes restantes dependem em grande parte dos valores dentro do cabeçalho e dos vários atributos contidos na entrada. Nem todos os elementos dentro do cabeçalho da entrada MFT são imediatamente úteis para um analista forense; contudo, a Figura 4.2 ilustra cinco dos elementos que são imediatamente úteis.
Como ilustrado na Figura 4.2 (que é uma porção extraída da Figura 4.1), vemos a assinatura “FILE” visível no início do registro. Depois vemos o número de sequência ou valor, que é incrementado quando a entrada é alocada ou não alocada. Como esta entrada MFT em particular é na verdade o primeiro registro dentro do MFT e se refere ao arquivo “$MFT”, é lógico que o número de seqüência é 1. Em seguida é a contagem do link, que se refere ao número de diretórios que têm entradas para este registro (links rígidos fazem com que este valor seja incrementado). A seguir é o offset com o registro para o primeiro atributo; se você olhar o offset 0x38 dentro do registro, você verá que o primeiro atributo tem um identificador de 0x10, ou 16. Finalmente, vemos o valor do flags, que nos diz se a entrada está atribuída (se o bit 0x01 está definido) e se a entrada é um directório (se o bit 0x02 está definido). Em suma, a partir destes dois valores, podemos determinar se a entrada é atribuída ou eliminada, e se é para um ficheiro ou directório. Quando o cabeçalho é analisado, o pseudocódigo para isso pode ser representado da seguinte forma:
if ($mft{flags} & 0x0001) – alocado; caso contrário, não alocado/apagado
if ($mft{flags} & 0x0002) – pasta/diretório; caso contrário, arquivo
O valor de flags visível na Figura 4.2 é “0x01”, que indica um arquivo alocado. Um valor de 0x00 indicaria um arquivo excluído, e um valor de 0x03 indicaria um diretório alocado.
Tip
MFT Records
MFT records não são excluídos uma vez que foram criados; novos registros são adicionados ao MFT conforme necessário, e registros para arquivos excluídos são reutilizados.
Como mencionado anteriormente, apenas os primeiros 42 bytes são estruturados; depois disso, o resto da entrada MFT é composto por um ou mais campos de atributos. Não há nenhuma especificação ou declaração formal que diga que precisa haver atributos específicos dentro de uma entrada MFT, mas para a maioria das entradas MFT, você pode esperar encontrar uma $STANDARD_INFORMATION e um atributo $FILE_NAME na maioria das entradas MFT. Esta seção analisa esses dois atributos, pois eles fornecem informações de carimbo de tempo, o que é valioso para os analistas forenses. Também vamos dar uma breve olhada no atributo $DATA e deixar os atributos restantes como um exercício para o leitor interessado e curioso.
O cabeçalho de cada atributo contém um cabeçalho de 16 bytes, que identifica o tipo de atributo, o comprimento total do atributo, e se o atributo é residente na entrada MFT ou não, entre outros elementos.
Nota
Arquivos de Metadados MFT
As primeiras 16 entradas do MFT contêm informações sobre arquivos de metadados; no entanto, nem todas podem ser utilizadas. Aqueles que não são utilizados são deixados em um estado alocado e contêm apenas informações básicas.
Usando esta informação de cabeçalho, podemos analisar através da entrada MFT e extrair informações valiosas de cada atributo. Por exemplo, o atributo $STANDARD_INFORMATION (que é sempre residente) existe para cada entrada de arquivo e diretório e tem um identificador de 0x10 (i.e., 16). Este atributo contém os tempos de arquivo para a entrada MFT (bem, três deles, de qualquer forma) que vemos quando digitamos “dir” no prompt de comando; a hora modificada, a última hora acessada, e a data de criação (nascimento) do arquivo ou diretório, também chamada de “MAC” times. O atributo contém um quarto valor de tempo que especifica a última vez que a entrada MFT foi alterada. Todos juntos, estes tempos são referidos como “MACE” (com o “E” referindo-se ao tempo de modificação do registo MFT) ou “MACB” (com o “C” referindo-se ao tempo de modificação do registo MFT) tempos.
Aviso
Tempos de arquivo
Tempos de arquivo NTFS são registados no formato Universal Coordinated Time (UTC), que é análogo ao Greenwich Mean Time (Tempo Médio de Greenwich). Isto é verdade para todos os tempos; em cada entrada MFT, um registro de arquivo provavelmente terá pelo menos 8 vezes associado a ele; muitas vezes, 12 ou mais. No sistema de arquivo FAT, os tempos de arquivo são mantidos no formato de hora local do sistema.
O atributo $FILE_NAME (identificador 0x30, ou 48) também é encontrado com a maioria das entradas de arquivo e diretório MFT; na verdade, muitas entradas MFT terão mais de um atributo $FILE_NAME. Como o atributo $STANDARD_INFORMATION, este atributo é sempre residente e também contém quatro valores de tempo; no entanto, estes valores de tempo são normalmente definidos quando o arquivo é criado no sistema. Ao contrário dos tempos de arquivo no atributo $STANDARD_INFORMATION, estes tempos de arquivo não são afetados pela atividade normal do sistema ou adulteração maliciosa e podem, portanto, ser usados para determinar indicadores de atividade nefasta, e passos podem ser tomados para ofuscar o tempo quando um sistema foi infectado. A seguinte amostra de código (função parseSIAttr()) fornece um exemplo de como o atributo $STANDARD_INFORMATION pode ser analisado:
sub parseSIAttr {
my $si = shift;
my %si;
meu ($type,$len,$res,$name_len,$name_ofs,$flags,$id,$sz_content,$ofs_content)
= desempacotar(“VVCCvvvvvv”,substr($si,0,22));
meu $content = substr($si,$ofs_content,$sz_content);
my ($t0,$t1) = desempacotar(“VV”,substr($content,0,8));
$si{c_time} = getTime($t0,$t1);
my ($t0,$t1) = desempacotar(“VV”,substr($content,8,8));
$si{m_time} = getTime($t0,$t1);
my ($t0,$t1) = desempacotar(“VV”,substr($content,16,8));
$si{mft_m_time} = getTime($t0,$t1);
my ($t0,$t1) = desempacotar(“VV”,substr($content,24,8));
$si{a_time} = getTime($t0,$t1);
$si{flags} = desempacotar(“V”,substr($content,32,4));
return %si;
}
Tip
GetTime
A função getTime() vista dentro da lista de códigos para o atributo parseSIAttr() que acaba de ser dado consiste em código emprestado de Andreas Schuster que traduz os carimbos de tempo do objeto FILETIME de 64 bits em um tempo Unix de 32 bits que pode ser traduzido para um tempo legível humano através da função Perl built-in gmtime(). Esse código aparece da seguinte forma:
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;
}
Este código é muito útil para analisar e traduzir qualquer objecto FILETIME, independentemente de onde é extraído.
Num sistema normal, muitas entradas MFT podem ter dois atributos $FILE_NAME: um para guardar o nome completo do ficheiro (ou directório) e outro para guardar o DOS, 8.3 nome do ficheiro. Por exemplo, se um arquivo é chamado “myreallylongfile.txt”, o nome do arquivo 8.3 aparecerá como “myreal~1.txt”. Isto é mantido para compatibilidade com sistemas de arquivo antigos e aqueles que não suportam nomes de arquivo longos. Portanto, não é incomum em um sistema Windows normal ter um número de entradas MFT com dois atributos $FILE_NAME com conteúdo quase idêntico. A seguinte amostra de código (função parseFNAttr()) fornece um exemplo de como um atributo $FILE_NAME de uma entrada MFT pode ser analisado e os dados disponíveis podem ser extraídos:
sub parseFNAttr {
meu $fn = shift;
meu %fn;
meu ($type,$len,$res,$name_len,$name_ofs,$flags,$id,$sz_content,$ofs_content)
= desempacotar(“VVCCvvvvvv”,substr($fn,0,22));
meu $content = substr($fn,$ofs_content,$sz_content);
$fn{parent_ref} = desembalar(“V”,substr($content,0,4));
$fn{parent_seq} = desembalar(“v”,substr($content,6,2));
my ($t0,$t1) = desempacotar(“VV”,substr($content,8,8));
$fn{c_time} = getTime($t0,$t1);
my ($t0,$t1) = desempacotar(“VV”,substr($content,16,8));
$fn{m_time} = getTime($t0,$t1);
my ($t0,$t1) = desempacotar(“VV”,substr($content,24,8));
$fn{mft_m_time} = getTime($t0,$t1);
my ($t0,$t1) = desempacotar(“VV”,substr($content,32,8));
$fn{a_time} = getTime($t0,$t1);
$fn{flags} = desempacotar(“V”,substr($content,56,4));
$fn{len_name} = desempacotar(“C”,substr($content,64,1));
$fn{namespace} = desempacotar(“C”,substr($content,65,1));
$fn{len_name} = $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;
}
O atributo final que discutimos é o atributo $DATA (identificador 0x80, ou 128). Este atributo contém ou se refere ao conteúdo real do arquivo. Se o flag não residente no cabeçalho do atributo não estiver definido, então o conteúdo do arquivo é residente dentro do atributo $DATA da entrada MFT, seguindo o cabeçalho e duas estruturas adicionais. Isto é geralmente verdade para arquivos de texto curto, por exemplo, ou outros arquivos com menos de 700 bytes. Se os dados são não residentes, então “data runs”, ou onde os dados estão localizados no disco, precisam ser traduzidos.
Código de exemplo para analisar as execuções de dados do atributo $DATA está muito envolvido e não é apresentado aqui. Similarmente, código para extrair informação de atributos $DATA residentes é trivial e consiste em analisar algumas informações adicionais (tamanho do conteúdo e offset para conteúdo) após o cabeçalho do atributo.
Algumas ferramentas de código aberto estão disponíveis para analisar o MFT (especificamente, atributos $STANDARD_INFORMATION e $FILE_NAME) e disponibilizar dados com carimbo de data/hora para o analista. Uma delas é o script analyzemft.python de David Kovar, encontrado na Web em http://www.integriography.com/projects/analyzeMFT. Outro é o script mft.pl Perl, do qual foram extraídas as funções parseSIAttr() e parseFNAttr(), que está disponível no WinForensicAnalysis Google Code projectado, localizado na Web em http://code.google.com/p/winforensicaanalysis.
Brian Carrier’s “The SleuthKit” (TSK) tools are probably the best known tools for collect a wide range of file system and file system metadata information from acquired images and even live systems. Por exemplo, para coletar uma listagem de tempos de arquivo do sistema de arquivos $STANDARD_INFORMATION de uma imagem adquirida, um analista pode usar um comando similar ao seguinte:
C:\tsk>fls -f ntfs -m C:/ -p -r G:\case\xp.img > G:\case\files\bodyfile.txt
Este comando produz o que é conhecido como um “bodyfile”, que é um formato de arquivo intermediário usado para armazenar esta informação antes de convertê-la para uma linha de tempo de atividade do sistema de arquivos. Em alguns casos, o analista pode precisar adicionar a chave “-o” para identificar o offset na partição que apareceu no sistema live como a unidade “C:\”; esta informação de offset pode ser determinada manualmente através de um editor hexadecimal ou usando mmls.exe.
Um analista também pode coletar esta mesma informação de um sistema live, remoto, usando F-Response. Se o analista se conectou corretamente ao sistema remoto e montou a unidade C:\ do sistema como F:\ em seu próprio sistema, ele pode então usar um comando similar ao seguinte para coletar os tempos dos arquivos do atributo $STANDARD_INFORMATION para os arquivos na partição C:\:
C:\tsk>fls -f ntfs -m C:/ -p -r \\.\F: > g:\case\files\bodyfile.txt
O conjunto completo de ferramentas TSK, juntamente com documentação e informações de uso, pode ser encontrado na Web no site do SleuthKit, http://www.sleuthkit.org.