- NSIS Discussion
- Hex Editing during install?
Archive: Hex Editing during install?
Pyrii
11th June 2004 20:16 UTC
Hex Editing during install?
I was sure of a function in NSIS that could edit bytes withing binary files, but I'm at a loss, either I'm reading the documentation too fast and missed something. Or it needs special scripting. Basically, what I'm trying to do is make an installer for a edited version of a file, we do all sorts to Game EXEs, from allowing multiple windows, skipping certain annoying checks, reading data from different sources. I wanted to allow the installer to be able to give the user the choice of which features they wanted for once, rather than get an EXE with ALL the different "hacks". Our work is done in Hexadecimal, Offsets and data. I want a script where I can provide the offset and hexidecimal data to be written (Anything from one byte (00 - FF) to hundreds of bytes long.
Gomen if this is alot to ask, if there is such a function and I missed it, then please point me in the right direction, and sorry for being a n00b =P I'm not much of a programmer. Just the only "File Editing" functions seem to be only ASCII Based (txt and ini files).
All help apreciated.
deguix
11th June 2004 22:58 UTC
Yes, all that is possible. (Remember that hexadecimal numbers inside NSIS are identified by the "0x" before the number. i.e.: 0xFF)
You can use FileOpen to open the file (use "a" openmode), FileSeek to go where you want in the fileFileWrite or FileWriteByte to write where you chose and FileClose to close the file. All instructions on how to use them are found on the documentation.
John P.
13th June 2004 16:59 UTC
Hi.
I'm in a similar situation as Pyrii, and I'd like some help.
I have searched the forums and the FAQ and example files and such, and have found some things I can use I think. The problem is I'm not a coder, and I'm just too thick to get into my head exactly what to write in my installer script to make it work.
(sorry - this is not an attempt at "hijacking" the thread, I just thought that since a thread with such a similar problem was already posted, I would reply here instead of making a new thread)
OK, here's the deal:
There is a game that I have made some high resolution textures for. Luckily for me, this game is very easy to customize. All I have to do to make the game use my higher res textures, is to hex edit some game files, so that the game doesn't find the original texture names inside those files.
The game will then automatically look for the texture name in a DynamicallyLoaded folder, and if it finds a texture there with the same name as the file it missed inside the game file, it will use that texture in place of the original, even though the new texture is of a higher resolution.
Now - that's all well and good. But I can't very well tell people who download my textures that they have to hex edit these game files one by one, editing sometimes multiple strings inside them.
So after some head scratching, I finally had an "aha!!" moment, and figured the most obvious answer would be to batch hex edit these files.
And I actually made installers that does this, and they work. So everyone should be happy, right?
Well - it turns out that I did this in the most clumsy and awkward way. What my installers are currently doing, is to extract a folder with a hex editor inside it, then run a .bat file that runs a script for that hex editor, so that it batch hex edits the game files. When it's done, it deletes the hex editing tool's folder. On uninstall, the hex editor in it's folder is again extracted, and an UNDO script is run(basically reversing what the install did).
*phew*
But then I thought that it would be much better if I could somehow make my installer run the hex editor from inside, instead of exctracting it and then running it.
And so I came here, looking for an answer.
And from your posts in this thread, it looks like my NSIS installer will be able to hex edit the files in question without the need for an external hex editor.
Which is great news.
But now I need to get an example of how exactly to make this work. I think I have found the examples, it's just that I have no idea what to put in place of the file_handle, user_var, and other such function examples. Again, I'm no coder.
What I have gathered so far, is that I could perhaps use FileOpen, FileSeek, FileWrite, and FileClose. I just don't get how.
The files I want to open(hex edit), are called: Kernel_GFXALL.ibt and MainMenu_GFXALL.ibt.
I need my installer to search through them one at a time, for the same file names, and change them. As an example, one file name inside the .ibt files would be swooshc01, and I want to rename it so that it's called bwooshc01.
Likewise, I want the other file names I need to change to have their first letter changed to a 'b'.
This has to be done in both of the .ibt files(maybe a lot more of them later on, but for now it's those two).
So in essense; I need to open a file(the .ibt), find a specific string[where the texture name is](how do I find the "name" of the string, btw? Line number?), change a letter(or hex number) in that string, search for the next string with a given texture name, change a letter in that string, and so on, then save the altered .ibt file.
And it needs to do this for both of the files.
Could someone please give me an example of a script that would do this?
I need to be spoon fed! :hang:
I'm not asking you to do it all for me, I just need it explained in simple terms. I got my installer working this far because I found examples by searching these forums that I could use by pretty much just replace the names in the example with my own, plus some trial and error.
Thanks in advance. :)
PS: Sorry about the long post, just thought I'd try to explain exactly what I need and why.
John P.
13th June 2004 23:11 UTC
OK.
I have tried to get my head around my problem, and read a lot of example files and the NSIS Scripting Reference, and I can now make a script that will actually successfully make an .exe that will hex edit the files in question.
But...
The way I have to do it, seems to be that I have to find the placement of the first byte in the name I wish to alter, and write that exact address in the FileSeek part of the script. When I do that, the resulting .exe file does successfully overwrite the string that I specified inside the .ibt file.
But it's just sooo exhausting having to open a hex editor to find the exact placement of each and every filename inside the .ibt file...
Not to mention that even though it's the same file names in the two(or more) .ibt files, they are not placed at the same address in both files, so I'll have to go through the same tedious work for all the .ibt files I wish to change...
The external hex editor I'm currently using with my installers(xvi32), has a nifty script where I just have to tell it to REPLACEALLASC, which means it will search for and replace all occurances of an ASCII string to what I specify.
Is that possible to do with NSIS?
-Just tell it to search for a string(ASCII name or hex string), then make it change all the entries it finds to what I have specified?
Instead of the tedious work of having to find each and every address manually?
Below is a very short example of what I currently have.
This will of course be much bigger when it covers all the filenames, and it will also be just a small part of the rest of my installers, this is just to show what I've got so far when it comes to hex editing the files in question.
The "bwooshc01" is the name I'm replacing the original with, and 37669 is the address of the first byte in 'swooshc01', which is the word I want to overwrite:
Name "TEST"
OutFile "TEST.exe"
Section ""
FileOpen $2 "$DESKTOP\New installer TEST\Kernel_GFXALL.ibt" a
FileSeek $2 37669 SET
FileWrite $2 "bwooshc01"
FileClose $2
SectionEnd
Thanks.
Joost Verburg
13th June 2004 23:28 UTC
You can use NSIS commands to search for data, there are some examples available in the NSIS Archive.
John P.
14th June 2004 14:00 UTC
Well, I've been reading 'till my eyes bleed, but I can't seem to find exactly what I want.
Most of the 'replace string' scripts are for .txt files it seems, and they create and delete a temp file, which I don't want.
I just want to search a binary file for all occurances of a word, then convert all the instances of that word to some other word that I specify. That's all. If I could write that word in ASCII, that would be great.
I found a script that is made for doing just that, but it's for editing a .txt file as far as I can gather.
Since I don't want it to create a temp file, but rather that it should just write directly to the file in question, I tried to edit the script to do only what I need.
It does compile alright, but the resulting .exe doesn't do anything to the binary file (.ibt), as far as I can tell. It sure doesn't do what I want it to do, at least.
So could someone at least tell me why this script doesn't do anything to the binary file?
Can I use this script at all?
Do I need to write the words out in hex? (they are there as text as well in the file)
And where does he get the '0' and '+3' numbers from, and should I use different numbers there for my script?
My version:
Name "TEST"
OutFile "TEST.exe"
Section
ClearErrors
FileOpen $0 "$DESKTOP\New installer TEST\Kernel_GFXALL.ibt" "a"
loop:
FileRead $0 $2
IfErrors done
StrCmp $2 "swooshc01" 0 +3
FileWrite $0 "bwooshc01"
Goto loop
StrCmp $2 "swooshc01" 0 +3
FileWrite $0 "bwooshc01"
Goto loop
FileWrite $0 $2
Goto loop
done:
FileClose $0
SectionEnd
Original version:
ClearErrors
FileOpen $0 "file.txt" "r"
GetTempFileName $R0
FileOpen $1 $R0 "w"
loop:
FileRead $0 $2
IfErrors done
StrCmp $2 "line to replace$\r$\n" 0 +3
FileWrite $1 "replacement of line$\r$\n"
Goto loop
StrCmp $2 "line to replace" 0 +3
FileWrite $1 "replacement of line"
Goto loop
FileWrite $1 $2
Goto loop
done:
FileClose $0
FileClose $1
Delete "file.txt"
CopyFiles /SILENT $R0 "file.txt"
Delete $R0
I have tried some other scripts as well, but even though I get them to compile, they don't do anything either.
The only script I've got working, is the one I posted in my previous post, but that's just a way too exhausting method of doing this.
iceman_k
14th June 2004 14:54 UTC
If I were you, I would continue using the external hex editor instead of twisting myself in knots trying to do it by scripting.
The only thing I would change is to extract the hex editor and the batch file to the $PLUGINS directory. That way it gets automatically deleted when the installer closes.
Even better, instead of trying to script the binary search & replace, you could write it as a plugin using C or Delphi. That way you may end up with a smaller installer as well.
I am pretty sure there is plenty of C code out there to do binary search & replace.
Just my $0.02...
John P.
14th June 2004 15:59 UTC
OK, thanks for the reply.
It does seem to be simpler to use the external hex editor, and it's working 'perfectly' already.
The only reason I was trying to make the installer do the job itself, was to 1) have a smaller .exe, 2) not have to extract and delete a MB at the user's computer. Not that it matters much, I just thought that after umpteen installs of several of my installers, that the write/delete process would make it necessary to defragment their drive.
Hardly a big problem though. Kinda stupid even when I think about it more.
I'll certainly look into using the $PLUGINS directory and maybe even try to make a plugin though.
[edit]-Is the $PLUGINS directory a Windows specific one, or is it the NSIS plugins folder, or does it not matter? 'Cause my "clients" most likely don't have NSIS installed.[/edit]
Heh - by the time I'm done with all this, I'm probably a somewhat decent coder, which is a nice side effect. ;)
Anyway - thanks for the help. :)
iceman_k
14th June 2004 16:57 UTC
Here's a small fast search & replace utility- only 24 kb.
General Search And Replace .
You can either use it as is or convert it to a plugin.
It claims to be blindingly fast.
It is GPL'ed freeware so you should be able to use the source code for the plugin as long as you keep it GPL'ed.
The $PLUGINS directory is a temporary folder created by the installer when it runs, into which it extracts temporary files you may need.
It can be initialized using the InitPluginsDir command- usually in the .onInit function.
John P.
14th June 2004 18:05 UTC
Thank you again. This could be of invaluable help. :)