How to search HEX value and replace all it

Just starting out? Need help? Post your questions and find answers here.
hoangdiemtinh
User
User
Posts: 97
Joined: Wed Nov 16, 2022 1:51 pm

How to search HEX value and replace all it

Post 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?
Last edited by hoangdiemtinh on Mon Jun 24, 2024 10:40 am, edited 1 time in total.
PC: Windows 10 x64, 8GB RAM. PB ver: 6.x
--
I love PB5 vs PB6 :)
BarryG
Addict
Addict
Posts: 4219
Joined: Thu Apr 18, 2019 8:17 am

Re: How to search HEX value and replace all it

Post by BarryG »

Your post history is VERY concerning.
hoangdiemtinh
User
User
Posts: 97
Joined: Wed Nov 16, 2022 1:51 pm

Re: How to search HEX value and replace all it

Post 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.
PC: Windows 10 x64, 8GB RAM. PB ver: 6.x
--
I love PB5 vs PB6 :)
PBJim
Enthusiast
Enthusiast
Posts: 296
Joined: Fri Jan 19, 2024 11:56 pm

Re: How to search HEX value and replace all it

Post 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.
infratec
Always Here
Always Here
Posts: 7662
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: How to search HEX value and replace all it

Post 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.
hoangdiemtinh
User
User
Posts: 97
Joined: Wed Nov 16, 2022 1:51 pm

Re: How to search HEX value and replace all it

Post 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.
PC: Windows 10 x64, 8GB RAM. PB ver: 6.x
--
I love PB5 vs PB6 :)
infratec
Always Here
Always Here
Posts: 7662
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: How to search HEX value and replace all it

Post by infratec »

Is is correct that he stings have not the same length?

If you really want to replace strings, why not ReplaceString() ?
hoangdiemtinh
User
User
Posts: 97
Joined: Wed Nov 16, 2022 1:51 pm

Re: How to search HEX value and replace all it

Post 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.
PC: Windows 10 x64, 8GB RAM. PB ver: 6.x
--
I love PB5 vs PB6 :)
User avatar
mk-soft
Always Here
Always Here
Posts: 6320
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: How to search HEX value and replace all it

Post 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
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
hoangdiemtinh
User
User
Posts: 97
Joined: Wed Nov 16, 2022 1:51 pm

Re: How to search HEX value and replace all it

Post 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...
PC: Windows 10 x64, 8GB RAM. PB ver: 6.x
--
I love PB5 vs PB6 :)
boddhi
Enthusiast
Enthusiast
Posts: 524
Joined: Mon Nov 15, 2010 9:53 pm

Re: How to search HEX value and replace all it

Post by boddhi »

hoangdiemtinh wrote: and it's long for me to understand...
:shock:
 
Programming does require a bit of analysis, research and testing. :wink:

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!
If my English syntax and lexicon are incorrect, please bear with Google translate and DeepL. They rarely agree with each other!
Except on this sentence...
hoangdiemtinh
User
User
Posts: 97
Joined: Wed Nov 16, 2022 1:51 pm

Re: How to search HEX value and replace all it

Post 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



PC: Windows 10 x64, 8GB RAM. PB ver: 6.x
--
I love PB5 vs PB6 :)
Axolotl
Addict
Addict
Posts: 872
Joined: Wed Dec 31, 2008 3:36 pm

Re: How to search HEX value and replace all it

Post 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. :wink:

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. :oops: :mrgreen:
</OT>
Just because it worked doesn't mean it works.
PureBasic 6.04 (x86) and <latest stable version and current alpha/beta> (x64) on Windows 11 Home. Now started with Linux (VM: Ubuntu 22.04).
boddhi
Enthusiast
Enthusiast
Posts: 524
Joined: Mon Nov 15, 2010 9:53 pm

Re: How to search HEX value and replace all it

Post by boddhi »

hoangdiemtinh wrote: Tue Jun 25, 2024 2:10 pm Why not success ?
 
Little hint: You need to inspect the way search and replace strings are stored in and retrieved from memory.
If my English syntax and lexicon are incorrect, please bear with Google translate and DeepL. They rarely agree with each other!
Except on this sentence...
hoangdiemtinh
User
User
Posts: 97
Joined: Wed Nov 16, 2022 1:51 pm

Re: How to search HEX value and replace all it

Post 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;
        }
    }
}
PC: Windows 10 x64, 8GB RAM. PB ver: 6.x
--
I love PB5 vs PB6 :)
Locked