Cada entrada da Master File Table tem 1.024 bytes dispostos da mesma forma: um cabeçalho fixo, uma pequena estrutura de reparo, depois um fluxo de atributos tipados. Este post é um olhar próximo nessa disposição — o tipo de detalhe de que você precisa quando está lendo os bytes brutos de $MFT em um editor hexadecimal ou escrevendo seu próprio parser.
A assinatura FILE
Os quatro primeiros bytes de cada registro são a string ASCII FILE (46 49 4C 45). Os parsers usam isso como âncora ao escanear um volume bruto em busca de registros órfãos: toda fronteira de 1.024 bytes que começa com FILE é um registro MFT, mesmo se o cabeçalho da própria tabela for ilegível.
Um registro cujo conteúdo o chkdsk não conseguiu reparar carrega no lugar a assinatura BAAD (42 41 41 44). O NTFS mantém esses registros no lugar em vez de apagá-los — eles preservam o número de sequência do slot — mas o resto dos bytes não deve ser confiável.
O cabeçalho do registro
Os 56 bytes após a assinatura descrevem que tipo de registro é esse e como lê-lo com segurança:
- Offset do update sequence array (2 bytes) e tamanho do array em palavras de 16 bits (2 bytes). Juntos descrevem os dados de fixup; veja abaixo.
- Número de sequência do
$LogFile(8 bytes). Aponta de volta para o log de transações para recuperação após falha. - Número de sequência (2 bytes). Incrementado toda vez que o slot do registro é reutilizado.
- Contador de hard links (2 bytes). Um por atributo
$FILE_NAME. - Offset para o primeiro atributo (2 bytes).
- Flags (2 bytes). O bit 0 é
IN_USE; o bit 1 marca um diretório. - Tamanho usado (4 bytes) e tamanho alocado (4 bytes) do registro. O alocado é sempre 1.024 em volumes padrão.
- Referência ao registro base (8 bytes). Diferente de zero em registros de extensão — slots extras usados quando os atributos de um arquivo transbordam um único registro.
- Próximo ID de atributo (2 bytes). Usado para atribuir IDs únicos a novos atributos.
- Número do registro (4 bytes, NTFS 3.1+). Autorreferência, útil para verificação de sanidade da análise.
O número de sequência é o que torna a análise de arquivos excluídos confiável. O número do registro sozinho é reutilizado; a referência de arquivo de 64 bits (número do registro mais número de sequência) não é. Uma referência que discorda da sequência atual naquele número de registro é um ponteiro para um inquilino anterior — geralmente um arquivo excluído.
O fixup array
O NTFS detecta gravações interrompidas com um pequeno truque chamado update sequence array (USA), ou fixup array. Cada registro de 1.024 bytes é também dividido em dois setores de 512 bytes. O NTFS:
- Escolhe um update sequence number (USN — não relacionado ao USN do
$UsnJrnlapesar do acrônimo compartilhado) de 16 bits. - Substitui os dois últimos bytes de cada setor de 512 bytes por esse USN antes de gravar.
- Armazena os dois últimos bytes originais de cada setor no fixup array, em ordem, logo após o próprio USN.
Na leitura, o NTFS verifica que os dois últimos bytes de cada setor coincidem com o USN. Se sim, os setores foram escritos juntos; os bytes originais são puxados do fixup array e colocados de volta no lugar. Se a cauda de algum setor não bater, a gravação foi interrompida e o registro é suspeito.
Isso significa que um parser que lê $MFT byte por byte sem aplicar os fixups vai obter lixo nos offsets 510 e 1022 de cada registro. Todo parser MFT sério aplica o fixup como primeiro passo após localizar um registro.
O fluxo de atributos
Depois do cabeçalho (e do fixup array) vêm os atributos do arquivo. Cada atributo começa com seu próprio cabeçalho curto — código de tipo, comprimento, flag residente ou não residente, nome opcional — seguido pelos dados do atributo. Os atributos são alinhados em 8 bytes, escritos um após o outro e terminados por uma sentinela 0xFFFFFFFF.
Um registro mínimo carrega três:
$STANDARD_INFORMATION(0x10) — carimbos de tempo e flags DOS.$FILE_NAME(0x30) — nome, referência ao diretório pai e um segundo conjunto de carimbos de tempo.$DATA(0x80) — o conteúdo do arquivo, residente inline para arquivos pequenos ou uma lista de cluster runs caso contrário.
Os registros podem carregar muito mais, incluindo $ATTRIBUTE_LIST quando os atributos do arquivo crescem além de um único slot de 1.024 bytes. A lista completa está na referência da Master File Table.
Por que isso importa para a forense
A combinação de um layout estável de 1.024 bytes e da assinatura FILE é o que torna o carving de arquivos NTFS excluídos possível. Mesmo que a própria $MFT tenha sumido, uma varredura do volume bruto em busca de cabeçalhos FILE recupera a maioria dos registros — incluindo os nomes, os carimbos de tempo e (para arquivos pequenos) os dados das entradas excluídas. O mecanismo de fixup significa que esses registros carvados podem ser confiados desde que o USA verifique.