← Voltar ao blog

Detectar timestomping e antiforense no journal USN

Atacantes que editam timestamps do MFT não conseguem se esconder do change journal. Como as discrepâncias $STANDARD_INFORMATION vs $FILE_NAME e os BasicInfoChange inesperados expõem a atividade antiforense.

5 min de leitura

Operadores sofisticados não apenas apagam as evidências — eles tentam camuflar o que deixam. A técnica mais comum é o timestomping: editar os timestamps NTFS de um arquivo para que pareça inocente (ou fora da janela de investigação). Costumava funcionar. Com o journal USN ligado, deixa um sinal claro.

Este artigo descreve o que o timestomping faz ao disco, como o journal o expõe e quais outras manobras antiforenses você pega com o mesmo artefato.

Lembrete rápido sobre timestamps NTFS

Cada entrada MFT carrega timestamps em dois atributos:

  • $STANDARD_INFORMATION (SI): os timestamps que ferramentas userland e a maioria das APIs podem alterar. O que dir, o Explorador e Get-ChildItem mostram. Formato documentado na referência NTFS da Microsoft.
  • $FILE_NAME (FN): os timestamps que o NTFS define internamente em cada atributo $FILE_NAME. Tipicamente um por nome (o arquivo pode ter vários nomes se hard-linked). Eles são bem mais difíceis de mudar — exigem acesso de kernel ou ferramentas especializadas.

Ferramentas de timestomping (SetMACE, o histórico timestomp.exe do módulo antiforense do Metasploit, vários implantes customizados) costumam mirar os timestamps SI. Algumas hoje também miram FN. De qualquer modo, tocam no MFT — e esse toque acende o journal.

O que o journal registra para uma edição de timestamp

Quando os timestamps SI são gravados, o NTFS emite um registro BasicInfoChange | Close. Esse registro é a evidência cabal, porque:

  • Um «touch» legítimo produz um BasicInfoChange | Close junto com um DataExtend ou DataOverwrite da gravação real que disparou a atualização dos timestamps.
  • Um timestomp produz um BasicInfoChange | Close nu, sem gravação anterior no mesmo FileReferenceNumber.

Quando você vê BasicInfoChange | Close sem DataOverwrite, DataExtend ou FileCreate na mesma sessão de handle, está vendo manipulação de metadados — quase sempre timestomping ou mudanças de atributo (flags read-only/hidden).

A comparação clássica: SI vs FN

A detecção de timestomping mais autoritativa compara, para cada arquivo, os timestamps $STANDARD_INFORMATION com os timestamps $FILE_NAME. Os investigadores da Mandiant escrevem sobre isso há anos; o white paper histórico da Mandiant sobre timestomping é a referência, e Brian Carrier trata o tema em File System Forensic Analysis.

O journal complementa em vez de substituir a comparação:

  • A comparação MFT diz que o timestomping ocorreu em algum momento. Não consegue dizer quando.
  • Os BasicInfoChange | Close do journal dizem exatamente quando a gravação SI ocorreu, e qual contexto de processo a cercou (acoplado com Security.evtx 4663).

Um arquivo timestompado aparece assim nos seus dados:

  1. A comparação MFT sinaliza SI < FN (ou SI no futuro de FN etc.).
  2. O journal tem um BasicInfoChange | Close em, digamos, 2026-04-12 03:08:14 sem gravações ao redor.
  3. Esse timestamp é o que você coloca no relatório.

$LogFile e journal em desacordo sobre gravações MFT

O journal registra gravações em nível de arquivo; $LogFile registra as transações MFT subjacentes. Um timestomp produz:

  • Uma transação de gravação MFT em $LogFile (modifica $STANDARD_INFORMATION da entrada alvo).
  • Um BasicInfoChange | Close no journal.

Se você encontrar uma transação de atualização MFT em $LogFile sem um BasicInfoChange | Close correspondente no journal, o operador pode ter apagado o registro do journal — possível via fsutil usn deletejournal seguido de createjournal, o que deixa rastros próprios.

Outras manobras antiforense que o journal pega

Desabilitar o journal

fsutil usn deletejournal /D /N C: remove o journal. Após a chamada:

  • O arquivo journal é reconstruído vazio. Registros anteriores foram embora.
  • A entrada MFT de $UsnJrnl é regravada — $LogFile registra a transação.
  • Security.evtx, se havia SACLs configuradas, registra um Sensitive Privilege Use para SeRestorePrivilege ou SeManageVolumePrivilege.

O journal não pode dizer o que ele continha, mas o ato em si de desabilitá-lo já é sinal forte de antiforense. Ver a referência fsutil usn da Microsoft para os comandos de gestão e seus pré-requisitos de privilégio.

Fluxos de dados alternativos

Esconder em ADS é mais velho que eu, e o journal registra direito: um bit de razão StreamChange dispara quando um fluxo alternativo é adicionado ou removido. Filtrar StreamChange faz emergir cada evento de create/modify de ADS no volume. Falsos positivos incluem fluxos Zone.Identifier legítimos dos downloads do navegador — também produzem StreamChange, pareados com o FileCreate do arquivo original.

Truques com hard link

HardLinkChange dispara quando hard links são adicionados ou removidos. Operadores às vezes os usam para tornar um arquivo acessível por dois pais — útil para escapar de controles baseados em caminho. Rastrear HardLinkChange e pivotar em FileReferenceNumber para ver todos os pais.

Abuso de reparse points

Reparse points (junctions, links simbólicos, mount points) podem redirecionar um caminho para outro lugar. ReparsePointChange acende quando um é adicionado ou modificado. Buscar reparse points em $Recycle.Bin, \Users\Default ou outras localizações «não-deveriam-ser-tocadas».

O que você não pega assim

Uma lista curta de manobras antiforense que escapam totalmente do journal:

  • Dar boot em mídia externa e regravar o disco — nunca tocou o SO ativo.
  • Regravações em userland preservando o mesmo tamanho de conteúdo (overwrite no mesmo offset, sem atualização SI). Produzem registros DataOverwrite mas perdem o conteúdo original. O journal vê a gravação, não o que havia antes.
  • Desabilitar o journal antes de o operador fazer qualquer outra coisa. O journal só consegue registrar o que aconteceu enquanto estava ligado.

Para esses, você precisa ou de $LogFile, ou shadow copies, ou telemetria fora do host. O journal é uma testemunha forte, não a única.

Uma varredura prática

O filtro mais rápido para timestomping em um journal parseado:

  1. Filtrar registros com razão exatamente BasicInfoChange | Close.
  2. Para cada um, olhar os 5 minutos anteriores de registros na mesma FileReferenceNumber. Se não houver DataOverwrite, DataExtend, FileCreate ou rename, marcar.
  3. Para as entradas marcadas, calcular o delta SI-vs-FN no MFT. Ordenar pelo maior delta.

No topo da lista costuma estar seu timestomping. As entradas restantes são operações como o Explorador alternando «Oculto» ou scripts que tocam atributos — dependentes de contexto, mas raramente interessantes para uma investigação típica.