RBCmd icon indicating copy to clipboard operation
RBCmd copied to clipboard

FYI: PowerShell script to enumerate Recycle Bin contents with metadata

Open AbderafieChairi opened this issue 3 months ago • 0 comments

Hi Man , While using RBCmd for Recycle Bin analysis, I developed a PowerShell script that directly parses $I files and correlates them with nested $R items for forensic purposes. The script may be useful as a complement to RBCmd or could highlight potential functionality worth integrating.

Features

  • Recursively scans all user Recycle Bin folders (C:\$Recycle.Bin\<SID>).
  • Reads and parses $I* files to extract:
    • Original file path before deletion
    • File size (at deletion)
    • Deletion timestamp (converted from FILETIME to UTC)
  • Pairs each $I* file with its corresponding $R* data folder/file.
  • Recursively enumerates all items within $R* (up to 8 levels deep).
  • Collects forensic metadata for each deleted file/folder:
    • User SID (who deleted the file)
    • Original path
    • Deleted Recycle Bin path
    • Deletion timestamp (UTC)
    • File name
    • File size
    • Creation, LastWrite, and LastAccess timestamps (UTC)
  • Exports results to a UTF-8 CSV file (RecycleBin_Forensics.csv).

powershell script :

# Recycle Bin forensic extractor
# Lists deleted files/folders with metadata and maps them to original paths

$results = @()
$Recycle = "$"+"Recycle"

function Get-FileTimeUtc([byte[]]$bytes, [int]$offset) {
    $ft = [BitConverter]::ToInt64($bytes, $offset)
    if ($ft -gt 0) {
        return [DateTime]::FromFileTimeUtc($ft)
    }
    return $null
}

$recycleBin = "C:\$Recycle.Bin"

# Loop through each SID folder
foreach ($sidDir in Get-ChildItem $recycleBin -Directory -Force) {
    $sid = $sidDir.Name
    Write-Host "Processing SID: $($sidDir.FullName)"
    # Find all $I files (metadata files)
    foreach ($iFile in Get-ChildItem $sidDir.FullName -Filter '$I*' -Force) {
        try {
            $bytes = [System.IO.File]::ReadAllBytes($iFile.FullName)
            if ($bytes.Length -lt 24) { continue }

            $deletionTime = Get-FileTimeUtc $bytes 16
            $pathLen = [BitConverter]::ToInt32($bytes, 24)

            $origPath = [System.Text.Encoding]::Unicode.GetString($bytes, 28, $pathLen * 2)
            $origPath = $origPath.TrimEnd([char]0)  # remove trailing nulls
            $origPath = $origPath -replace "^\u0003?","" # strip weird control chars like ␦

            # Match the $R file/directory
            $rName = $iFile.Name.Replace('$I', '$R')
            $rPath = Join-Path $sidDir.FullName $rName

            if (Test-Path $rPath) {
                # Get all items inside (up to 8 levels)
                $items = Get-ChildItem $rPath -Recurse -Force -ErrorAction SilentlyContinue -Depth 8

                foreach ($item in $items) {
                    $results += [PSCustomObject]@{
                        SID            = $sid
                        OriginalPath   = $origPath
                        DeletedPath    = $item.FullName
                        DeletionTimeUTC= $deletionTime
                        FileName       = $item.Name
                        IsContainer    = $item.PSIsContainer
                        Size           = if ($item.PSIsContainer) { $null } else { $item.Length }
                        CreationTime   = $item.CreationTimeUtc
                        LastWriteTime  = $item.LastWriteTimeUtc
                        LastAccessTime = $item.LastAccessTimeUtc
                    }
                }
            }
        } catch {
            Write-Warning "Error parsing $($iFile.FullName): $_"
        }
    }
}

# Export results
$results | Export-Csv -Path .\RecycleBin_Forensics.csv -NoTypeInformation -Encoding UTF8

This isn’t a replacement for RBCmd by any means, but more of a quick-and-dirty helper script. It might be useful for quick triage, or maybe as inspiration for additional RBCmd functionality around nested $R* content.

mini output for illustration :

SID OriginalPath DeletedPath FileName DeletionTimeUTC
S-1-5-21-2562676247-2455829573-1000 C:\Users\user1 C:$Recycle.Bin\S-1-5-21-2562676247-2455829573-1000$RZ9AYH3 $RZ9AYH3 2022-03-20 16:20:00
S-1-5-21-2562676247-2455829573-1000 C:\Users\user1\host C:$Recycle.Bin\S-1-5-21-2562676247-2455829573-1000$RZ9AYH3\host host 2022-03-20 16:20:00
S-1-5-21-2562676247-2455829573-1000 C:\Users\user1\host\file.txt C:$Recycle.Bin\S-1-5-21-2562676247-2455829573-1000$RZ9AYH3\host\file.txt file.txt 2022-03-20 16:20:00

Feel free to test it and give feedback!

AbderafieChairi avatar Sep 14 '25 13:09 AbderafieChairi