I had some help with a text-replacement script recently and wondered if it could be used for patching purposes. I usually use HxD, and thought that if it's essentially a glorified notepad, what difference is there between editing an executable in a text editor and a hex editor? I decided to test my theory and put the script to the test, while it can replace the specified strings, it adds information to the executable.

What throws me off here is that if it is used for replacing text in a text document, it only replaces strings and doesn't add bytes to the document unless the new string is longer than the previous one. I believe this is because the script is designed for editing text documents and modifies the header because of this. I used HxD to compare the before and after and sure enough the header gets modified. Here is the script I have currently:

@echo off
setlocal enableextensions disabledelayedexpansion

set search=OutDir=Old String
set replace=OutDir=New String
set textFile=Document.txt

SET PSScript=%temp%\~tmpStrRplc.ps1
ECHO (Get-Content "%~dp0%textFile%").replace("%search%", "%replace%") ^| Set-Content "%~dp0%textFile%">"%PSScript%"

SET PowerShellDir=C:\Windows\System32\WindowsPowerShell\v1.0
CD /D "%PowerShellDir%"
Powershell -ExecutionPolicy Bypass -Command "& '%PSScript%'"

(The strings I will be replacing are the same size, so the executable's size will be unaltered, and string corruption is not being used.)

I would like to note that I am new to PowerShell, so I'm still learning how it works. I noticed the %~dp0%textFile% variable. If I am interpreting this variable correctly, it tells the PowerShell script to handle the defined file to be modified as a text document. Going with this logic (if it is correct), is there a similar variable that will either ignore the format or handle the input file as an executable? My script is capable of changing what I define, but breaks the executable, Is patching with my script feasible?

  • No. In the general case, you cannot "patch" an executable with a text editor. Executables care where most bytes are positioned and moving them around without adjusting the pointers tends to result in unintended effects. If you're lucky it will crash straight up; if not then it can do just about anything. You can't even assume anything about the format of text stored in an unknown executable nor what is necessary to modify it. – Bob Feb 19 '18 at 12:56
  • I am aware that bytes must be overwritten, not shifted in an executable. In my case the strings I am replacing are the same size as their predecessors. My example does not reflect this so I will revise it. Even so, I don't understand how I can replace the string in Notepad++ without corrupting the binary. Unless Notepad++ is "format aware" I don't see how replacing strings is impossible. Is there something else here I'm missing? – Mr. Mendelli Feb 19 '18 at 13:11
  • 1
    To guard against corruptions, there is a check-sum in the header of an EXE file: this will need to be updated if you change anything in the file. Also, any text-based string replacement is liable to corrupt a binary file, since null bytes are used as string delimiters, so you need to use a binary editor, but I don't know of any that allow batch operation. – AFH Feb 19 '18 at 13:24
  • Good to know @AFH, I had not taken the null bytes into consideration. – Mr. Mendelli Feb 19 '18 at 13:25
  • A better answer might be to change the output directory into a symbolic link pointing at the directory you want, and leave the binaries alone. – AFH Feb 19 '18 at 13:27

Taken from an example I saw recently:

# Description: set your.exe resolution 0 to any x/y specified
# By knowning the offset for these values hard coded in your 
# executable
# - None of this is real world... example only

Set-Location(Split-Path $MyInvocation.MyCommand.Path)

# Prompt resolution

$resolutionX = Read-Host -Prompt "Width"
$resolutionY = Read-Host -Prompt "Height"
# Resolution Z is just hard coded as 32

# Patch bytes

$bytes  = [System.IO.File]::ReadAllBytes("your.exe")

# Arbitrary locations and values for example

$offsetX = 0x0039CA70
$offsetY = $offsetX + 4
$offsetZ = $offsetY + 4

$resolutionX = [BitConverter]::GetBytes([Int16]$resolutionX)
$resolutionY = [BitConverter]::GetBytes([Int16]$resolutionY)
$resolutionZ = [BitConverter]::GetBytes([Int16]32)

# SMASH your new values into the exe

$bytes[$offsetX] = $resolutionX[0]
$bytes[$offsetX+1] = $resolutionX[1]
$bytes[$offsetY] = $resolutionY[0]
$bytes[$offsetY+1] = $resolutionY[1]
$bytes[$offsetZ] = $resolutionZ[0]

# And save the result

[System.IO.File]::WriteAllBytes("your.exe", $bytes)

Read-Host -Prompt "Press Enter to exit"
  • Some explanation is welcome. – Toto Mar 23 '18 at 18:12
  • Thank you @isaac willard. This is very interesting, I will see what I can do with it. Could you perhaps provide the original source this was taken from? – Mr. Mendelli Mar 28 '18 at 7:14

Your Answer

By clicking "Post Your Answer", you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.