Page 1 of 2
How to search HEX value and replace all it
Posted: Mon Jun 24, 2024 10:17 am
by hoangdiemtinh
I am new to PB. My primary language is not US/UK. I am using Google Translate.
I need to create a patch for a file.
I have the hex code from
the following Procedure.
How to find all these HEX value and replace them in one file?
Re: How to search HEX value and replace all it
Posted: Mon Jun 24, 2024 10:21 am
by BarryG
Your post history is VERY concerning.
Re: How to search HEX value and replace all it
Posted: Mon Jun 24, 2024 10:38 am
by hoangdiemtinh
I replaced the same hex value (in my exe file) by using
HxD Hex Editor.
But I want to automate this operation, it happens faster.
Re: How to search HEX value and replace all it
Posted: Mon Jun 24, 2024 10:53 am
by PBJim
BarryG wrote: Mon Jun 24, 2024 10:21 am
Your post history is VERY concerning.
Agreed, I’ve been increasingly concerned, particularly with all the global news of state-sponsored attacks on systems and infrastructure, which human rights-abusing regimes we’re in fact helping to support by giving powerful working PB code and functions. In fact, the writer of the linked post to which the OP refers, also asked several days ago about the ability to disable an important Windows anti-malware security feature. I’m mindful that PureBasic’s architecture, gives it a great deal of power to do harm, as well as good, in comparison with some of the competing languages that are encumbered by Common Language Infrastructure and so on.
Re: How to search HEX value and replace all it
Posted: Mon Jun 24, 2024 7:45 pm
by infratec
You don't nee a hex code to replace a byte or a sequence of bytes.
You can do it directly in the memory which is much faster.
Btw. you didn't told us what you want to replace with what.
Re: How to search HEX value and replace all it
Posted: Mon Jun 24, 2024 11:22 pm
by hoangdiemtinh
Is it possible to replace it with a hex segment whose length is smaller or larger than the found hex segment?
(If this is not possible, just use the equal length option.)
ex:
hex to find: 66696e642069742e
hex to replace: 666f756e642069742e
Hex code is converted from utf-8 string.
Re: How to search HEX value and replace all it
Posted: Tue Jun 25, 2024 4:58 am
by infratec
Is is correct that he stings have not the same length?
If you really want to replace strings, why not ReplaceString() ?
Re: How to search HEX value and replace all it
Posted: Tue Jun 25, 2024 9:06 am
by hoangdiemtinh
Have the same byte length.
( If possible, in case the byte length to replace is greater than the original byte length, insert 00 or FF ).
The file (.exe, .dll...) to find replacement bytes is made with unicode support.
Re: How to search HEX value and replace all it
Posted: Tue Jun 25, 2024 9:47 am
by mk-soft
HEX values are only one form of representation. So there will be no HEX in the file (unless someone has stored them as text in the file for fun)
It is therefore an array of bytes and can be edited with ReadByte and WriteByte in the file.
Then you can think about how this display. (HEX, OCT, DEC, CHAR, BIN)
Code: Select all
Structure ArrayOfByte
StructureUnion
b.b[0] ; -128 .. 128
a.a[0] ; 0 .. 255
EndStructureUnion
EndStructure
Re: How to search HEX value and replace all it
Posted: Tue Jun 25, 2024 11:25 am
by hoangdiemtinh
Searched the forum, I saw
a post by @CELTIC88
I tried running it but got an error:
Code: Select all
ScrollBarGadget(): ScrollBar 'PageLength' must be lower than or equal to the 'Max' value.
and it's long for me to understand...
Re: How to search HEX value and replace all it
Posted: Tue Jun 25, 2024 1:05 pm
by boddhi
hoangdiemtinh wrote:
and it's long for me to understand...
Programming does require a bit of analysis, research and testing.
Code: Select all
ScrollBarGadget(#PB_Any, Width + x, y, 15, Height, 0, 0, 1,#PB_ScrollBar_Vertical)
PureBasic debug wrote:[...] 'PageLength' MUST BE LOWER THAN OR EQUAL to the 'Max' value
PureBasic help wrote:Result = ScrollBarGadget(#Gadget, x, y, Width, Height, Minimum, Maximum, PageLength [, Flags])
So, what are the values of these two parameters?
0, 1,#PB_ScrollBar_Vertical
Try to change these values to see what it happens!
Re: How to search HEX value and replace all it
Posted: Tue Jun 25, 2024 2:10 pm
by hoangdiemtinh
Why not success ? ( Source
at here )
Code: Select all
EnableExplicit
#REPLACEONE = 1 ;make only one replacement, default is to search whole file and make multiple replacements (without this flag)
#STRINGMODE = 2 ;find string, default is hex (without this flag)
#CASESENSITIVE = 4 ;case sensitive string search and replace, default is case-insensitive (without this flag)
#FILLDATA = 8 ;if DataToReplace$ is smaller than DataToFind$ then append data to make it same length as DataToFind$, function returns error (-1) without this flag if DataToFind$ and DataToReplace$ are not same length
#STRING_CASESENSITIVE=#STRINGMODE|#CASESENSITIVE|#FILLDATA
Procedure ReplaceDataInFile(File$, DataToFind$, DataToReplace$, StartPosition=1, Flags=#FILLDATA, BufferLen=4096,*Count=0)
;RETURN: <0 if error {-4=file not found;-3=file open error;-2=not enough free memory on system;-1=wrong parameters}
; =0 if ToFind$ not found
; >0 position of last replacement
Protected _ltf=Len(DataToFind$)
Protected _ltr=Len(DataToReplace$)
Protected length = _ltf
Protected k, result
If Not Flags & #STRINGMODE ; if hex search...
If (length%2)<>0 ; ...then len must be {2,4,6,8,...}
ProcedureReturn -1 ; we don't have valid len for hex search (1,3,5,7,... is not valid)
EndIf
length/2 ; 2 hex characters means 1 byte
EndIf
If Flags & #FILLDATA
If _ltf>_ltr ;if length of DataToReplace$ is smaller than DataToFind$...
DataToReplace$+Space(_ltf-_ltr) ;...then add empty data (space characters: chr(20)) to end of DataToReplace$
Protected __ltr=_ltr
_ltr=Len(DataToReplace$)
If Not Flags & #STRINGMODE ;if we do not search for string (--> hex search)...
For k=__ltr To _ltf-1
PokeS(@DataToReplace$+k,"0") ;...then convert spaces to zeros (or instead of "0" to "F")
Next
EndIf
EndIf
EndIf
If length=0 Or StartPosition=<0 Or _ltf<>_ltr Or BufferLen=<0 Or BufferLen<length Or Flags<0
ProcedureReturn -1
EndIf
Protected *searchdata = AllocateMemory((length*2)+BufferLen)
Protected *replacedata = *searchdata+length
Protected *testdata.Character = *replacedata+length
If *searchdata=0
ProcedureReturn -2
EndIf
If Flags & #STRINGMODE ; if string search...
If Not Flags & #CASESENSITIVE
DataToFind$=UCase(DataToFind$)
EndIf
PokeS(*searchdata ,DataToFind$)
PokeS(*replacedata,DataToReplace$)
Else ; if hex search...
For k=0 To length-1
PokeB(*searchdata +k,Val("$"+PeekS(@DataToFind$ +(k*2),2)))
PokeB(*replacedata+k,Val("$"+PeekS(@DataToReplace$+(k*2),2)))
Next
EndIf
If FileSize(File$)>=0 ;OpenFile() creates file if it doesn't exist --> we don't want that so we check it before if it exists
Protected file = OpenFile(#PB_Any, File$) ;if someone deletes file before this line is executed then we create empty file :( but probability of this is so small that we simply ignore it
If file
Protected readpos = StartPosition-1
Protected thiseof = Lof(file) - length
Protected replacecount = 0
While (Not Eof(file)) And readpos <= thiseof
FileSeek(file, readpos)
Protected DataRead=ReadData(file, *testdata, BufferLen)
If Flags & #STRINGMODE
If Not Flags & #CASESENSITIVE
For k=0 To DataRead-1 ;we can't convert it to uppercase at once because it could have chr(0) in the middle so we have this loop
*testdata\c = Asc(UCase(Chr(*testdata\c))) ;*testdata\c is a little faster than PeekC()
*testdata+1 ;optionally: create structure with chr.c[0] and then use *testdata\chr[k] in previous line instead of this
Next
*testdata-DataRead ;return pointer to first byte
EndIf
EndIf
;Debug "Buffered: "+PeekS(*testdata,DataRead)
For k=0 To DataRead-length
;Debug "> Test: "+PeekS(*testdata+k,length) + " == " + PeekS(*searchdata,length)
If CompareMemory(*testdata+k, *searchdata, length)
FileSeek(file, readpos+k)
;Debug "Replacing data..."
WriteData(file, *replacedata, length)
result=readpos+k+1 ;save position
replacecount+1
If ((DataRead-length)-k)=<length
readpos+(2*length+k-DataRead-1)
EndIf
k+(length-1) ;skip comparing replaced characters in this loop
If Flags & #REPLACEONE
Break 2
EndIf
EndIf
Next
readpos + (DataRead - (length-1))
Wend
CloseFile(file)
Else
result=-3
EndIf
Else
result=-4
EndIf
FreeMemory(*searchdata)
If *Count<>0
PokeI(*Count,replacecount)
EndIf
ProcedureReturn result
EndProcedure
Define counter.i
Global ddd.i = ReplaceDataInFile("E:\my-app.exe", "66696e64206d65", "66696e64207975", 1, #FILLDATA, 4096, @counter)
Debug ddd
Select ddd
Case -4,-3,-2,-1
MessageRequester("Error","Procedure failed!",#MB_ICONERROR)
Case 0
MessageRequester("","No replacements made.")
Default
MessageRequester("Success","Number of replacements made: "+Str(counter))
EndSelect
Re: How to search HEX value and replace all it
Posted: Tue Jun 25, 2024 2:44 pm
by Axolotl
<OT>
I really like you guys for trying to help here.
However, I do not understand how help can be provided.
What does it mean when someone is not even willing or able to execute a single command without error?
Programming does require a bit of analysis, research and testing.

I don't think so any more, as you can easily get help from forums with the support of natural intelligence and (in the near future) artificial intelligence.
I'm sorry, but sometimes I can't help myself.

</OT>
Re: How to search HEX value and replace all it
Posted: Tue Jun 25, 2024 4:52 pm
by boddhi
Little hint: You need to inspect the way search and replace strings are stored in and retrieved from memory.
Re: How to search HEX value and replace all it
Posted: Wed Jun 26, 2024 6:36 am
by hoangdiemtinh
I found a module ( it's belong to C# ). Please convert it to PB.
Code: Select all
namespace ClassicPatcher
{
internal class Patch
{
private static bool DetectPatch(byte[] sequence, int position, byte[] FindHex)
{
if (position + FindHex.Length > sequence.Length) return false;
for (int p = 0; p < FindHex.Length; p++)
{
if (FindHex[p] != sequence[position + p] && FindHex[p] != 0x3F) // Check for wildcard byte 0x3F ('?')
return false;
}
return true;
}
internal static byte[] StringToByteArray(string hex)
{
hex = hex.Replace(" ", "");
int NumberChars = hex.Length;
byte[] bytes = new byte[NumberChars / 2];
for (int i = 0; i < NumberChars; i += 2)
{
if (hex.Substring(i, 2) == "??")
bytes[i / 2] = 0x3F; // Set wildcard byte 0x3F ('?')
else
bytes[i / 2] = Convert.ToByte(hex.Substring(i, 2), 16);
}
return bytes;
}
internal static bool PatchFile(string originalFile, string findHex, string patchHex)
{
bool b = false;
if (File.Exists(originalFile))
{
byte[] ReplaceHex = StringToByteArray(patchHex);
byte[] FindHex = StringToByteArray(findHex);
// Read file bytes.
byte[] fileContent = File.ReadAllBytes(originalFile);
// Detect and patch the file.
for (int p = 0; p < fileContent.Length; p++)
{
if (!DetectPatch(fileContent, p, FindHex)) continue;
for (int w = 0; w < ReplaceHex.Length; w++)
{
b = true;
fileContent[p + w] = ReplaceHex[w];
}
}
File.WriteAllBytes(originalFile, fileContent);
}
return b;
}
internal static void PatchOffset(string originalFile, string offset, string patchHex)
{
byte[] ReplaceHex = StringToByteArray(patchHex);
int off = Convert.ToInt32(offset, 16);
// Read file bytes.
byte[] fileContent = File.ReadAllBytes(originalFile);
// Detect and patch the file.
for (int p = 0; p < fileContent.Length; p++)
{
//if (p >= off) continue;
for (int w = 0; w < ReplaceHex.Length; w++)
{
fileContent[off + w] = ReplaceHex[w];
}
}
File.WriteAllBytes(originalFile, fileContent);
}
internal static bool PatternExists(string originalFile, string findHex)
{
byte[] FindHex = StringToByteArray(findHex);
// Read file bytes.
byte[] fileContent = File.ReadAllBytes(originalFile);
// Detect and patch the file.
for (int p = 0; p < fileContent.Length; p++)
{
if (DetectPatch(fileContent, p, FindHex))
{
return true;
}
}
return false;
}
}
}