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?

huangapple go评论76阅读模式
英文:

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-&gt;e_shoff);
Elf64_Shdr sh_str_section = section_h_arr[elf_header-&gt;e_shstrndx];
char *sh_str_tbl = (char*)elf + sh_str_section.sh_offset;
Elf64_Half sections_amount = elf_header-&gt;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(&quot;func name %s\n&quot;,symbol_name);
for (int j = 0; j &lt; elf_header-&gt;e_shnum; j++) {
printf(&quot;[%2d] %s\n&quot;, j, sh_str_tbl + section_h_arr[j].sh_name);
}
for(int i = 0; i &lt; sections_amount; i++) {
if(section_h_arr[i].sh_type==SHT_RELA){
printf(&quot;rela is - [%2d] %s\n&quot;, 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&lt;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(&quot;current symbol - %s\n&quot;,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.

huangapple
  • 本文由 发表于 2023年7月6日 19:08:40
  • 转载请务必保留本文链接:https://go.coder-hub.com/76628182.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定