Índices de diretórios ($I30)¶
O que é o $I30¶
Todo diretório NTFS mantém um índice dos arquivos que contém, chamado $I30. Um diretório pequeno o mantém em
seu registro do $MFT ($INDEX_ROOT); um maior também tem registros INDX, geralmente de 4.096 bytes cada, em
um fluxo $INDEX_ALLOCATION:$I30. Cada entrada de índice contém uma cópia do $FILE_NAME do arquivo: seu
nome, a referência MFT, o diretório pai, quatro carimbos de data/hora e dois tamanhos, conforme a última vez que o NTFS
atualizou a entrada.
Quando um arquivo é excluído ou renomeado para fora de um diretório, o NTFS remove sua entrada e desloca as entradas
seguintes. Os bytes antigos permanecem no slack do registro INDX, além das entradas em uso, até que
entradas posteriores os sobrescrevam. O slack de índice pode preservar o nome, os horários e o tamanho de um arquivo cujo
registro do $MFT foi reutilizado e cujos registros do Diário USN já foram descartados pela rotação.
Melhor conclusão: um nome encontrado no slack de índice esteve, em algum
momento, no índice deste diretório com os horários e tamanhos de $FILE_NAME indicados. Uma entrada de slack não
informa quando foi removida, nem se foi excluída, renomeada ou deslocada por rebalanceamento.
Localização e coleta¶
O $I30 é metadado do NTFS: colete-o com uma ferramenta forense com acesso bruto ao disco que consiga exportar o fluxo
$I30 de um diretório (os arquivos exportados costumam se chamar $I30). O Juntei também pode procurar registros INDX em uma imagem de disco ou
em espaço não alocado. Colete também o $MFT e o $J do mesmo volume, para determinar o que
eram as entradas de slack.
Cuidados para o analista¶
- O slack de índice é parcial e desordenado. As entradas são sobrescritas à medida que o diretório muda; um nome ausente não prova nada.
- Muitas entradas de slack são cópias de entradas ainda em uso, deixadas quando as entradas se deslocam.
CopyOfEntryInUseas marca. O mesmo nome excluído também pode aparecer no slack várias vezes. - Os horários em uma entrada de índice são horários de
$FILE_NAMEconforme a última atualização da entrada. Eles podem diferir tanto dos horários de$STANDARD_INFORMATIONquanto dos de$FILE_NAMEdo registro do$MFTdo arquivo. AllocatedSizeeRealSizetambém refletem a última atualização da entrada e podem estar desatualizados.- O
FileEntry(ouParentEntry) de uma entrada de slack pode estar ausente quando bytes posteriores o sobrescreveram. Quando presente, o registro MFT que ele indica pode ter sido reutilizado desde então: compare o número de sequência. parse-ntfs i30lê registros INDX. O índice de um diretório pequeno existe apenas em seu registro do$MFT($INDEX_ROOT); seus arquivos estão no$MFT.
Analisar com o Juntei¶
Usage: juntei parse-ntfs i30 <INPUT> [OPTIONS]
Input:
-d, --directory <DIR> Recursively find $I30 files (with $I30 in their name, or starting with an INDX record)
-f, --file <FILE> Parse one $I30 stream, or any file holding INDX records (a disk image, unallocated space)
Filtering:
--slack-only Only the entries found in slack
--no-copies Leave out the slack entries that copy an entry in use
Output:
-o, --output <FILE> Save every entry
-t, --output-type <TYPE> csv, json, or jsonl
juntei parse-ntfs i30 -f 'Users_$I30'
juntei parse-ntfs i30 -d evidence/ -o i30.csv
juntei parse-ntfs i30 -f 'Users_$I30' --slack-only --no-copies -t jsonl
juntei parse-ntfs i30 -f disk.raw -o carved-i30.csv
O resumo lista os registros INDX (e quantos foram gravados parcialmente), as entradas em uso e no slack, e os nomes das entradas de slack que não são cópias exatas de entradas em uso. Esses nomes são candidatos a arquivos excluídos ou renomeados, e não um veredito por si sós.
Campos de saída CSV¶
| Campo | Interpretação |
|---|---|
SourcePath |
Arquivo de entrada; distingue hosts e diretórios. |
RecordOffset, EntryOffset |
Deslocamentos em bytes do registro INDX e da entrada na entrada analisada. Essenciais para a validação e para registros encontrados em imagens de disco. |
RecordVCN, RecordLSN |
A posição do registro no fluxo de índice e seu número de sequência do $LogFile. |
FromSlack |
True para uma entrada encontrada além das entradas em uso. |
CopyOfEntryInUse |
Entrada de slack com o mesmo nome, namespace, arquivo (quando conhecido), pai e horários de uma entrada em uso do mesmo índice de diretório. Geralmente é uma sobra do deslocamento de entradas, não um arquivo excluído. |
Filename |
O nome no diretório. |
Namespace |
win32, dos (nome curto 8.3), win32_and_dos ou posix. |
FileEntry, FileSequence |
A referência MFT do arquivo. Vazio para uma entrada de slack cujo cabeçalho foi sobrescrito. |
ParentEntry, ParentSequence |
A referência MFT do diretório. Vazio quando outros bytes a sobrescreveram. |
CreatedUTC, ModifiedUTC, MFT-ModifiedUTC, AccessedUTC |
Horários de $FILE_NAME, com precisão de 100 ns, conforme a última atualização da entrada. |
AllocatedSize, RealSize |
Tamanhos que o NTFS copiou para a entrada; veja os cuidados acima. |
FileAttributes |
Nomes de atributos unidos por | (hidden|archive); is_directory para um subdiretório. Os bits que esta versão do Juntei não nomeia são mantidos em hexadecimal (0x00800000). |
ReparseValue |
Tag de reparse ou tamanho dos atributos estendidos, a partir de $FILE_NAME. |
Problems |
Danos no registro, como setores gravados parcialmente. Entradas de um registro danificado ainda merecem análise, com cuidado. |
JSON/JSONL têm os mesmos campos em snake_case, com problems como lista e null para valores
desconhecidos.
Como as entradas de slack são encontradas¶
O slack é varrido em cada limite de 8 bytes, onde as entradas começam, em busca de entradas inteiras, de
atributos $FILE_NAME cujo cabeçalho de entrada foi sobrescrito e, no início do slack, de um
$FILE_NAME cuja referência ao pai foi sobrescrita pelo final das entradas em uso. Um candidato precisa se parecer
com o que o Windows grava: um nome UTF-16 válido sem caracteres de controle nem separadores de caminho, quatro
horários entre 1980 e 2100, um namespace conhecido e flags de atributo conhecidas. Uma referência ao pai acima de
32 bits indica bytes que a sobrescreveram e é deixada vazia.
A matriz de sequência de atualização (update sequence array) de cada registro é aplicada. Um setor que não termina com o valor da sequência de atualização
foi gravado parcialmente; o Juntei lê o registro como está e indica os setores em Problems.
Estratégia de investigação¶
- Comece pelos nomes no slack que não são cópias, listados no resumo, e depois filtre com
--slack-only --no-copies. - Procure o
FileEntryno$MFT. O mesmoFileSequencesignifica o mesmo arquivo; um valor maior significa que o registro foi liberado desde então e, talvez, reutilizado. - Pesquise o nome no Diário USN para saber quando ele foi excluído ou renomeado.
- Compare os horários de
$FILE_NAMEcom os horários de$STANDARD_INFORMATIONdo$MFTpara detectar timestomping. - Correlacione com Prefetch, LNK, Jump Lists e logs de eventos para saber como o arquivo foi usado.
Mais detalhes¶
- Microsoft: Master File Table
- libfsntfs: documentação do formato NTFS
- dfir_ntfs
- INDXRipper
- ys-ntfs-parser (o módulo
i30do seu cratemft)