Avatar of Member_2_8180951
Member_2_8180951
 asked on

PowerShell: Find & Replace Hex Values

I need help writing a PowerShell script: write offset positions, find and replace hex value with another hex value in an entire file.

Similar to,
$Hex_Search = "0xFF 0xFF 0xFF" # White

Write-Host Found "$Hex_Search" Between Offsets: 0x00000500-0x00001000

$Hex_Replace = "0xC0 0xC0 0xC0" # Silver

Open in new window


For my script the file can be any size.
Been using two PowerShell scripts, no avail.
# Credit to OP

$path = "C:\_Test 2\Test.txt"

$numberOfBytesToRead = 1000000

$stringToSearch = "0xFF 0xFF 0xFF"
$enc = [system.Text.Encoding]::UTF8
[Byte[]]$replacementString = $enc.GetBytes("0xC0 0xC0 0xC0");

$fileStream = [System.IO.File]::Open($path, [System.IO.FileMode]::Open, [System.IO.FileAccess]::Read, [System.IO.FileShare]::ReadWrite)

# binary reader to search for the string 
$binaryReader = New-Object System.IO.BinaryReader($fileStream)

# get the contents of the beginning of the file
[Byte[]] $byteArray = $binaryReader.ReadBytes($numberOfBytesToRead)

# look for string
$m = [Regex]::Match([Text.Encoding]::ASCII.GetString($byteArray), $stringToSearch)
if ($m.Success)
{    
    echo "Found '$stringToSearch' At Position "$m.Index
}
else
{
    echo "'$stringToSearch' Not Found"
}

$fileStream.Close()

# reopen to write
$fileStream = [System.IO.File]::Open($path, [System.IO.FileMode]::Open, [System.IO.FileAccess]::Write, [System.IO.FileShare]::ReadWrite)

$binaryWriter = New-Object System.IO.BinaryWriter($fileStream)

# set file position to location of the string
$binaryWriter.BaseStream.Position = $m.Index; 
$binaryWriter.Write($replacementString)

$fileStream.Close()

Open in new window


(Get-Content "C:\_Test 2\Test.txt") | ForEach-Object {$_ -Replace '0xFF 0xFF 0xFF', '0xC0 0xC0 0xC0'} | Set-Content "C:\_Test 2\Test.txt"

Open in new window


Thanks In Advance
Powershell

Avatar of undefined
Last Comment
footech

8/22/2022 - Mon
footech

Can you provide a couple sample files?
One in the format you're ingesting and that has the values you want to replace, and one that shows the file as it should be after processing.

This will be the easiest way to ensure there's no confusion around objectives, etc.
Michael B. Smith

I think you may be overthinking this. :-)

[byte[]] $searchBytes = 0x3, 0x4, 0x5  ## whatever
[byte[]] $content = Get-Content -Path <filename> -Raw -ReadCount 0 -Encoding Byte
if( $content.Contains( $searchBytes ) )
{
    $startIndex = $content.IndexOf( $searchBytes )
    Write-Host "Found searchBytes at $startIndex"
    ## well, replace it and rewrite it - you already know how to do that
}

Open in new window

Member_2_8180951

ASKER
I don't have example files (apologies), I need to find and replace hex (and print the offset range positions) similar to,
$Find_example = (0x65 0x78 0x61 0x6d 0x70 0x6c 0x65) # example (in hex)
Write-Host Found "$Find_example" Between Offsets: 0x00000500-0x00001000 # Just Example Position Range
$Replace_With_next = (0x6e 0x65 0x78 0x74) # next (in hex)

Open in new window


I actually need to find and replace color hex code,
$Find_Color_Hex = (0x00 0x80 0x00) # green in hex proper hex code (#008000)
Write-Host Found "$Find_Color_Hex" Between Offsets: 0x00000500-0x00001000 # Just Example Position Range
$Replace_Color_Hex = (0x87 0xCE 0xEB) # skyblue in hex proper hex code(#87CEEB)

Open in new window


@Michael B. Smith thanks for an answer, but the parameter "-Raw" isn't in PowerShell v2 ;_;
I started with Experts Exchange in 2004 and it's been a mainstay of my professional computing life since. It helped me launch a career as a programmer / Oracle data analyst
William Peck
footech

The files should be pretty trivial for you to create.  You've already got files you want to work on (hence your question).  Just strip out all but a few lines that include the match you're searching for (you can obfuscate other info if needed).  Save it and you've got your sample input.  Do a manual edit to create your desired result, save it and you've got your sample output.
Michael B. Smith

Replace this line

[byte[] $content = Get-Content -Path <filename> -Raw -ReadCount 0 -Encoding Byte

with

[byte[] $content = [System.Io.File]::ReadAllBytes( <filename> )

To get (and I added the rest of it):

[byte[]] $searchBytes = 0x0, 0x80, 0x0  ## your example
[byte[]] $replaceBytes = 0x87, 0xCE, 0xEB  ## your example
[byte[]] $content = [System.Io.File]::ReadAllBytes( <filename> )
if( $content.Contains( $searchBytes ) )
{
    $startIndex = $content.IndexOf( $searchBytes )
    Write-Host "Found searchBytes at $startIndex"
    for( $i = 0; $i -lt $searchBytes.Length; $i++ )
    {
        $content[ $i + $startIndex ] = $replaceBytes[ $i ]
    }
    [System.Io.File]::WriteAllBytes( <filename>, $content )
}

Open in new window

Member_2_8180951

ASKER
Here is example in text document,
some hex values are: 0x49, 0x4B, 0x41 (IKA)
and need to change to: 0x6D, 0x75, 0x73, 0x75, 0x6D, 0x65 (musume)
and vice-versa

and print ranges, such as
0x00000000-0x00000002
0x00000053-0x00000055

@Michael B. Smith
I received error,
Error: "Method invocation failed because [System.Byte[] doesn't contain a method named 'Contains'." (Apologies, new to PowerShell.)

Edit: tried to upload text file? here is link to contents of Example.txt https://pastebin.com/pw1P9k2S
Get an unlimited membership to EE for less than $4 a week.
Unlimited question asking, solutions, articles and more.
Michael B. Smith

How old a version of .NET and PowerShell are you running?

I copy-and-paste what I wrote above and it works.
Member_2_8180951

ASKER
PowerShell v2.0
.NET v3.0
Michael B. Smith

Word.

So the input and output lengths can be different?

Can there be multiple occurrences of the input string in the file?
Experts Exchange has (a) saved my job multiple times, (b) saved me hours, days, and even weeks of work, and often (c) makes me look like a superhero! This place is MAGIC!
Walt Forbes
Member_2_8180951

ASKER
Yes, input and output can be different lengths.

There can be more occurrences.
ASKER CERTIFIED SOLUTION
Michael B. Smith

Log in or sign up to see answer
Become an EE member today7-DAY FREE TRIAL
Members can start a 7-Day Free trial then enjoy unlimited access to the platform
Sign up - Free for 7 days
or
Learn why we charge membership fees
We get it - no one likes a content blocker. Take one extra minute and find out why we block content.
Not exactly the question you had in mind?
Sign up for an EE membership and get your own personalized solution. With an EE membership, you can ask unlimited troubleshooting, research, or opinion questions.
ask a question
Member_2_8180951

ASKER
Many Thanks @Michael B. Smith ^^

@footech if you have an solution please post it, I want learn from it :)
footech

I've got nothing, as I was waiting on sample files.  I had some questions that the files would have definitively answered, much easier than my trying to type them out.

But no worries, I'm glad Michael's solution works for you.
Get an unlimited membership to EE for less than $4 a week.
Unlimited question asking, solutions, articles and more.