问题
I have an executable in which I embed a binary file resource using the objcopy
method
objcopy --input binary --output elf32-i386 --binary-architecture i386 data.txt data.o
link to data.o
and use
extern char _binary_data_txt_start
extern char _binary_data_txt_end
Is it possible now to update this data inside the executable? The updated data can have the same exact size, I just need to change some of the bits.
In windows PE files this is very simple to do using UpdateResource()
回答1:
Nothing special and nothing hard at all. I'll give you correct sequence below, but first let me to correct slightly your embedding method. Lets not use objcopy
explicitly, lets use GNU LD instead to got correct entry inside ELF file.
Lets begin. This is test-emb.c
file:
#include <stdio.h>
extern unsigned char data[] asm("_binary_data_txt_start");
int
main (void)
{
fprintf(stderr, "%u, %u, %u\n", data[0] - '0', data[1] - '0', data[2] - '0');
return 0;
}
This is resource called data.txt
12345678
This is another resource called newdata.txt
98765432
Now compile and link:
$ gcc test-emb.c -c -m32
$ gcc -o test-emb test-emb.o -Wl,--format=binary -Wl,data.txt -Wl,--format=default -m32
Try:
$ ./test-emb
1, 2, 3
Now start dancing. Step one: determine logical and physical address of data section:
$ readelf -S test-emb | grep "\.data" | awk '{print $4}'
080496b8
$ readelf -S test-emb | grep "\.data" | awk '{print $5}'
0006b8
Step two: start and size fo binary data:
$ readelf -s test-emb | grep _binary_data_txt_start | awk '{print $2}'
080496c0
$readelf -s test-emb | grep _binary_data_txt_size | awk '{print $2}'
00000009
Step three: doing math. We do need: find offset of binary data in data, and convert it to physical starting point:
$ echo $((0x080496c0 - 0x080496b8))
8
echo $((0x0006b8 + 8))
1728
Step four: actual replacement (count value is binary data size, taht is 9):
cat newdata.txt | dd of=test-emb bs=1 seek=1728 count=9 conv=notrunc
Now check again:
$ ./test-emb
9, 8, 7
Everything works. You may easily fold this method into script, not harder in use, that UpdateResource under Windows, but I want to give you understanding of how things are going on.
回答2:
Is it possible now to update this data inside the executable? The updated data can have the same exact size, I just need to change some of the bits.
Sure: just do it:
int main()
{
unsigned char *cp = (unsigned char*) _binary_data_txt_start
cp[0] = 'a'; // change first byte to 0x41
cp[42] += 3; // increment 43rd byte by 3
}
Note: if your _binary_data_txt_start
ended up in .rodata
, you may have to mprotect
the pages on which it resides with PROT_READ|PROT_WRITE
first.
Note: if you want the updated data to persist for the next execution of the binary, then harper's answer is correct: just use fopen
, seek to correct place in the file, and write the data there.
That leaves the final question: how to find the correct place. If that is your question, see libelf
documentation.
回答3:
When you want to update the date in the binary you will just open the file with a mean you prefer like fopen
iostream
or what ever.
You can also modify the data when you executable is running. Tho modify the resource in process memory you must be sure that it is in a writable section. Verify this in your MAP file.
You can control the section with --rename-section
argument of the objcopy
command:
objcopy -I binary -O elf32-i386 --rename-section .rodata=.data data.txt data.o
When you really want to change the content of your elf-file before it is loaded as process than you will have to read the elf header to locate the resource data. It's easier to find the data.txt when you place it in section with a name of its own using --rename-section.
Edit:
The elf file format is too complex to decribe it in just an Stackoverflow answer. You find the basic description and links to the necessary specification here at the Wiki page.
But the easiest way to modify the linker output file is to generate a new version of data.txt
and run the linker.
来源:https://stackoverflow.com/questions/26649221/linux-update-embedded-resource-from-executable