【问题标题】:How to extract a few functions out of a compiled ELF-executable (no disassembly)?如何从已编译的 ELF 可执行文件(无反汇编)中提取一些函数?
【发布时间】:2012-12-26 18:34:56
【问题描述】:

我正在处理一个大型可执行文件,我没有源代码(长话短说)。

我想从中提取几个函数的二进制代码——并尝试从我自己的程序中调用它们。如果重要的话,我正在寻找的函数都是从同一个源文件(在 Linux 上使用 gcc)编译的。

我可以使用 objdump 查看函数的二进制代码。有什么方法可以说服该工具转储函数的二进制代码 - 没有其他任何东西并且无需反汇编?

基本上,如果定义函数的 C 文件称为 foo.c,我想获取 foo.o(我实际上更喜欢 foo.So,但它不会存在于可执行文件中) .可以用objdump、readelf之类的吗?

如果重要的话,这些功能是独立的。

谢谢!

【问题讨论】:

    标签: elf objdump readelf


    【解决方案1】:

    可以用objdump、readelf之类的吗?

    当然:您可以使用 GDB 写出构成函数的字节。示例:

    cat t.c
    int foo() { return 42; }
    int main() { return foo(); }
    
    gcc t.c
    gdb -q ./a.out
    
    (gdb) disas/r foo
    Dump of assembler code for function foo:
       0x00000000004004c4 <+0>:  55              push   %rbp
       0x00000000004004c5 <+1>:  48 89 e5        mov    %rsp,%rbp
       0x00000000004004c8 <+4>:  b8 2a 00 00 00  mov    $0x2a,%eax
       0x00000000004004cd <+9>:  c9              leaveq 
       0x00000000004004ce <+10>: c3              retq   
    End of assembler dump.
    
    (gdb) dump memory foo.o 0x00000000004004c4 0x00000000004004ce+1
    (gdb) quit
    
    od -tx1 foo.o
    0000000 55 48 89 e5 b8 2a 00 00 00 c9 c3
    0000013
    

    注意 foo.o 的内容正是 foo 的代码字节。

    我想得到 foo.o

    部分很遗憾是不可能的:搬迁记录已经全部解决。如果 foo() 调用 bar(),bar 将不会出现在代码中的任何位置,只会出现它的地址。

    现在,如果需要的函数都是叶子函数(不要调用任何其他函数),并且不引用任何全局数据,那么您现在知道如何转储的字节序列可用于重建可链接的 foo。 o,像这样:

    { echo -e "foo:\n\t.byte\t\c";
      od -tx1 foo.o | cut -c9- |
        sed -e '/^ *$/d' -e 's/^/0x/' -e 's/ /,0x/g'; } > foo1.s
    
    cat foo1.s 
    foo:
        .byte   0x55,0x48,0x89,0xe5,0xb8,0x2a,0x00,0x00,0x00,0xc9,0xc3
    
    gcc -c foo1.s
    objdump -d foo1.o
    
    foo1.o:     file format elf64-x86-64
    
    
    Disassembly of section .text:
    
    0000000000000000 <foo>:
       0:   55                      push   %rbp
       1:   48 89 e5                mov    %rsp,%rbp
       4:   b8 2a 00 00 00          mov    $0x2a,%eax
       9:   c9                      leaveq 
       a:   c3                      retq
    

    QED

    【讨论】:

    • 好的,所以 foo() 调用 bar() (按地址),但 bar() 也是一个全局函数 -- 并且可以查找和绑定地址(通过 foo 调用 bar)到名字。 objdump 甚至可以做到这一点——但还有很多需要手动修复......
    猜你喜欢
    • 2012-09-02
    • 1970-01-01
    • 2020-07-09
    • 2012-08-20
    • 2020-07-09
    • 2012-05-08
    • 2013-09-07
    • 2013-08-04
    相关资源
    最近更新 更多