# encoding: utf-8
# api: powershell
# title:
# description: My old bytes module with some extra functions from SANS all wrapped up into a single module.
# version: 0.1
# type: class
# license: CC0
# function: Shift-Left
# x-poshcode-id: 1729
# x-archived: 2016-03-10T10:09:48
#
#
#requires -version 2.0
Add-Type @"
public class Shift {
public static int Right(int x, int count) { return x >> count; }
public static uint Right(uint x, int count) { return x >> count; }
public static long Right(long x, int count) { return x >> count; }
public static ulong Right(ulong x, int count) { return x >> count; }
public static int Left(int x, int count) { return x << count; }
public static uint Left(uint x, int count) { return x << count; }
public static long Left(long x, int count) { return x << count; }
public static ulong Left(ulong x, int count) { return x << count; }
}
"@
#.Example
# Shift-Left 16 1 ## returns 32
#.Example
# 8,16 |Shift-Left ## returns 16,32
function Shift-Left {
PARAM( $x=1, $y )
BEGIN {
if($y) {
[Shift]::Left( $x, $y )
}
}
PROCESS {
if($_){
[Shift]::Left($_, $x)
}
}
}
#.Example
# Shift-Right 8 1 ## returns 4
#.Example
# 2,4,8 |Shift-Right 2 ## returns 0,1,2
function Shift-Right {
PARAM( $x=1, $y )
BEGIN {
if($y) {
[Shift]::Right( $x, $y )
}
}
PROCESS {
if($_){
[Shift]::Right($_, $x)
}
}
}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)
}
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).
}
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
#Â An 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)
}
function Convert-ByteArrayToString {
################################################################
#.Synopsis
#Â Returns the string representation of a System.Byte[] array.
#Â ASCII string is the default, but Unicode, UTF7, UTF8 and
#Â UTF32 are available too.
#.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 Encoding
#Â Encoding of the string: ASCII, Unicode, UTF7, UTF8 or UTF32.
#Â ASCII is the default.
################################################################
[CmdletBinding()] Param (
[Parameter(Mandatory = $True, ValueFromPipeline = $True)] [System.Byte[]] $ByteArray,
[Parameter()] [String] $Encoding = "ASCII"
)
switch ( $Encoding.ToUpper() )
{
"ASCII"Â Â { $EncodingType = "System.Text.ASCIIEncoding" }
"UNICODE" { $EncodingType = "System.Text.UnicodeEncoding" }
"UTF7"Â Â Â { $EncodingType = "System.Text.UTF7Encoding" }
"UTF8"Â Â Â { $EncodingType = "System.Text.UTF8Encoding" }
"UTF32"Â Â { $EncodingType = "System.Text.UTF32Encoding" }
Default  { $EncodingType = "System.Text.ASCIIEncoding" }
}
$Encode = new-object $EncodingType
$Encode.GetString($ByteArray)
}
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 NoOffset
#Â Switch to suppress offset line numbers in output.
#.Parameter NoText
#Â Switch to suppress ASCII translation of bytes in output.
################################################################
[CmdletBinding()] Param (
[Parameter(Mandatory = $True, ValueFromPipelineByPropertyName = $True)]
[Alias("FullName","FilePath")] $Path,
[Parameter()] [Int] $Width = 16,
[Parameter()] [Int] $Count = -1,
[Parameter()] [Switch] $NoOffset,
[Parameter()] [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 = $asciitext = $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, e.g., "F".
$paddedhex += $byteinhex.PadLeft(2,"0") + " "Â Â Â Â # Pad with zero to force 2-digit length, e.g., "0F ".
}
# Total bytes in file unlikely to be evenly divisible by $width, so fix last line.
# Hex output width is '$width * 3' because of the extra spaces added around hex characters.
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) )
{ $asciitext += [Char] $byte }
else
{ $asciitext += $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, each line representing $width bytes.
if (-not $NoOffset) { $paddedhex = "$offsettext $paddedhex" }
if (-not $NoText) { $paddedhex = $paddedhex + $asciitext }
$paddedhex
}
}
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
}
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()
}