2016-03-19 53 views
1

我想编写一个python脚本,它从知道它的地址(例如0x437310和size)的elf二进制文件中提取函数操作码。我怎样才能将这个地址映射到二进制文件中相应的偏移量以开始读取?从ELF二进制文件中提取函数字节

使用十六进制编辑器我可以计算出0x437310处的函数从hexdump中的偏移量0x37310开始。

如何以通用方式计算此值,因为二进制文件的imagebase并不总是相同。

任何帮助将不胜感激

+0

请附上(相关)样本ELF文件。 – boardrider

回答

0

比方说,我想从bash提取maybe_make_export_env的说明。

你想要做的第一件事就是找到符号表这个符号:

$ readelf -s /bin/bash 
    Num: Value   Size Type Bind Vis  Ndx Name 
[...] 
    216: 000000000043ed80 18 FUNC GLOBAL DEFAULT 14 maybe_make_export_env 
[...] 

这让我们在记忆(0x43ed80)和长度(18)的功能的地址。

我们有(虚拟)存储器中的地址(在过程映像中)。我们现在想要在文件中找到相关地址。为了做到这一点,我们需要看程序头表:

$ readelf -l /bin/bash 
Program Headers: 
    Type   Offset    VirtAddr   PhysAddr 
       FileSiz   MemSiz    Flags Align 
    PHDR   0x0000000000000040 0x0000000000400040 0x0000000000400040 
       0x00000000000001f8 0x00000000000001f8 R E 8 
    INTERP   0x0000000000000238 0x0000000000400238 0x0000000000400238 
       0x000000000000001c 0x000000000000001c R  1 
     [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2] 
    LOAD   0x0000000000000000 0x0000000000400000 0x0000000000400000 
       0x00000000000f3ad4 0x00000000000f3ad4 R E 200000 
    LOAD   0x00000000000f3de0 0x00000000006f3de0 0x00000000006f3de0 
       0x0000000000008ea8 0x000000000000ea78 RW  200000 
    DYNAMIC  0x00000000000f3df8 0x00000000006f3df8 0x00000000006f3df8 
       0x0000000000000200 0x0000000000000200 RW  8 
    NOTE   0x0000000000000254 0x0000000000400254 0x0000000000400254 
       0x0000000000000044 0x0000000000000044 R  4 
    GNU_EH_FRAME 0x00000000000d8ab0 0x00000000004d8ab0 0x00000000004d8ab0 
       0x0000000000004094 0x0000000000004094 R  4 
    GNU_STACK  0x0000000000000000 0x0000000000000000 0x0000000000000000 
       0x0000000000000000 0x0000000000000000 RW  10 
    GNU_RELRO  0x00000000000f3de0 0x00000000006f3de0 0x00000000006f3de0 
       0x0000000000000220 0x0000000000000220 R  1 

我们希望在其中找到PT_LOAD进入该地址属于(基于VirtAddrMemSize)。第一个PT_LOAD输入范围从0x4000000x400000 + 0xf3ad4 = 0x4f3ad4(不包括),所以该符号属于这个PT_LOAD条目。

我们无法找到文件中的偏移量symbol_value - VirtAddr + Offset = 0x3ed80

这是该文件的相关部分:

0003ed80: 8b05 3260 2b00 85c0 7406 e911 feff ff90 ..2`+...t....... 
0003ed90: f3c3 0f1f 4000 662e 0f1f 8400 0000 0000 [email protected] 

事实上,我们有相同的字节由objdump -d /bin/bash给出的一个:

000000000043ed80 <[email protected]@Base>: 
    43ed80:  8b 05 32 60 2b 00  mov 0x2b6032(%rip),%eax  # 6f4db8 <[email protected]@Base> 
    43ed86:  85 c0     test %eax,%eax 
    43ed88:  74 06     je  43ed90 <[email protected]@Base+0x10> 
    43ed8a:  e9 11 fe ff ff   jmpq 43eba0 <[email protected]@Base+0x60> 
    43ed8f:  90      nop 
    43ed90:  f3 c3     repz retq 
    43ed92:  0f 1f 40 00    nopl 0x0(%rax) 
    43ed96:  66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1) 
    43ed9d:  00 00 00