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

小编典典

在Linux上,dlopen不返回加载ELF二进制文件的地址。而是返回struct

link_map具有.l_addr成员的成员。因此,您需要以下内容:

struct link_map *lm = (struct link_map*) dlopen(0, RTLD_NOW);

printf("%p\n", lm->l_addr);

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

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

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

#ifndef _GNU_SOURCE

#define _GNU_SOURCE

#endif

#include

#include

#include

static int

callback(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%zx\n",

base + first_load->p_vaddr, first_load->p_vaddr, info->dlpi_addr);

return 1;

}

}

}

return 0;

}

int

main(int argc, char *argv[])

{

dl_iterate_phdr(callback, NULL);

exit(EXIT_SUCCESS);

}

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

$ gcc -g t.c -ldl -m32 && ./a.out

ELF header is at 0x8048000, image linked at 0x8048000, relocation: 0x0

$ gcc -g t.c -ldl -m32 -pie -fPIE && ./a.out

ELF header is at 0xf779a000, image linked at 0x0, relocation: 0xf779a000

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

2020-06-07

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值