PoshCode Archive  Artifact [4fc63888b9]

Artifact 4fc63888b98caf0939056d5158d52dd75f762dd90c32f6bc6d29045702ff4b4e:

  • File Shift-Left.ps1 — part of check-in [c888cde013] at 2018-06-10 13:00:33 on branch trunk — My old bytes module with some extra functions from SANS all wrapped up into a single module. (user: unknown size: 13612)

# 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()
}