Archive: Search In EXE and return Offset


Search In EXE and return Offset
Is it possible to search an exe for a string or hex code and return the offset of the first match ?


FileReadByte might do what you need.

-Stu


but how does FileReadByte search ? In a loop ? That would take forever since the file I'm searching in is around 1.60 MBs


That's how searching is done if you think about it...
As long as you call it inside a Function it shouldn't take that long at all.

-Stu


well I've been trying to edit this function so that it searches only once and returns only the offset of the first byte of the string... No luck yet! If you can help me out I'd appreciate it.


I'm not sure how you'd do the comparison exactly, but a simple loop would be:


FileOpen $R0 "$INSTDIR\file.exe" r
StrCpy $R2 -1 # return -1 if not found
StrCpy $R3 0
Loop:
ClearErrors
FileReadByte $R0 $R1
IfErrors Done

IntOp $R3 $R3 + 1
StrCmp $R1 ... 0 Loop
StrCpy $R2 $R3

FileClose $R0

# At this point $R2 is the byte #, or -1.


-Stu

yes! thanks for that... but now how do I implement it to search for an specified string and not just a byte ?


Hmm that would be quite a bit more complicated.
If the string was 5 bytes in length for example you'd have to grab the first 5 bytes starting at offset 0, 5 bytes starting at offset 1, offset 2 and so on.

How about this plugin:
http://nsis.sourceforge.net/TextReplace_plugin

-Stu


TextReplace cannot search in a binary file. Gives the following: "input file is binary or wide character Unicode file"


I think what Afrow meant was to use his search example for binary file searches and to use the TextReplace plugin for text file searches.


The TextReplace plugin seems to have an error code specifically for binary files, so you could use this to detect whether the file was binary or text (if you needed that type of test).


Originally posted by kookh
yes! thanks for that... but now how do I implement it to search for an specified string and not just a byte ?
Well, duh... after you get 1st character match from that loop, you have to add another loop to check byte by byte if the rest of the string matches too.

Var BSS_Filename
Var BSS_String
Var BSS_Offset

Function BinStrSearch
Push $0
Push $1
Push $2
Push $R0
Push $R1
Push $R2
StrLen $R0 $BSS_String
StrCmp $R0 0 @errors
StrCpy $BSS_Offset 0
FileOpen $R2 $BSS_Filename r
DetailPrint 'File $\"$BSS_Filename$\" :'
StrCpy $1 $BSS_String 1 0 ;1st_chr
@loop_1st_char:
ClearErrors
FileSeek $R2 $BSS_Offset
FileReadByte $R2 $R1
IfErrors @errors
IntOp $BSS_Offset $BSS_Offset + 1
IntFmt $R1 "%c" $R1
StrCmp $1 $R1 0 @loop_1st_char
StrCpy $0 $R0
@loop_the_rest:
IntOp $0 $0 - 1
StrCmp $0 0 @loop_end
StrCpy $2 $BSS_String 1 -$0
FileReadByte $R2 $R1
IntFmt $R1 "%c" $R1
StrCmp $2 $R1 @loop_the_rest
Goto @loop_1st_char
@loop_end:
IntOp $BSS_Offset $BSS_Offset - 1
IntFmt $BSS_Offset "0x%X" $BSS_Offset
DetailPrint 'String $\"$BSS_String$\" is at offset $BSS_Offset'
Goto @done
@errors:
DetailPrint 'String $\"$BSS_String$\" not found!'
@done:
FileClose $R2
Pop $R2
Pop $R1
Pop $R0
Pop $2
Pop $1
Pop $0
FunctionEnd


Case insensitive. If you need sensitive, you know what to do.
Stops after first match. If you need to find all matches, it's easy enough to change too.

that's it. Thank you !