我正在修补(静态链接)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条目没有效果。
我正在尝试从文件的两个单独“页面”拼凑 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 中观察到的。