pyelftools 重定位节符号

逆向工程 二元分析 静态分析 Python
2021-06-27 04:48:44

最近我一直在尝试进行逆向工程,在玩过 Radare2 之后,我意识到我在玩很多东西而没有真正理解我在做什么。为了纠正这个问题,我决定做一些更多的实践,并用 python 做一些简单的逆向练习。我开始关注这个有点过时的帖子。

https://anee.me/reversing-an-elf-from-the-ground-up-4fe1ec31db4a

我试图在重定位部分中查找符号,似乎一个部分提供了准确的地址,而另一部分没有,我对原因有点不知所措。

我的代码:

import sys
from elftools.elf.elffile import ELFFile
from elftools.elf.relocation import RelocationSection
from elftools.elf.descriptions import describe_reloc_type


def process_file(fname):
    with open(fname, 'rb') as f:
        e = ELFFile(f)
        for section in e.iter_sections():
            if not isinstance(section, RelocationSection):
                continue
            print(f'\n{section.name} with {section.num_relocations()} Sections: ')
            symbol_table = e.get_section(section['sh_link'])
            for relocation in section.iter_relocations():
                symbol = symbol_table.get_symbol(relocation['r_info_sym'])
                addr = hex(relocation['r_offset'])
                type = describe_reloc_type(relocation['r_info_type'], e)
                print(f'{addr}\t{type}\t{symbol.name}')


if __name__ == '__main__':
    if len(sys.argv) == 2:
        process_file(sys.argv[1])

返回:

.rela.dyn with 9 Sections: 
0x3de8  R_X86_64_RELATIVE   
0x3df0  R_X86_64_RELATIVE   
0x4048  R_X86_64_RELATIVE   
0x3fd8  R_X86_64_GLOB_DAT   _ITM_deregisterTMCloneTable
0x3fe0  R_X86_64_GLOB_DAT   __libc_start_main
0x3fe8  R_X86_64_GLOB_DAT   __gmon_start__
0x3ff0  R_X86_64_GLOB_DAT   _ITM_registerTMCloneTable
0x3ff8  R_X86_64_GLOB_DAT   __cxa_finalize
0x4050  R_X86_64_COPY       stdin

.rela.plt with 5 Sections: 
0x4018  R_X86_64_JUMP_SLOT  puts
0x4020  R_X86_64_JUMP_SLOT  printf
0x4028  R_X86_64_JUMP_SLOT  fgets
0x4030  R_X86_64_JUMP_SLOT  strcmp
0x4038  R_X86_64_JUMP_SLOT  malloc

'.rela.plt' 下的所有地址的地址都与我知道的呼叫不匹配。

例如:

--cut--
0x11f0: mov eax, 0
0x11f5: call    0x1040 <<-- This is a call to printf
0x11fa: mov rdx, qword ptr [rip + 0x2e4f]       ** RIP + Offset: 0x4050  - calls: stdin
0x1201: mov rax, qword ptr [rbp - 8]
0x1205: mov esi, 0xa
0x120a: mov rdi, rax
0x120d: call    0x1050 <<-- This is a call to fgets
0x1212: mov rdx, qword ptr [rbp - 0x10]
--cut--

我已经用Radare2验证了这一点,正确的地址似乎如下。

 0x1030     sym.imp.puts                             
 0x1040     sym.imp.printf
 0x1050     sym.imp.fgets
 0x1060     sym.imp.strcmp
 0x1070     sym.imp.malloc

据我所知,这可能是由于动态链接造成的,但我不确定。我一直无法找到一种方法让我的脚本使用我认为合适的地址输出此部分。任何有关此过程如何工作或如何使用 pyelftools 检索所需地址的信息将不胜感激。

1个回答

R_X86_64_JUMP_SLOT重定位应用于GOT(全局偏移表)插槽,给调用指令,你看到。

调用指令转到 .plt 部分中的 PLT(程序链接表)存根,然后这些存根使用 GOT 和.rela.plt重定位来解析并跳转到外部共享对象中的最终符号。这个过程是在动态链接器 ( ld.so)的帮助下发生的,在这个答案框中解释起来有点复杂,但是您可以通过搜索这些术语来找到更多信息。