dliteratephdr遍历linkmap头、获取so加载地址
https://linux.die.net/man/3/dl_iterate_phdr (opens new window)
通过dl_iterate_phdr遍历so的linkmap,获取so加载地址
elf_utils.h
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <stdio.h>
#include <link.h>
#include <string.h>
/**
* ref:
* https://stackoverflow.com/questions/19451791/get-loaded-address-of-a-elf-binary-dlopen-is-not-working-as-expected
* https://linux.die.net/man/3/dl_iterate_phdr
*
**/
typedef struct CbData_t {
char in_so_name[1024]; //input
void *so_addr; //output
size_t so_size; //output
}CbData;
extern "C" int __libc_csu_init(); //near 0x400920
extern "C" int __libc_start_main(); //__libc_start_main@GLIBC_2.2.5
extern "C" int _start(); //near 0x400610
// iterator all shared objects, or iterator unitl this callback return none 0
static int dl_iter_callback(struct dl_phdr_info *info, size_t size, void *data)
{
CbData *cbdata = (CbData *)data;
printf("======dl_iter_callback: %s @ %#lx\n", info->dlpi_name, (unsigned long)info->dlpi_addr);
if(strstr(info->dlpi_name, cbdata->in_so_name)) {
cbdata->so_addr = (char *)info->dlpi_addr;
}
int j;
const char *main_addr = (const char *)&_start;
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 *begin = base + phdr->p_vaddr;
const char *end = begin + phdr->p_memsz;
printf(" in [%s] load %p->%p size=%ld\n", info->dlpi_name, begin, end, end-begin);
if (first_load == NULL) first_load = phdr;
if (begin <= main_addr && main_addr < end) {
// Found PT_LOAD that "covers" callback().
printf(" --main 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);
//elf_header=0x400000, image_link=0x400000, relocation: 0x0
// return 0;
}
}
}
return 0;
}
// get so load addr. so_name should be smaller than 1024
__attribute__((visibility("default")))
void *get_so_addr(const char *so_name) {
if(!so_name) return NULL;
CbData cbdata;
bzero(&cbdata, sizeof(CbData));
strncpy(cbdata.in_so_name, so_name, sizeof(cbdata.so_addr));
dl_iterate_phdr(&dl_iter_callback, &cbdata);
if(cbdata.so_addr) {
return cbdata.so_addr;
}
return nullptr;
}
int main(int argc, char *argv[])
{
void *addr = get_so_addr("libc.so.6");
printf("\nget addr of libc.so.6: %p\n", addr);
addr = get_so_addr("libgcc");
printf("\nget addr of libgcc: %p\n", addr);
printf("main end\n");
getchar(); // cat /proc/`pgrep demo`/maps
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
编辑 (opens new window)
上次更新: 2022/05/03, 12:45:04