A pergunta mais comum que os analistas forenses recebem de stakeholders não-técnicos é alguma variante de «consegue provar que este ficheiro existiu?». Quando o ficheiro foi eliminado do disco, a reciclagem esvaziada, e passou tempo suficiente para a entrada $MFT ter sido reutilizada para outra coisa, a resposta depende quase sempre do que o journal USN ainda recorda. O journal é, na minha experiência, a testemunha mais duradoura para «este ficheiro alguma vez existiu» depois de tudo o resto ter sido apagado.
Este artigo percorre o que o journal preserva sobre ficheiros eliminados, como extrair essa evidência, e os casos em que o journal é a sua última linha.
O que o journal guarda após a eliminação
Quando um ficheiro é eliminado em NTFS acontecem três coisas:
- A entrada
$FILE_NAMEno directório pai é desligada. OINDEX_ALLOCATIONdo directório é reescrito sem ela. - A entrada MFT é marcada como não usada mas não é zerada. O próximo ficheiro alocado a essa entrada sobrescreve os data runs, atributos e timestamps.
- O journal USN recebe um registo
FileDelete | Closea nomear o ficheiro, a sua referência ao pai, o seu número de entrada MFT e sequência, e o timestamp da eliminação.
O registo do journal é o mais resiliente dos três. A entrada do directório desaparece no momento em que o pai é reescrito — por vezes em segundos num volume ocupado. A entrada MFT pode ser reutilizada assim que um novo ficheiro for criado — por vezes em minutos. O registo do journal fica num buffer circular que só rota fim ao fim ao fim de dias ou semanas.
Para ficheiros eliminados há dias, o journal dá-lhe tipicamente:
- O nome do ficheiro como folha UTF-16 LE. Apenas a folha, sem caminho.
- O número de referência MFT do directório pai. Combinado com um
$MFTparseado, resolve para um caminho. - O timestamp de eliminação em FILETIME UTC.
- O número de entrada e número de sequência MFT que o ficheiro ocupava. Útil para cruzar com artefactos carved e before-images do
$LogFile. - Um traço do ciclo de vida. Os registos
FileCreate,DataExtend,BasicInfoChangee renames no mesmoFileReferenceNumberdizem quando o ficheiro foi criado, como foi escrito e se os seus timestamps foram modificados antes da eliminação.
Um quádruplo — referência MFT, nome de ficheiro, referência do pai, FILETIME da eliminação — mais um evento de criação anterior no mesmo journal, é normalmente suficiente para satisfazer uma retenção legal ou ancorar uma investigação mais profunda. Na maior parte das vezes também se obtém o registo FileCreate do mesmo $J, o que dá a idade do ficheiro e um timestamp de criação independente do $STANDARD_INFORMATION.
Um fluxo mínimo de recuperação
Com um journal parseado e um $MFT parseado (ver o guia de extracção para ambos):
- Filtre por
FileDeletena janela temporal de interesse. Ordene por timestamp. Esta é a sua lista mestra de eliminações a triar. - Agrupe por
FileReferenceNumberpara qualquer eliminação que importe. Obtém o histórico completo do ficheiro: criação, escritas, pares de rename, alterações de atributos e, por fim, o delete. - Resolva o caminho pai via
$MFT. O parser desta página fá-lo automaticamente quando ambos os ficheiros são fornecidos. Sem$MFTpára no nome de ficheiro folha. - Cruze com
$LogFilese a eliminação for muito recente. Pode ainda conter a imagem «before» da entrada do directório, dando uma segunda testemunha independente da existência do ficheiro.
A combinação «referência MFT, nome do ficheiro, caminho pai, timestamp de criação, timestamp de eliminação, traço completo do ciclo de vida» é normalmente suficiente para escrever um relatório defensável.
Quando o caminho pai não pode ser resolvido
Por vezes a entrada MFT do pai foi também já reciclada quando olha — comum em hosts com filesystem muito activo, particularmente file servers e CI runners. O journal continua a dar-lhe o nome do ficheiro e o número de referência do pai, mas o $MFT já não sabe a que pasta essa referência apontava.
Três alternativas costumam destravar o caminho:
Registos RenameNewName anteriores na mesma referência de pai. Agrupe todos os registos do journal por referência de pai. Qualquer RenameNewName anterior cujo novo pai coincide com a sua referência não resolvida e cujo próprio caminho resolve diz-lhe a que pasta essa referência costumava corresponder.
Entradas de índice no $LogFile. O log de recuperação de crash guarda before-images das actualizações INDEX_ALLOCATION. O libfsntfs de Joachim Metz e o LogFileParser de Jonas Schicht extraem-nas. Numa eliminação suficientemente recente, a before-image da entrada do directório ainda está no $LogFile e resolve para um caminho.
Ficheiros irmãos na mesma referência de pai. Agrupe todos os registos do journal por referência de pai. Se um dos irmãos foi renomeado para dentro de um directório cuja entrada MFT ainda é válida, pivote por aí: o pai antigo no momento do rename é a sua pasta desconhecida.
Quando nenhuma destas funciona, o parser mostra o ficheiro como «filename: notes.docx, parent: 1234-5» sem caminho resolvido. Isso é intencional. Inventar um caminho que não pode verificar é pior do que admitir que está em falta.
«Apagado» não significa desaparecido
Ferramentas de shredding — apagar seguro do CCleaner, Eraser, BleachBit, sdelete — sobrescrevem o conteúdo do ficheiro e depois eliminam-no. Deixam um rasto mais barulhento no journal, e não mais silencioso:
- Vários registos
DataOverwrite | Closeno ficheiro antes do seuFileDelete | Closeindicam sobrescrita intencional de conteúdo. Uma eliminação normal não produz overwrites. - Um
FileCreatemaisDataOverwritemaisFileDeleteno mesmo ficheiro em segundos é a assinatura canónica de destruição de evidências. - Quando o shredder também limpou espaço slack escrevendo e depois eliminando ficheiros de enchimento, esses ficheiros têm as suas próprias sequências create/extend/overwrite/delete — um enxame de registos em redor do momento da destruição.
O mapeamento MITRE ATT&CK é T1485 Data Destruction para a sobrescrita de conteúdo e T1070.004 File Deletion para a eliminação em si. Num host onde suspeita de destruição deliberada de evidências, o journal frequentemente dá-lhe um timestamp mais apertado do que qualquer outro artefacto.
E quanto ao conteúdo do ficheiro
O journal USN nunca transporta conteúdo. Apenas metadados sobre operações. Se precisa de bytes de volta, o journal aponta-lhe os locais onde procurar:
- O número da entrada MFT do ficheiro eliminado. Se a entrada não foi reutilizada,
$MFTainda contém os data runs e o conteúdo pode ser recuperável via oicatdo The Sleuth Kit ou X-Ways. - As before-images do
$LogFilepara eliminações muito recentes. - Volume Shadow Copies (VSS) se existirem no host. O ficheiro eliminado pode estar num snapshot anterior.
vssadmin list shadowsnum host activo ouvshadowmountdo libyal numa imagem fazem-nos aparecer. - Stores específicos da aplicação. A reciclagem online do OneDrive, a pasta «Autosaved» do Office sob
\Users\<u>\AppData\Roaming\Microsoft\Office\UnsavedFiles\, caches dos browsers (as ferramentas forenses de browser cobrem isto), cópias staged em OST/PST do Outlook. - O pagefile e um dump de RAM se o ficheiro tiver sido aberto recentemente o suficiente.
O papel do journal é dizer-lhe que um ficheiro existiu e quando foi eliminado. A recuperação de conteúdo é a jusante.
Limites práticos
Janela do buffer circular. Ficheiros eliminados antes de o journal ter passado por cima do registo mais antigo visível desapareceram deste artefacto. Puxe $LogFile e shadow copies como complementos.
Operações que não atingem o journal. Alterações de cifragem ao nível do filesystem que só actualizam atributos, escritas em região esparsa que tocam apenas no mapa de alocação, e algumas manipulações de reparse-point NTFS podem não produzir registos DataExtend ou DataOverwrite. O journal vê o que o NTFS decide registar.
FileDelete sem FileCreate anterior. Significa que o ficheiro foi criado antes do registo mais antigo actual do journal. O seu ciclo de vida em $J é parcial, mas o timestamp da eliminação e a referência do pai ainda ancoram um relatório.
Partilhas montadas por bind ou volume. Se os dados vivem num filesystem remoto, o journal no seu host conhece apenas handles locais. Puxe o journal do filesystem que realmente os hospeda.
Leituras adicionais
- Microsoft Learn — Change Journals cobre a superfície de API e o ciclo de vida que produz registos
FileDelete. - Páginas man do The Sleuth Kit —
icateflspara recuperação de conteúdo contra entradas MFT ainda alocadas. - SANS DFIR — o poster Windows Forensic Analysis coloca o journal em contexto com
$LogFile, Volume Shadow Copies e outros artefactos de recuperação de eliminações numa única página. - O libfsntfs de Joachim Metz — a referência aberta para extracção de before-images do
$LogFilequando a eliminação é recente e a entrada do directório ainda não foi sobrescrita noutro lado.