C语言 修改已编译的ELF可执行文件中的全局变量

cmssoen2  于 2023-04-19  发布在  其他
关注(0)|答案(1)|浏览(188)

我有一个类似UPX的程序。它通过全局变量执行包含在可执行文件中的嵌入式程序:

const char programData[] = { 0x12,0x13… }

有没有一种方法可以修改这个变量的值而不需要重新编译程序?
我不希望我的用户必须安装整个构建工具链来更改嵌入的可执行文件,也不希望由于环境限制而使用外部文件

j0pj023g

j0pj023g1#

我将添加两个变量,首先是blockSize,然后是大块的programData
我认为你需要存储数据的大小,因为 * 可能 * 有效负载程序的大小可能会改变。
如果你构建了这个简单的可执行文件:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>

#define MAX_BLOCK_SIZE 8192ul   // probably much bigger in practice

uint64_t blockSize = MAX_BLOCK_SIZE;
uint8_t  programData[ MAX_BLOCK_SIZE ] = {
                                            0xf0, 0x0d, 0xf0, 0x0d, 0xf0, 0x0d, 0xf0, 0x0d,
                                            0xf0, 0x0d, 0xf0, 0x0d, 0xf0, 0x0d, 0xf0, 0x0d,
// ... huge block of MAX_BLOCK_SIZE~sized initialisation data, 
                                            0xf0, 0x0d, 0xf0, 0x0d, 0xf0, 0x0d, 0xf0, 0x0d,
                                         };

int main( int argc, char **argv )
{
    fprintf( stderr, "Maximum block size is %lu bytes\n", MAX_BLOCK_SIZE );
    fprintf( stderr, "Used block size is %lu bytes\n", blockSize );

    return 0;
}

可以使用类似十六进制编辑器的东西来检查可执行文件的字节。编译器会将初始化字节嵌入到可执行文件中。很容易看到大小和块在可执行文件中的位置(注意hexdump输出来自gcc/Linux/x86-64):

0001000 0000 0000 0000 0000 1008 0020 0000 0000
0001010 0000 0000 0000 0000 0000 0000 0000 0000
0001020 2000 0000 0000 0000 0000 0000 0000 0000
0001030 0000 0000 0000 0000 0000 0000 0000 0000
0001040 0df0 0df0 0df0 0df0 0df0 0df0 0df0 0df0
*
0003040 4347 3a43 2820 6255 6e75 7574 3720 352e

上面的大小和字节在哪里很清楚:0x 1020和0x 1040。但如果不使用一些容易识别的常见模式,例如0x 88558855...
接下来,编写 * 另一个 * 程序,打开可执行文件进行读/写-就像任何二进制数据文件一样,然后用有效负载可执行文件的详细信息覆盖blockSizeprogramData。也许 stdio 函数fseek()fwrite()会使这变得微不足道。

相关问题