获取ELF二进制文件的已加载地址,dlopen无法正常工作

获取ELF二进制文件的已加载地址,dlopen无法正常工作,第1张

获取ELF二进制文件的已加载地址,dlopen无法正常工作

在Linux上,

dlopen
不返回加载ELF二进制文件的地址。而是返回
structlink_map
具有
.l_addr
成员的成员。因此,您需要以下内容:

struct link_map *lm = (struct link_map*) dlopen(0, RTLD_NOW);printf("%pn", lm->l_addr);

但是,尽管有评论

/usr/include/link.h
说,
.l_addr
实际上也不是加载地址。相反,这是ELF图像链接到加载位置与实际加载位置之间的_区别_ 。

对于非PIE主可执行文件,该差异始终为0。对于非预链接的共享库,该差异始终为加载地址(因为非预链接的ELF共享库已链接到地址0的加载)。

那么,如何找到主要可执行文件的基地址呢?最简单的方法是使用以下代码(链接到主要可执行文件中):

#ifndef _GNU_SOURCE#define _GNU_SOURCE#endif#include <link.h>#include <stdio.h>#include <stdlib.h>static intcallback(struct dl_phdr_info *info, size_t size, void *data){  int j;  const char *cb = (const char *)&callback;  const char *base = (const char *)info->dlpi_addr;  const ElfW(Phdr) *first_load = NULL;  for (j = 0; j < info->dlpi_phnum; j++) {    const ElfW(Phdr) *phdr = &info->dlpi_phdr[j];    if (phdr->p_type == PT_LOAD) {      const char *beg = base + phdr->p_vaddr;      const char *end = beg + phdr->p_memsz;      if (first_load == NULL) first_load = phdr;      if (beg <= cb && cb < end) {        // Found PT_LOAD that "covers" callback().        printf("ELF header is at %p, image linked at 0x%zx, relocation: 0x%zxn",    base + first_load->p_vaddr, first_load->p_vaddr, info->dlpi_addr);        return 1;      }    }  }  return 0;}intmain(int argc, char *argv[]){  dl_iterate_phdr(callback, NULL);  exit(EXIT_SUCCESS);}

这是在32位系统上应该看到的内容:

$ gcc -g t.c -ldl -m32  && ./a.outELF header is at 0x8048000, image linked at 0x8048000, relocation: 0x0$ gcc -g t.c -ldl -m32 -pie -fPIE  && ./a.outELF header is at 0xf779a000, image linked at 0x0, relocation: 0xf779a000

(最后一个地址:

0xf779a000
如果启用了地址随机化,则每次运行都会有所不同(应如此))。



欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/zaji/4981950.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-11-14
下一篇2022-11-14

发表评论

登录后才能评论

评论列表(0条)

    保存