In my previous post I showed you a couple of wrapper functions I made to handle binary to string conversion (and vice versa). Building on one of these I thought it would be fun to try to make a simple file hex viewer, similar to how popular hex editors work (without the editing part of course).
The function opens a filestream and uses a binary reader object to read the file, then pipes the result to my wrapper function called Invoke-CryptBinaryToString that shows a string representation of the file in hex as well as in ASCII. Optionally you can also add address fields using the ShowAddress parameter.
This means that you need to have my code from the previous post loaded in memory to be able to use this one.
The function also lets you choose where to start and how many bytes it should read, in case you only want to look at particular sections of the file.
Hope you find this one interesting. Catch you on the next one!
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function Show-BinaryFile { | |
<# | |
.SYNOPSIS | |
Binary file viewer. | |
.DESCRIPTION | |
This function will read and output a HEX and ASCII representation of a | |
binary file, similar to hex editors. | |
.EXAMPLE | |
Show-BinaryFile -Path 'c:\path\to\binary.file' | |
This will read and output the entire binary file. | |
.EXAMPLE | |
Show-BinaryFile -Path 'c:\path\to\binary.file' -Start 16 -Length 64 | |
This will read 64 bytes starting at position 16, and output the results. | |
.NOTES | |
NOTE! This function is using my wrapper function Invoke-CryptBinaryToString and will not work without it! | |
Author: Øyvind Kallstad | |
Date: 09.02.2016 | |
Version: 1.0 | |
.LINK | |
https://communary.wordpress.com/ | |
#> | |
[CmdletBinding()] | |
param ( | |
# The path to the file you want to read. | |
[Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true, ValueFromPipelinebyPropertyName = $true)] | |
[ValidateNotNullOrEmpty()] | |
[string] $Path, | |
# Start position for read operation. | |
[Parameter(Position = 1)] | |
[ValidateRange(0,[int]::MaxValue)] | |
[int] $Start = 0, | |
# The length of the read operation. | |
[Parameter(Position = 2)] | |
[ValidateRange(0,[int]::MaxValue)] | |
[int] $Length = 0, | |
# Indicate whether you want an address portion added to the output. | |
[Parameter(Position = 3)] | |
[switch] $ShowAddress | |
) | |
if (Test-Path –Path $Path) { | |
try { | |
$resolvedPath = Resolve-Path –Path $Path | |
$fileStream = New-Object –TypeName System.IO.FileStream –ArgumentList ($resolvedPath, [System.IO.FileMode]::Open, [System.IO.FileAccess]::Read) | |
$fileReader = New-Object –TypeName System.IO.BinaryReader –ArgumentList $fileStream | |
if ($Length -eq 0) { | |
$Length = $fileReader.BaseStream.Length | |
} | |
$fileReader.BaseStream.Position = $Start | |
[byte[]]$readBytes = $fileReader.ReadBytes($Length) | |
if ($ShowAddress) { | |
$readBytes | Invoke-CryptBinaryToString –Format HexASCIIAddr | |
} | |
else { | |
$readBytes | Invoke-CryptBinaryToString –Format HexASCII | |
} | |
} | |
catch { | |
Write-Warning $_.Exception.Message | |
} | |
finally { | |
$fileReader.Dispose() | |
$fileStream.Dispose() | |
} | |
} | |
else { Write-Warning "$Path not found!" } | |
} |
UPDATE! As Kirk mentions in his comment down below, this functionality is in fact natively supported in PowerShell version 5! So no need for my function at all if you are using v5. 🙂
Did you know you can do this natively with Format-Hex in PowerShell 5?
e.g.
Format-Hex -Path $pathToBinaryFile | Select-Object -First 4
Format-Hex -Path $pathToBinaryFile | Select-Object -First 16
You even get back .NET objects so you could filter on an address range by using the Offset property.
I thought it was worth pointing this functionality out since it is available out of the box with PowerShell 5.
LikeLike
Thank you for your comment Kirk. No, I didn’t know, so tanks for bringing it to my attention! I love learning new stuff 🙂 This was just a spin-off idea based on my previous post, so I thought it would be a cool function.. turns out it’s not needed at all 😀
LikeLike
What versions will your script work with? Or what version was it written in? There’s always a need for scripts to do things in prior versions… not all of us can upgrade immediately at work. In addition, I find it awesome that you coded this, AND other people thought it was useful enough to put into v5. Kirk, thanks for pointing it out, too!
LikeLike