ELF phdr:将来自多个可执行文件范围的内存页拼凑在一起

问题描述 投票:0回答:1

我正在修补(静态链接)ELF 可执行文件。 我想从二进制文件的多个不同部分在虚拟地址空间中创建页面。

这是我想要实现的一个简单案例的可视化。

|
标记内存页面边界):

file: |aabb|ccdd|
mem:  |aadd|

前半页来自文件第一页大小范围的前半部分,后半页来自第二页大小范围的后半部分,所以每一块的对齐都是在其范围内的。

是否有可能以任何方式实现这一目标?

我修改了一个二进制文件,使其具有以下程序头表(打印有

readelf -l

Elf file type is EXEC (Executable file)
Entry point 0x401520
There are 12 program headers, starting at offset 64

Program Headers:
  Type           Offset             VirtAddr           PhysAddr
                 FileSiz            MemSiz              Flags  Align
  LOAD           0x0000000000560000 0x0000000000400000 0x0000000000400000
                 0x0000000000000040 0x0000000000000040  R      0x1000
  LOAD           0x0000000000001270 0x0000000000400270 0x0000000000400270
                 0x00000000000002c8 0x00000000000002c8  R      0x1000
  LOAD           0x0000000000002000 0x0000000000401000 0x0000000000401000
                 0x0000000000075ac1 0x0000000000075ac1  R E    0x1000
  LOAD           0x0000000000078000 0x0000000000477000 0x0000000000477000
                 0x0000000000027053 0x0000000000027053  R      0x1000
  LOAD           0x000000000009f7d8 0x000000000049f7d8 0x000000000049f7d8
                 0x0000000000005ab8 0x000000000000b288  RW     0x1000
  LOAD           0x0000000000000000 0x00000000004ab000 0x00000000004ab000
                 0x00000000000002e0 0x00000000000002e0  R      0x1000
  NOTE           0x0000000000001270 0x0000000000400270 0x0000000000400270
                 0x0000000000000040 0x0000000000000040  R      0x8
  NOTE           0x00000000000012b0 0x00000000004002b0 0x00000000004002b0
                 0x0000000000000044 0x0000000000000044  R      0x4
  TLS            0x000000000009f7d8 0x000000000049f7d8 0x000000000049f7d8
                 0x0000000000000018 0x0000000000000060  R      0x8
  GNU_PROPERTY   0x0000000000001270 0x0000000000400270 0x0000000000400270
                 0x0000000000000040 0x0000000000000040  R      0x8
  GNU_STACK      0x0000000000000000 0x0000000000000000 0x0000000000000000
                 0x0000000000000000 0x0000000000000000  RW     0x10
  GNU_RELRO      0x000000000009f7d8 0x000000000049f7d8 0x000000000049f7d8
                 0x0000000000003828 0x0000000000003828  R      0x1

正如您所看到的,我正在尝试从文件的两个单独的“页面”拼凑

0x400000
处的内存页面:来自偏移量
0x40
的“页面”的第一个
0x560000
字节,其余来自那个在偏移
0x1000
.

当我在 GDB 中运行可执行文件时,

info proc mappings
有以下输出:

          Start Addr           End Addr       Size     Offset  Perms  objfile
            0x400000           0x401000     0x1000     0x1000  r--p   <the executable>
            0x401000           0x477000    0x76000     0x2000  r-xp   <the executable>
            0x477000           0x49f000    0x28000    0x78000  r--p   <the executable>
            0x49f000           0x4a6000     0x7000    0x9f000  rw-p   <the executable>
            0x4a6000           0x4ab000     0x5000        0x0  rw-p   
            0x4ab000           0x4ac000     0x1000        0x0  r--p   <the executable>
      0x7ffff7ff9000     0x7ffff7ffd000     0x4000        0x0  r--p   [vvar]
      0x7ffff7ffd000     0x7ffff7fff000     0x2000        0x0  r-xp   [vdso]
      0x7ffffffde000     0x7ffffffff000    0x21000        0x0  rw-p   [stack]
  0xffffffffff600000 0xffffffffff601000     0x1000        0x0  --xp   [vsyscall]

好像我的第一个phdr条目没有效果。

linux ld elf
1个回答
0
投票

我正在尝试从文件的两个单独“页面”拼凑 0x400000 处的内存页面

那是行不通的:内核将一次“解释”并执行

LOAD
“指令”。给定:

  LOAD           0x0000000000560000 0x0000000000400000 0x0000000000400000
                 0x0000000000000040 0x0000000000000040  R      0x1000
  LOAD           0x0000000000001270 0x0000000000400270 0x0000000000400270
                 0x00000000000002c8 0x00000000000002c8  R      0x1000

内核会做(相当于)

mmap(0x400000, 0x400, PROT_READ, MAP_FIXED, fd, 0x560000);
mmap(0x400000, 0x400, PROT_READ, MAP_FIXED, fd,   0x1000);

第二个

mmap
将替换第一个,这正是您在 GDB 中观察到的。

© www.soinside.com 2019 - 2024. All rights reserved.