Public/Get-OffsetString.ps1
|
function Get-OffsetString { <# .SYNOPSIS Extracts printable ASCII and UTF-16LE strings from a file with their byte offsets. .DESCRIPTION Scans the file in bounded-memory windows and emits each printable string (default minimum length 4) tagged with its absolute byte offset and encoding. The offsets feed directly into Invoke-OffsetInspect for context. A string that straddles a window boundary may be split; raise -WindowSize to reduce that. Cross-platform. .PARAMETER FilePath The file to scan. .PARAMETER MinimumLength Minimum character count for a string to be reported (default 4). .PARAMETER Encoding Ascii, Unicode (UTF-16LE), or Both (default). .PARAMETER WindowSize Bytes read per window (default 1 MiB). .EXAMPLE Get-OffsetString .\sample.bin -MinimumLength 6 | Where-Object Value -match 'http|\.exe' #> [CmdletBinding()] param( [Parameter(Mandatory = $true, Position = 0)] [ValidateNotNullOrEmpty()] [string]$FilePath, [ValidateRange(2, 1024)] [int]$MinimumLength = 4, [ValidateSet('Ascii', 'Unicode', 'Both')] [string]$Encoding = 'Both', [ValidateRange(4096, 67108864)] [int]$WindowSize = 1048576 ) $resolvedPath = (Resolve-Path -LiteralPath $FilePath -ErrorAction Stop).Path $item = Get-Item -LiteralPath $resolvedPath -ErrorAction Stop if ($item.PSIsContainer) { throw "Path is a directory, not a file: $resolvedPath" } $fileSize = $item.Length $stream = $null try { $stream = [System.IO.File]::Open( $resolvedPath, [System.IO.FileMode]::Open, [System.IO.FileAccess]::Read, [System.IO.FileShare]::Read ) $start = [int64]0 while ($start -lt $fileSize) { $bytes = Read-OIFileRange -Stream $stream -Start $start -Length $WindowSize if ($bytes.Length -le 0) { break } foreach ($found in (Get-OIByteString -Bytes $bytes -BaseOffset $start -MinimumLength $MinimumLength -Encoding $Encoding)) { [pscustomobject]@{ Offset = $found.Offset OffsetHex = '0x{0:X}' -f $found.Offset Encoding = $found.Encoding Length = $found.Length Value = $found.Value } } $start += $bytes.Length } } finally { if ($null -ne $stream) { $stream.Dispose() } } } |