How to modify the length of an incbin in an exe?

BlitzMax Forums/BlitzMax Programming/How to modify the length of an incbin in an exe?

ImaginaryHuman(Posted 2011) [#1]
I need to modify an already-existing exe which is a compiled blitzmax app containing an incbin'd file. ie

1) Write a blitzmax app which incbins a data file
2) Compile it to a Windows exe
3) Use another blitzmax app to read the exe file, find out where the incbin'd data file starts, `cut it` from the file and `insert` a new data file which may be longer or shorter
4) Be able to correctly execute the modified exe as normal

I can figure out how to find the start of the incbin data in the file by including a codeword at the start of the data file and then searching for it. I can modify the existing incbinned data and it works fine so long as the incbin data stays the same length.

What I can't figure out is where the `length` of the incbin is stored (presumably it's an INT somewhere?) and thus how to modify it so that both blitz and Windows see the exe as `normal` after resizing.

I'm also a little concerned that if I resize the incbin area there may be hardcoded references to the offset of other incbin areas or other portions of the exe which would now be thrown off, but I'm only guessing. I could maybe merge all incbins into one data block at the very end of the app?

Any ideas?

Last edited 2011


xlsior(Posted 2011) [#2]
No idea on how to make this work, but a worth of warning: Many antivirus programs will keep programs from modifying other executables after installation time -- if you are looking at deploying this into the wild you're bound to have a ton of users run into problems with it.

Just something to consider. :-?


ImaginaryHuman(Posted 2011) [#3]
That won't be a problem. I will have an exe which basically writes out a new exe file, based on an included original exe plus the modifications I'm trying to make to it, so it isn't so much modifying an existing file on the computer as it is generating a new one.


ImaginaryHuman(Posted 2011) [#4]
I just tried detecting the start of the incbin data and then writing a bunch of additional bytes to the output file before continuing with the rest of the input file, and it produces an exe which Windows refuses to run. So it might not work but I'll keep trying.


Doc Holliday(Posted 2011) [#5]
Maybe this thoughts will help you getting on the right way:

1. Write a minimal bmax programm with only one incbined file
2. Have a look at the assembler code that the bmax compiler
will produce for this minimal bmax program. In which segment
was your incbin file put?
3. Every EXE under Windows has a PE-Header (google will help ;-)
at the start of the EXE-File in which the different segments
and their lengths are listed. To do the task you want you have
to manipulate these entries in the PE-Header.

I'm not sure if this is the right way but it's an idea where you
can start ...

Doc Holliday


ImaginaryHuman(Posted 2011) [#6]
Yes that's a good idea, thanks.

What I just discovered is that in fact you can write any amount of additional bytes to the end of an exe file and it will still execute fine without any issues. That means I can store a block of custom data at the end of the exe, then when the exe runs it can open ITSELF (its exe file) and jump to the end of the file and backtrack based on a known length of data.

That should work, right? Any reason why that might not be `legal` or safe? I got the idea from here: http://support.microsoft.com/kb/84062

I also read this: The Windows PE file format permits additional data to be appended to the executable file. This data is ignored by the Windows program loader, so we can use the data for our own purposes without affecting the program code.

It also `seems` like the Windows exe loader does not load the extra data at the end of the file (a 100 mb file loaded just as quick as a 1mb file), probably because the PE format doesn't reference it so it just ignores it. That's good :-D No need to load it twice.

Last edited 2011


Doc Holliday(Posted 2011) [#7]
Yes, at the end of an EXE-file this isn't a problem (maybe a problem for some virus scanners like xlsior mentioned in his post above).

But you want to change data somewhere in the middle of the exe and there comes the PE-header into account.

Or you find a way that the bmax compiler puts the incbin at the end of the exe file. But I think this way is more complicated than try to adjust the PE-header.

It's an interesting problem and I would like to hear from you here if you find a way to solve this ...

Doc Holliday


ziggy(Posted 2011) [#8]
Create a string constant in the sample exe with a parsable contents, such as

CURRENTLENGHTIS000000 and then make a copy of the exe with the 000000 modified to with the amount of data appended. The program (the original one) should be coded to self-open, look for CURRENTLENGHTHIS literal and take the next 6 characters as the number of bytes to read from the end of itself.


ImaginaryHuman(Posted 2011) [#9]
Yes that's what I plan to do Ziggy, thanks for explaining.

I can see how a virus checker might throw up a `exe has been modified` kind of thing, given it contains some data that isn't referenced in the PE header. But if I ADD something to the PE header the Windows loader will load it into memory as if it's part of the application.

I suppose if I look at the incbin data and see if it's like `in its own segment` then the segment size could just be modified to allow inclusion of a bigger file. But then in Blitz surely it's not going to know what IncbinLength() is for that file, since it's changed.

I suppose I could go with the append-to-end method which seems way easier, and then just advise customers that if they have virus software they must allow the app to run?


BlitzSupport(Posted 2011) [#10]
Interesting stuff -- you may or may not find this of interest/use:

Read Win32 executable data section names


ImaginaryHuman(Posted 2011) [#11]
Interesting code, thanks for that!


SLotman(Posted 2011) [#12]
It wont't work. Programs usually (in ASM) use offsets (for example, when code jumps for one part to another, it could be an absolute jump (specifying one address) or a relative jump (specifying an offset).

If you change stuff inside the exe file, and if it's bigger os smaller than it already was, then all adresses in memory will change, and it will crash or present some strange errors.

Your best option it's to just recompile the exe, and then create a patch file, to change the old one into the new one.


ImaginaryHuman(Posted 2011) [#13]
Recompilation isn't an option as that would mean distributing blitzmax with the app.

But I do understand about changing the addresses. However, doesn't the PE format automatically translate the addresses upon loading the exe? I guess if I just expand a section of data and there is some code after it the relative addresses would be off and even with modification it'd be wrong?

I mean, it sounds reasonable. That's why I think appending to the end of the exe might be the only option.


TaskMaster(Posted 2011) [#14]
Make the intial EXE with a incbin'd file larger than the file will ever need to be. Then you will always have room to add the data you need to change the file.

Last edited 2011


ImaginaryHuman(Posted 2011) [#15]
I thought of that but the size can vary from 1 megabyte to several hundred potentially and having a huge file `just in case` it's not big enough for the payload is not an option.


SLotman(Posted 2011) [#16]
Recompilation isn't an option as that would mean distributing blitzmax with the app.

You don't send the source to the user to compile.

You compile on your local machine, then you make a patch file - which will patch an older EXE to a new one. You distribute this patch file alongside a 'patcher' program, and that's it.

There are even some installers that support 'patch installations'! Much better and less hassle than having to mess with data inside the EXE!

Last edited 2011


ImaginaryHuman(Posted 2011) [#17]
That's not going to be dynamic enough. To make the patch I would need to have the modified exe compiled in blitz also and that's not possible, it gets modified in the hands of my customers and the payload is added by them, then passed onto their customers.


Shortwind(Posted 2011) [#18]
Is there a solid requirement that the data be in the .exe file? Just wondered, because wouldn't it be easier to implement all the data in a sqlite encrypted database file?

Then the executable never changes. You then still only need to modify one file, and distribute that. All settings, ect, can be stored in the sqlite database file, and be "secure." (If your worried about security.)

:)


ImaginaryHuman(Posted 2011) [#19]
Yes it must be an exe, it has to be able to be instantly `run` when downloaded from a web browser. And the exe itself contains some code which must run in additional to the data that's added to it.

Last edited 2011