Cómo crear un informe de integridad de archivos en PowerShell
Este tutorial muestra cómo crear un informe de integridad de archivos en PowerShell para verificar cambios en archivos críticos. La solución genera y guarda hashes (SHA256) de archivos, compara versiones posteriores y resalta archivos añadidos, eliminados o modificados — útil para auditorías, detección de cambios no autorizados y copias de seguridad verificadas.
Requisitos previos
- Windows con PowerShell 5.1 o PowerShell 7+
- Permisos de lectura para la carpeta a comprobar
- Una carpeta de informes donde guardar el archivo de referencia (JSON o CSV)
Paso 1: Concepto y estructura del informe
Es importante entender qué vamos a registrar: para cada archivo guardamos la ruta relativa, el tamaño, la fecha de última modificación y el hash SHA256. El formato JSON es sencillo de leer y fácil de comparar. El archivo de referencia se llamará file-integrity.json.
Paso 2: Script para generar el informe inicial
Este script crea el informe inicial con todos los archivos de la carpeta objetivo. Ejecútalo desde la carpeta padre o proporciona una ruta completa para $RootPath.
$RootPath = 'C:\PastaASeguir' # Alterar para a pasta a verificar
$ReportFile = 'C:\Relatorios\file-integrity.json' # Onde guardar o relatório
Get-ChildItem -Path $RootPath -Recurse -File | ForEach-Object {
$relative = $_.FullName.Substring($RootPath.Length).TrimStart('\')
$hash = Get-FileHash -Path $_.FullName -Algorithm SHA256
[PSCustomObject]@{
Path = $relative
Size = $_.Length
LastWriteTime = $_.LastWriteTimeUtc
Hash = $hash.Hash
}
} | ConvertTo-Json -Depth 4 | Out-File -FilePath $ReportFile -Encoding UTF8
Write-Output "Relatório inicial gerado em: $ReportFile"
Paso 3: Script para comparar el estado actual con el informe
Este script carga el informe anterior, analiza el estado actual de la carpeta e identifica archivos Added, Removed y Modified. También guarda un nuevo informe con timestamp para historial.
$RootPath = 'C:\PastaASeguir'
$ReportFile = 'C:\Relatorios\file-integrity.json'
$NowReport = "C:\Relatorios\file-integrity-$(Get-Date -Format 'yyyyMMdd-HHmmss').json"
# Carregar relatório anterior
if (-Not (Test-Path $ReportFile)) { throw "Relatório anterior não encontrado: $ReportFile" }
$old = Get-Content $ReportFile -Raw | ConvertFrom-Json
$oldIndex = @{ }
foreach ($item in $old) { $oldIndex[$item.Path] = $item }
# Criar relatório atual em memória
$current = @()
Get-ChildItem -Path $RootPath -Recurse -File | ForEach-Object {
$relative = $_.FullName.Substring($RootPath.Length).TrimStart('\')
$hash = Get-FileHash -Path $_.FullName -Algorithm SHA256
$current += [PSCustomObject]@{
Path = $relative
Size = $_.Length
LastWriteTime = $_.LastWriteTimeUtc
Hash = $hash.Hash
}
}
# Index current
$currentIndex = @{ }
foreach ($item in $current) { $currentIndex[$item.Path] = $item }
# Detetar Added, Removed, Modified
$added = @()
$removed = @()
$modified = @()
foreach ($path in $currentIndex.Keys) {
if (-Not $oldIndex.ContainsKey($path)) { $added += $currentIndex[$path] }
else {
$oldItem = $oldIndex[$path]
$curItem = $currentIndex[$path]
if ($oldItem.Hash -ne $curItem.Hash -or $oldItem.Size -ne $curItem.Size) {
$modified += [PSCustomObject]@{
Path = $path
OldHash = $oldItem.Hash
NewHash = $curItem.Hash
OldSize = $oldItem.Size
NewSize = $curItem.Size
}
}
}
}
foreach ($path in $oldIndex.Keys) {
if (-Not $currentIndex.ContainsKey($path)) { $removed += $oldIndex[$path] }
}
# Guardar relatório atual para histórico
$current | ConvertTo-Json -Depth 4 | Out-File -FilePath $NowReport -Encoding UTF8
# Output resumido
$summary = [PSCustomObject]@{
Timestamp = (Get-Date).ToString('o')
Added = $added.Count
Removed = $removed.Count
Modified = $modified.Count
NewReport = $NowReport
}
$summary | ConvertTo-Json -Depth 3
# Também podemos guardar um log simples
$logFile = 'C:\Relatorios\file-integrity-log.txt'
Add-Content -Path $logFile -Value ("$((Get-Date).ToString('s')) - Added:$($added.Count) Removed:$($removed.Count) Modified:$($modified.Count)")
# Opcional: sobrescrever o relatório de referência para próxima comparação
$current | ConvertTo-Json -Depth 4 | Out-File -FilePath $ReportFile -Encoding UTF8
Paso 4: Programar o o automatizar la comprobación
Para ejecutar automáticamente, usa el Task Scheduler. Crea una tarea que ejecute PowerShell con la ruta del script y parámetros si es necesario. Configura para ejecutarse con permisos adecuados y con un trigger (p. ej.: diario o cada hora).
Verificar el resultado
Revisa los archivos JSON y el log: el resumen en JSON muestra Added, Removed y Modified. Abre el archivo file-integrity-log.txt para un historial rápido. En caso de Modified, compara OldHash vs NewHash para confirmar cambios. Errores comunes: rutas con permisos insuficientes o excepciones en archivos bloqueados — corrige permisos o ejecuta con una cuenta que tenga acceso.
Conclusión
Ahora tienes una solución sencilla para generar y comparar informes de integridad de archivos con PowerShell; los siguientes pasos incluyen notificación por email cuando haya cambios, excluir tipos de archivo específicos o integrar con SIEM. Consejo: prueba primero en una carpeta pequeña para validar hashes y permisos antes de aplicar en producción.