我有一个可执行文件,我使用objcopy
方法
objcopy --input binary --output elf32-i386 --binary-architecture i386 data.txt data.o
链接到data.o
并使用
extern char _binary_data_txt_start
extern char _binary_data_txt_end
现在可以在可执行文件中更新此数据吗?更新的数据可以具有相同的确切大小,我只需要更改一些位。
在Windows PE文件中,使用UpdateResource()
答案 0 :(得分:3)
没什么特别的,也没什么难的。我将在下面给出正确的顺序,但首先让我稍微纠正你的嵌入方法。让我们不要明确使用objcopy
,让我们使用GNU LD代替在ELF文件中获得正确的条目。
让我们开始吧。这是test-emb.c
文件:
#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;
}
这是名为data.txt
12345678
这是另一种名为newdata.txt
98765432
现在编译并链接:
$ gcc test-emb.c -c -m32
$ gcc -o test-emb test-emb.o -Wl,--format=binary -Wl,data.txt -Wl,--format=default -m32
尝试:
$ ./test-emb
1, 2, 3
现在开始跳舞。第一步:确定数据部分的逻辑和物理地址:
$ readelf -S test-emb | grep "\.data" | awk '{print $4}'
080496b8
$ readelf -S test-emb | grep "\.data" | awk '{print $5}'
0006b8
第二步:开始并确定二进制数据的大小:
$ 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
第三步:做数学。我们确实需要:在数据中找到二进制数据的偏移量,并将其转换为物理起始点:
$ echo $((0x080496c0 - 0x080496b8))
8
echo $((0x0006b8 + 8))
1728
第四步:实际替换(计数值为二进制数据大小,taht为9):
cat newdata.txt | dd of=test-emb bs=1 seek=1728 count=9 conv=notrunc
现在再次检查:
$ ./test-emb
9, 8, 7
一切正常。您可以轻松地将此方法折叠到脚本中,而不是更难使用,即Windows下的UpdateResource,但我想让您了解事情的进展情况。
答案 1 :(得分:2)
当您想要更新二进制文件中的日期时,您只需打开一个您喜欢的文件fopen
iostream
即可。
您还可以在可执行文件运行时修改数据。要修改进程内存中的资源,您必须确保它在可写部分中。在MAP文件中验证这一点。
您可以使用--rename-section
命令的objcopy
参数控制该部分:
objcopy -I binary -O elf32-i386 --rename-section .rodata=.data data.txt data.o
如果您真的想在将elf文件作为进程加载之前更改其内容,则必须阅读elf标头以查找资源数据。当您使用--rename-section将其放在具有自己名称的部分中时,可以更轻松地找到data.txt。
编辑:
elf文件格式太复杂,无法在Stackoverflow答案中描述它。您可以在Wiki page找到基本描述和指向必要规范的链接。
但修改链接器输出文件的最简单方法是生成data.txt
的新版本并运行链接器。
答案 2 :(得分:2)
现在可以在可执行文件中更新此数据吗?更新的数据可以具有相同的确切大小,我只需要更改一些位。
当然:就这样做:
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
}
注意:如果您的_binary_data_txt_start
最终位于.rodata
,则您可能必须mprotect
首先PROT_READ|PROT_WRITE
所在的网页。
注意:如果您希望更新的数据持久以便下次执行二进制文件,那么harper的答案是正确的:只需使用fopen
,寻找更正文件中的位置,并在那里写数据。
这留下了最后一个问题:如何找到正确的地方。如果 是您的问题,请参阅libelf
documentation。