英文:
How to access the address of a function I bring from a shared object in a debugger using ELF file, RELA and then finding it in GOT?
问题
以下是代码部分的中文翻译:
我有一个.exe文件的名称和我正在寻找的函数。我知道它是来自共享对象的全局函数。
我搜索了RELA部分,然后通过使用sh_link找到了dynsym和dynstr。
所以通过使用每个RELA条目的索引,我在dynstr中找到了符号的名称,然后返回了具有与我获得的函数相同的符号名称的RELA条目的偏移量。
然后在调试器中,我使用了ptrace和peektext来找到偏移量所包含的数据。
但似乎不起作用。我漏掉了什么?
它确实返回给我偏移量,但无法给我GOT的地址。有时它甚至找不到我正在寻找的符号。
另外我应该提到,这个问题仅使用了懒绑定。
代码:
unsigned long find_symbol_address(const char* symbol_name, const char* executable_path) {
int elf_fd = open(executable_path, O_RDONLY);
void *elf = mmap(NULL, lseek(elf_fd, 0, SEEK_END), PROT_READ, MAP_PRIVATE, elf_fd, 0);
Elf64_Ehdr* elf_header = (Elf64_Ehdr*)elf;
Elf64_Shdr* section_h_arr = (Elf64_Shdr*)((char*)elf + elf_header->e_shoff);
Elf64_Shdr sh_str_section = section_h_arr[elf_header->e_shstrndx];
char *sh_str_tbl = (char*)elf + sh_str_section.sh_offset;
Elf64_Half sections_amount = elf_header->e_shnum;
int symbols_amount = 0;
Elf64_Half index_dyn;
Elf64_Half index_str;
Elf64_Rela *rela;
Elf64_Sym *dyn;
char *strtab;
char* curr_symbol_name;
Elf64_Addr offset;
printf("函数名 %s\n",symbol_name);
for (int j = 0; j < elf_header->e_shnum; j++) {
printf("[%2d] %s\n", j, sh_str_tbl + section_h_arr[j].sh_name);
}
for(int i = 0; i < sections_amount; i++) {
if(section_h_arr[i].sh_type==SHT_RELA){
printf("rela 是 - [%2d] %s\n", i, sh_str_tbl + section_h_arr[i].sh_name);
rela=(Elf64_Rela*)((char*)elf + section_h_arr[i].sh_offset);
symbols_amount=section_h_arr[i].sh_size / section_h_arr[i].sh_entsize;
dyn=(Elf64_Sym*)((char*)elf + section_h_arr[section_h_arr[i].sh_link].sh_offset);
strtab = ((char*)elf + section_h_arr[section_h_arr[section_h_arr[i].sh_link].sh_link].sh_offset);
for (int j=0;j<symbols_amount;j++)
{
index_dyn=ELF64_R_SYM(rela[j].r_info);
index_str=ELF64_ST_BIND(dyn[index_dyn].st_info);
curr_symbol_name= strtab + dyn[j].st_name;
printf("当前符号 - %s\n",curr_symbol_name);
if (strcmp(curr_symbol_name,symbol_name)==0)
{
offset=rela[j].r_offset;
return offset;
}
}
}
}
return 0;
}
//在获得偏移量后,我使用以下代码从该地址获取数据。
unc_addr=ptrace(PTRACE_PEEKTEXT, child_pid, offset, NULL);
func_addr=func_addr-6;
希望这对你有所帮助。如果你有任何其他问题,请随时提出。
英文:
I have the name of an exe file and the function I'm looking for. Knowing it's a global function coming from a shared object.
I searched for the section of RELA, and then by using sh_link I found the dynsym and dynstr.
So by using the index of each RELA entry, I found the name of the symbol in dynstr, and then returned the offset of the RELA entry that had the same symbol name as the function I got.
Then in the debugger I used ptrace and peektext to find the data that the offset holds.
However it doesn't seem to work. What am I missing?
It does return me the offset, but can't give me the address from GOT. or sometimes it just doesn't find the symbol I'm looking for.
Also I should mention that the question is only using Lazy binding
Code:
unsigned long find_symbol_address(const char* symbol_name, const char* executable_path) {
int elf_fd = open(executable_path, O_RDONLY);
void *elf = mmap(NULL, lseek(elf_fd, 0, SEEK_END), PROT_READ, MAP_PRIVATE, elf_fd, 0);
Elf64_Ehdr* elf_header = (Elf64_Ehdr*)elf;
Elf64_Shdr* section_h_arr = (Elf64_Shdr*)((char*)elf + elf_header->e_shoff);
Elf64_Shdr sh_str_section = section_h_arr[elf_header->e_shstrndx];
char *sh_str_tbl = (char*)elf + sh_str_section.sh_offset;
Elf64_Half sections_amount = elf_header->e_shnum;
int symbols_amount = 0;
Elf64_Half index_dyn;
Elf64_Half index_str;
Elf64_Rela *rela;
Elf64_Sym *dyn;
char *strtab;
char* curr_symbol_name;
Elf64_Addr offset;
printf("func name %s\n",symbol_name);
for (int j = 0; j < elf_header->e_shnum; j++) {
printf("[%2d] %s\n", j, sh_str_tbl + section_h_arr[j].sh_name);
}
for(int i = 0; i < sections_amount; i++) {
if(section_h_arr[i].sh_type==SHT_RELA){
printf("rela is - [%2d] %s\n", i, sh_str_tbl + section_h_arr[i].sh_name);
rela=(Elf64_Rela*)((char*)elf + section_h_arr[i].sh_offset);
symbols_amount=section_h_arr[i].sh_size / section_h_arr[i].sh_entsize;
dyn=(Elf64_Sym*)((char*)elf + section_h_arr[section_h_arr[i].sh_link].sh_offset);
strtab = ((char*)elf + section_h_arr[section_h_arr[section_h_arr[i].sh_link].sh_link].sh_offset);
for (int j=0;j<symbols_amount;j++)
{
index_dyn=ELF64_R_SYM(rela[j].r_info);
index_str=ELF64_ST_BIND(dyn[index_dyn].st_info);
curr_symbol_name= strtab + dyn[j].st_name;
printf("current symbol - %s\n",curr_symbol_name);
if (strcmp(curr_symbol_name,symbol_name)==0)
{
offset=rela[j].r_offset;
return offset;
}
}
}
}
return 0;
}
//after I get the offset, I used this to get the data from that address.
unc_addr=ptrace(PTRACE_PEEKTEXT, child_pid, offset, NULL);
func_addr=func_addr-6;
答案1
得分: 0
以下是翻译好的部分:
所以这只是一些非常小的东西。
而不是:
curr_symbol_name= strtab + dyn[j].st_name;
我必须使用:
curr_symbol_name= strtab + dyn[index_dyn].st_name;
当从共享对象调用函数时,仍然会遇到一些问题,使我不得不随着时间的推移更改的地址。
英文:
so it was something very minor.
instead of :
curr_symbol_name= strtab + dyn[j].st_name;
I had to use
curr_symbol_name= strtab + dyn[index_dyn].st_name;
It still encounters some problems when a function is being called from a shared object as well, making the address I had to change over the time.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论