【问题标题】:Extract function bytes from ELF binary file从 ELF 二进制文件中提取函数字节
【发布时间】:2016-07-06 09:32:16
【问题描述】:

我想编写一个 python 脚本,它从一个知道其地址(例如 0x437310 和大小)的 elf 二进制文件中提取函数操作码。如何将此地址映射到二进制文件中的相应偏移量以开始从中读取?

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

我如何以通用方式计算这个,因为二进制的图像库并不总是相同的。

任何帮助将不胜感激

【问题讨论】:

  • 请附上一个(相关的)示例 ELF 文件。

标签: python reverse-engineering elf


【解决方案1】:

假设我想从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  ....@.f.........

我们确实和objdump -d /bin/bash给出的字节相同:

000000000043ed80 <maybe_make_export_env@@Base>:
  43ed80:       8b 05 32 60 2b 00       mov    0x2b6032(%rip),%eax        # 6f4db8 <array_needs_making@@Base>
  43ed86:       85 c0                   test   %eax,%eax
  43ed88:       74 06                   je     43ed90 <maybe_make_export_env@@Base+0x10>
  43ed8a:       e9 11 fe ff ff          jmpq   43eba0 <bind_global_variable@@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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-10-04
    • 2012-07-11
    • 1970-01-01
    • 2011-11-23
    • 2013-03-12
    • 1970-01-01
    • 2020-01-15
    相关资源
    最近更新 更多