使用PowerShell在二进制文件中查找和替换十六进制值 [英] Use PowerShell to find and replace hex values in binary files

查看:371
本文介绍了使用PowerShell在二进制文件中查找和替换十六进制值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

更新:
我有一个工作脚本来完成任务。我需要批处理一堆文件,以便它接受格式为FileName,OriginalHEX,CorrectedHEX的csv文件。即使将搜索限制为前512个字节,它也非常慢。它可能写得更好,做得更快。

UPDATE: I got a working script to accomplish the task. I needed to batch process a bunch of files so it accepts a csv file formatted as FileName,OriginalHEX,CorrectedHEX. It's very slow even after limiting the search to the first 512 bytes. It could probably be written better and made faster. Thanks for the help.

更新2:将搜索方法修改为更快,但它远没有专用的十六进制编辑器快。请注意,这会占用大量内存。峰值大约是RAM中文件大小的32倍。 10MB = 320MB RAM。 100MB = 3.2GB RAM。我不建议使用大文件。它还会保存到新文件而不是覆盖文件。原始文件重命名为File.ext_original@date-time。

UPDATE 2: Revised the search method to be faster but it's nowhere near as fast as a dedicated hex editor. Be aware that it's memory intensive. peaks around 32X the size of the file in RAM. 10MB=320MB of RAM. 100MB=3.2GB of RAM. I don't recommend for big files. It also saves to a new file instead of overwriting. Original file renamed as File.ext_original@date-time.

Import-CSV $PSScriptRoot\HEXCorrection.csv | ForEach-Object {
  $File = $_.'FileName'
  $Find = $_.'OriginalHEX'
  $Replace = $_.'CorrectedHEX'


  IF (([System.IO.File]::Exists("$PSScriptRoot\$File"))) {
    $Target = (Get-ChildItem -Path $PSScriptRoot\$File)
  } ELSE {
    Write-Host $File "- File Not Found`n" -ForegroundColor 'Red'
    RETURN
  }

  Write-Host "File:   "$Target.Name`n"Find:    "$Find`n"Replace: "$Replace
  $TargetLWT = $Target.LastWriteTime
  $TargetCT = $Target.CreationTime
  IF ($Target.IsReadOnly) {
    Write-Host $Target.Name "- Is Read-Only`n" -ForegroundColor 'Red'
    RETURN
  }
  $FindLen = $Find.Length
  $ReplaceLen = $Replace.Length
  $TargetLen = (1..$Target.Length)

  IF (!($FindLen %2 -eq 0) -OR !($ReplaceLen %2 -eq 0) -OR 
  [String]::IsNullOrEmpty($FindLen) -OR [String]::IsNullOrEmpty($ReplaceLen)) {
    Write-Host "Input hex values are not even or empty" -ForegroundColor 'DarkRed'
    RETURN
  } ELSEIF (
    $FindLen -ne $ReplaceLen) {
    Write-Host "Input hex values are different lengths" -ForegroundColor 'DarkYellow'
    RETURN
  }

  $FindAsBytes = New-Object System.Collections.ArrayList
  $Find -split '(.{2})' | ? {$_} | % { $FindAsBytes += [Convert]::ToInt64($_,16) }
  $ReplaceAsBytes = New-Object System.Collections.ArrayList
  $Replace -split '(.{2})' | ? {$_} | % { $ReplaceAsBytes += [Convert]::ToInt64($_,16) }
  # ^-- convert to base 10

  Write-Host "Starting Search"
  $FileBytes = [IO.File]::ReadAllBytes($Target)
  FOREACH ($Byte in $FileBytes) {
        $ByteCounter++
        IF ($Byte -eq [INT64]$FindAsBytes[0]) { TRY {
             (1..([INT64]$FindAsBytes.Count-1)) | % {
               $Test = ($FileBytes[[INT64]$ByteCounter-1+[INT64]$_] -eq $FindAsBytes[$_])
               IF ($Test -ne 'True') {
                 THROW
               }
  }
    Write-Host "Found at Byte:" $ByteCounter -ForegroundColor 'Green'
    (0..($ReplaceAsBytes.Count-1)) | % {
      $FileBytes[[INT64]$ByteCounter+[INT64]$_-1] = $ReplaceAsBytes[$_]}
  $Found = 'True'
  $BytesReplaces = $BytesReplaces + [INT64]$ReplaceAsBytes.Count
  }
CATCH {}
}

}
  IF ($Found -eq 'True'){
    [IO.File]::WriteAllBytes("$Target-temp", $FileBytes)
    $OriginalName = $Target.Name+'_Original'+'@'+(Get-Date).ToString('yyMMdd-HHmmss')
    Rename-Item -LiteralPath $Target.FullName -NewName $OriginalName
    Rename-Item $Target"-temp" -NewName $Target.Name
    #Preserve Last Modified Time
    $Target.LastWriteTime = $TargetLWT
    $Target.CreationTime = $TargetCT
    Write-Host $BytesReplaces "Bytes Replaced" -ForegroundColor 'Green'
    Write-Host "Original saved as:" $OriginalName
  } ELSE {
      Write-Host "No Matches" -ForegroundColor 'Red'}
    Write-Host "Finished Search`n"
    Remove-Variable -Name * -ErrorAction SilentlyContinue
} # end foreach from line 1

PAUSE

原文:之前曾有人问过,但没有找到解决方案执行简单而直接的查找十六进制值,并在大于100MB的大文件上替换十六进制值。
甚至最好是对具有此任务的命令行支持的十六进制编辑器的建议。

Original: This has been asked before but found no solutions to perform a simple and straight up find hex value and replace hex value on large files, 100MB+. Even better would be any recommendations for a hex editor with command line support for this task.

推荐答案

这是第一个破解:

(get-content -encoding byte file) -replace '\b10\b',11 -as 'byte[]'

我正在检查其他链接,但唯一搜索并回答替换有一些错误。我投票决定重新开放。 mklement0一个关闭。他们都不搜索然后打印替换的位置。

I was checking those other links, but the only answer that does search and replace has some bugs. I voted to reopen. The mklement0 one is close. None of them search and then print the position of the replacement.

没关系。您的速度更快并且使用的内存更少。

Nevermind. Yours is faster and uses less memory.

这篇关于使用PowerShell在二进制文件中查找和替换十六进制值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆