通过读取maps信息获取可执行文件头装载的地址

1. 通过maps文件获取进程的文件头和段表

想要实现这一功能,根据书上所写,首先要找到代码段的首地址BaseVaddr,然后文件头就从这个地址开始,用ptrace从这个地址读一个sizeof(Elf64_Ehdr)大小的数据出来就可以了

但是,我在实现的时候遇到的一个问题,读出来的结果压根不对,其结果如下所示

$ sudo ./reconstruct 12127
BaseVaddr: 0x401000
ELF header:

magic:    f3 f 1e fa ff ff ff ff 48 8b 5 e9 ff ff ff ff 
 Type:                               c085
 Machine:                            274
 Version:                            0
 Entry point address:                c308c4
 Start of Program header:            2fe235ff
 Size of program header:             65535 (bytes)
 Number of Program headers:          61952
 Size of section header:             57833 (bytes)
 Number of Section headers:          65535
 Section header string table index:  65535

正常64为ELF文件的前四个字节应该为\0x7fELF,而这里是个啥???

2. 手动查看maps文件

R98avD.png
从上图可以发现,它跟网上很多博客给出来的并不是完全一样,在权限为r-xp的代码段上面还有一个权限为r--p的段,且其映像文件也是test

3. 尝试BaseVaddr

因此我去尝试着将BaseVaddr设置为固定值0x400000,继续运行代码得出如下结果:

$ sudo ./reconstruct 12127
BaseVaddr: 0x400000
correct!
ELF header:

magic:    7f 45 4c 46 0 0 0 0 0 0 0 0 0 0 0 0 
 Type:                               2
 Machine:                            3e
 Version:                            0
 Entry point address:                0x401070
 Start of Program header:            64 (bytes into file)
 Flags:                              0x0
 Size of this header:                0 (bytes)
 Size of program header:             0 (bytes)
 Number of Program headers:          13
 Size of section header:             64 (bytes)
 Number of Section headers:          0
 Section header string table index:  0

对比一下用readelf读出来的文件头

$ readelf -h ./test
ELF Header:
  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 
  Class:                             ELF64
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              EXEC (Executable file)
  Machine:                           Advanced Micro Devices X86-64
  Version:                           0x1
  Entry point address:               0x401070
  Start of program headers:          64 (bytes into file)
  Start of section headers:          14728 (bytes into file)
  Flags:                             0x0
  Size of this header:               64 (bytes)
  Size of program headers:           56 (bytes)
  Number of program headers:         13
  Size of section headers:           64 (bytes)
  Number of section headers:         31
  Section header string table index: 30

可以发现其大部分是对上了,但是有一些数据是对不上的,比如DataVersionOS/ABISize of this headerSize of program header都是对不上的,段的数量却是正确的

4. 结论

虽然上面还是有一些数据对不上,但是有一个结论,那就是在这种情况下,系统实际装载可执行文件的时候,是将文件头和段表等信息作为r--p权限的段,并将其与实际的代码段分开

5. 修正

出现上面有些许不对的,是我自己的代码问题,在64位平台中的gcc环境下,unsigned long是8个字节,ptrace每次读取的是4个字节,而我用8个字节去存4个字节的数据就出现上面的错误了。现在数据是对的了

$ sudo ./reconstruct 13483
BaseVaddr: 0x400000
correct!
ELF header:

magic:    7f 45 4c 46 2 1 1 0 0 0 0 0 0 0 0 0 
 Type:                               2
 Machine:                            3e
 Version:                            1
 Entry point address:                401070
 Start of Program header:            64 (bytes into file)
 Flags:                              0x0
 Size of this header:                64 (bytes)
 Size of program header:             56 (bytes)
 Number of Program headers:          13
 Size of section header:             64 (bytes)
 Number of Section headers:          31
 Section header string table index:  30
posted @ 2021-06-18 22:27  bunner  阅读(118)  评论(0编辑  收藏  举报