Skip to content

Instantly share code, notes, and snippets.

@bitraid
Last active June 7, 2021 06:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bitraid/fe8fa15fc1c30b1ca9cc380e5bcebde6 to your computer and use it in GitHub Desktop.
Save bitraid/fe8fa15fc1c30b1ca9cc380e5bcebde6 to your computer and use it in GitHub Desktop.
Update PE checksum
@echo off
setlocal EnableDelayedExpansion
if ["%~1"] == [""] (echo:Usage: %~nx0 ^<PE-File [...]^>) & (goto:eof)
:update_file
for %%G in ("%~1") do (
call:powershell update_pechecksum "%%~G"
if !ERRORLEVEL! equ 1 (1>&2 echo:%%~fG: Error: Could not open the file.)
if !ERRORLEVEL! equ 2 (1>&2 echo:%%~fG: Error: Could not map the file.)
if !ERRORLEVEL! equ 3 (1>&2 echo:%%~fG: Error: Could not map a view of the file.)
if !ERRORLEVEL! equ 4 (1>&2 echo:%%~fG: Error: Could not convert the file name to Unicode.)
if !ERRORLEVEL! equ 5 (1>&2 echo:%%~fG: Error: Could not open the file for writing.)
if !ERRORLEVEL! equ 6 (1>&2 echo:%%~fG: Error: Could not read form file.)
if !ERRORLEVEL! equ 7 (1>&2 echo:%%~fG: Error: Could not write to file.)
if !ERRORLEVEL! equ 8 (1>&2 echo:%%~fG: Error: Not a PE file.)
)
shift
if not ["%~1"] == [""] (goto:update_file)
goto:eof
:powershell
setlocal EnableDelayedExpansion
set /a SKIP=1
for /f "delims=" %%G in (%~f0) do if !SKIP! equ 1 (if "%%G" == "::PS:%~1.start" set /a SKIP=0) else (if "%%G" == "::PS:%~1.end" (goto:run) else (set PS=!PS!;%%G))
:run
shift
set /a N=1
:set_vars
if not ["%~1"] == [""] (
set P%N%=%~1
shift
set /a N+=1
goto:set_vars
)
echo:%PS% | powershell -nologo -noprofile -command -
endlocal
goto:eof
::PS:update_pechecksum.start
$ErrorActionPreference = 'Stop'
$PointerOffset = 60
$CheckSumOffset = 88
$Buffer = 4096
$Bytes = New-Object byte[]($Buffer)
try { $PeFile = Get-ChildItem -Path $env:P1 } catch { exit 1 }
try { $Stream = New-Object System.IO.FileStream($PeFile, [System.IO.FileMode]::Open, [System.IO.FileAccess]::Read) } catch { exit 1 }
try { if ($Stream.Read($Bytes, 0, $Buffer) -lt $PointerOffset + 4) { $Stream.Close(); exit 8 } } catch { $Stream.Close(); exit 6 }
if ($Bytes[0] -ne 0x4d -or $Bytes[1] -ne 0x5a) { $Stream.Close(); exit 8 }
if (($HeaderOffset = [System.BitConverter]::ToUint32($Bytes, $PointerOffset)) -eq 0 -or $HeaderOffset -ge $PeFile.Length) { $Stream.Close(); exit 8 }
try { $Stream.Position = $HeaderOffset } catch { $Stream.Close(); exit 6 }
try { if ($Stream.Read($Bytes, 0, $Buffer) -lt $CheckSumOffset + 4) { $Stream.Close(); exit 1 } } catch { $Stream.Close(); exit 1 }
if (@(Compare-Object -ReferenceObject 80, 69, 0, 0 -DifferenceObject $Bytes[0..3] -SyncWindow 0).Length -ne 0) { $Stream.Close(); exit 8 }
Add-Type -TypeDefinition 'using System; using System.Diagnostics; using System.Runtime.InteropServices
public static class Imagehlp { [DllImport("imagehlp.dll", CharSet = CharSet.Auto)]public static extern int MapFileAndCheckSum(string Filename, out int HeaderSum, out int CheckSum); }'
[int]$HeaderSum = 0
[int]$CheckSum = 0
if (($Result = [Imagehlp]::MapFileAndCheckSum($PeFile.FullName, [ref]$HeaderSum, [ref]$CheckSum)) -ne 0) { $Stream.Close(); exit $Result }
if ($HeaderSum -ne [System.BitConverter]::ToUint32($Bytes, $ChecksumOffset)) { $Stream.Close(); exit 8 }
if ($HeaderSum -ne $CheckSum) {
$Stream.Close()
try { $Stream = New-Object System.IO.FileStream($PeFile.FullName, [System.IO.FileMode]::Open, [System.IO.FileAccess]::ReadWrite, [System.IO.FileShare]::Read) } catch { exit 5 }
$Writer = New-Object System.IO.BinaryWriter($Stream)
try { $Writer.BaseStream.Position = $HeaderOffset + $CheckSumOffset } catch { $Stream.Close(); exit 7 }
try { $Writer.Write($CheckSum) } catch { $Stream.Close(); exit 7 }
Write-Host ("${PeFile}: Checksum updated: {0:X8} -> {1:X8}" -f $HeaderSum, $CheckSum)
} else { Write-Host ("${PeFile}: Checksum update not required: {0:X8}" -f $HeaderSum) }
$Stream.Close()
::PS:update_pechecksum.end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment