【问题标题】:Where would I find specific function addresses in libc object files?我在哪里可以找到 libc 目标文件中的特定函数地址?
【发布时间】:2015-11-24 03:07:37
【问题描述】:

我正在尝试在 libc 中查找函数的地址。

我知道我可以在 C 中做这样的事情:

printf("%x", (int) system);

但我不知道这是否给了我 libc 中系统函数的基地址。我假设它在程序中给出了某种间接指针?

我正在运行 gdb 并做到了:

info files

在运行程序时,但它给了我很多片段,除了那些包含 libc.so 的片段之外,我不确定在哪里看?

编辑:

这是我在 gdb 中得到的,我想知道在哪里可以找到“system”、“printf”、“exit”等内容。我检查了 rodata 并能够在那里找到系统,但我不知道这是否是函数本身:

    0x08048154 - 0x08048167 is .interp
    0x08048168 - 0x08048188 is .note.ABI-tag
    0x08048188 - 0x080481ac is .note.gnu.build-id
    0x080481ac - 0x080481d0 is .gnu.hash
    0x080481d0 - 0x08048290 is .dynsym
    0x08048290 - 0x08048326 is .dynstr
    0x08048326 - 0x0804833e is .gnu.version
    0x08048340 - 0x08048380 is .gnu.version_r
    0x08048380 - 0x08048388 is .rel.dyn
    0x08048388 - 0x080483d8 is .rel.plt
    0x080483d8 - 0x080483fb is .init
    0x08048400 - 0x080484b0 is .plt
    0x080484b0 - 0x08048892 is .text
    0x08048894 - 0x080488a8 is .fini
    0x080488a8 - 0x08048994 is .rodata
    0x08048994 - 0x080489c8 is .eh_frame_hdr
    0x080489c8 - 0x08048a98 is .eh_frame
    0x08049f08 - 0x08049f0c is .init_array
    0x08049f0c - 0x08049f10 is .fini_array
    0x08049f10 - 0x08049f14 is .jcr
---Type <return> to continue, or q <return> to quit---
    0x08049f14 - 0x08049ffc is .dynamic
    0x08049ffc - 0x0804a000 is .got
    0x0804a000 - 0x0804a034 is .got.plt
    0x0804a034 - 0x0804a03c is .data
    0x0804a03c - 0x0804a054 is .bss
    0xb7fde114 - 0xb7fde138 is .note.gnu.build-id in /lib/ld-linux.so.2
    0xb7fde138 - 0xb7fde1f8 is .hash in /lib/ld-linux.so.2
    0xb7fde1f8 - 0xb7fde2dc is .gnu.hash in /lib/ld-linux.so.2
    0xb7fde2dc - 0xb7fde4ac is .dynsym in /lib/ld-linux.so.2
    0xb7fde4ac - 0xb7fde642 is .dynstr in /lib/ld-linux.so.2
    0xb7fde642 - 0xb7fde67c is .gnu.version in /lib/ld-linux.so.2
    0xb7fde67c - 0xb7fde744 is .gnu.version_d in /lib/ld-linux.so.2
    0xb7fde744 - 0xb7fde7b4 is .rel.dyn in /lib/ld-linux.so.2
    0xb7fde7b4 - 0xb7fde7e4 is .rel.plt in /lib/ld-linux.so.2
    0xb7fde7f0 - 0xb7fde860 is .plt in /lib/ld-linux.so.2
    0xb7fde860 - 0xb7ff67ac is .text in /lib/ld-linux.so.2
    0xb7ff67c0 - 0xb7ffa7a0 is .rodata in /lib/ld-linux.so.2
    0xb7ffa7a0 - 0xb7ffae24 is .eh_frame_hdr in /lib/ld-linux.so.2
    0xb7ffae24 - 0xb7ffd71c is .eh_frame in /lib/ld-linux.so.2
    0xb7ffecc0 - 0xb7ffef34 is .data.rel.ro in /lib/ld-linux.so.2
    0xb7ffef34 - 0xb7ffefec is .dynamic in /lib/ld-linux.so.2
    0xb7ffefec - 0xb7ffeff8 is .got in /lib/ld-linux.so.2
    0xb7fff000 - 0xb7fff024 is .got.plt in /lib/ld-linux.so.2
---Type <return> to continue, or q <return> to quit---
    0xb7fff040 - 0xb7fff878 is .data in /lib/ld-linux.so.2
    0xb7fff878 - 0xb7fff938 is .bss in /lib/ld-linux.so.2
    0xb7e16174 - 0xb7e16198 is .note.gnu.build-id in /lib/i386-linux-gnu/libc.so.6
    0xb7e16198 - 0xb7e161b8 is .note.ABI-tag in /lib/i386-linux-gnu/libc.so.6
    0xb7e161b8 - 0xb7e19ec8 is .gnu.hash in /lib/i386-linux-gnu/libc.so.6
    0xb7e19ec8 - 0xb7e23438 is .dynsym in /lib/i386-linux-gnu/libc.so.6
    0xb7e23438 - 0xb7e2915e is .dynstr in /lib/i386-linux-gnu/libc.so.6
    0xb7e2915e - 0xb7e2a40c is .gnu.version in /lib/i386-linux-gnu/libc.so.6
    0xb7e2a40c - 0xb7e2a898 is .gnu.version_d in /lib/i386-linux-gnu/libc.so.6
    0xb7e2a898 - 0xb7e2a8d8 is .gnu.version_r in /lib/i386-linux-gnu/libc.so.6
    0xb7e2a8d8 - 0xb7e2d2e8 is .rel.dyn in /lib/i386-linux-gnu/libc.so.6
    0xb7e2d2e8 - 0xb7e2d348 is .rel.plt in /lib/i386-linux-gnu/libc.so.6
    0xb7e2d350 - 0xb7e2d420 is .plt in /lib/i386-linux-gnu/libc.so.6
    0xb7e2d420 - 0xb7f5eb6e is .text in /lib/i386-linux-gnu/libc.so.6
    0xb7f5eb70 - 0xb7f5fafb is __libc_freeres_fn in /lib/i386-linux-gnu/libc.so.6
    0xb7f5fb00 - 0xb7f5fcfe is __libc_thread_freeres_fn in /lib/i386-linux-gnu/libc.so.6
---Type <return> to continue, or q <return> to quit---
    0xb7f5fd00 - 0xb7f81754 is .rodata in /lib/i386-linux-gnu/libc.so.6
    0xb7f81754 - 0xb7f81767 is .interp in /lib/i386-linux-gnu/libc.so.6
    0xb7f81768 - 0xb7f88c0c is .eh_frame_hdr in /lib/i386-linux-gnu/libc.so.6
    0xb7f88c0c - 0xb7fb9f68 is .eh_frame in /lib/i386-linux-gnu/libc.so.6
    0xb7fb9f68 - 0xb7fba3c6 is .gcc_except_table in /lib/i386-linux-gnu/libc.so.6
    0xb7fba3c8 - 0xb7fbd928 is .hash in /lib/i386-linux-gnu/libc.so.6
    0xb7fbe1d4 - 0xb7fbe1dc is .tdata in /lib/i386-linux-gnu/libc.so.6
    0xb7fbe1dc - 0xb7fbe220 is .tbss in /lib/i386-linux-gnu/libc.so.6
    0xb7fbe1dc - 0xb7fbe1e8 is .init_array in /lib/i386-linux-gnu/libc.so.6
    0xb7fbe1e8 - 0xb7fbe260 is __libc_subfreeres in /lib/i386-linux-gnu/libc.so.6
    0xb7fbe260 - 0xb7fbe264 is __libc_atexit in /lib/i386-linux-gnu/libc.so.6
    0xb7fbe264 - 0xb7fbe274 is __libc_thread_subfreeres in /lib/i386-linux-gnu/libc.so.6
    0xb7fbe280 - 0xb7fbfda8 is .data.rel.ro in /lib/i386-linux-gnu/libc.so.6
    0xb7fbfda8 - 0xb7fbfe98 is .dynamic in /lib/i386-linux-gnu/libc.so.6
    0xb7fbfe98 - 0xb7fbfff4 is .got in /lib/i386-linux-gnu/libc.so.6
    0xb7fc0000 - 0xb7fc003c is .got.plt in /lib/i386-linux-gnu/libc.so.6
    0xb7fc0040 - 0xb7fc0ebc is .data in /lib/i386-linux-gnu/libc.so.6

【问题讨论】:

  • 将指针转换为int 总是错误的。函数指针更加特殊,因为有些架构根本不转换为整数类型甚至void*。但总的来说,你的问题听起来像是一个 XY 问题。您要求 X,但您想要 Y。您真正想要实现的目标是什么?
  • 要打印一个指针,使用'%p'格式说明符,这就是它的用途。
  • 只有库中使用的函数实际上在链接/可执行代码中。它们的地址可以在可执行代码的内存空间中的任何位置。您的 printf() 输出的内容与函数在库中的位置无关。
  • @Skorpius 你试过我的建议了吗?
  • 我觉得你的问题不清楚。我试图猜测你的真正意思并给出了我的答案。

标签: c gdb libc memory-segmentation


【解决方案1】:

这是您如何找到映射到可执行文件中的函数地址的方法。

$ gdb program 
Reading symbols from ...done.
(gdb) print main
$1 = {int (int, char **)} 0x400d61 <main>
(gdb) print exit
$2 = {<text variable, no debug info>} 0x400910 <exit@plt>

【讨论】:

  • 但是 OP 想要找到 programaticcaly 函数的地址
  • 它没有在任何地方被提及。我认为最终目的是知道那个地址。
【解决方案2】:

它可能是特定于实现的。我专注于Linux。你可能想要

printf("system@%p\n", (void*)system);

这确实为您提供了system 函数的地址。您可以将其存储在函数指针中:

int (*funptr)(const char*) = system;

随后对(*funptr)("date") 的调用与system("date") 的行为相同,因此system(或funptr 中的值)libcsystem(3) 函数。

迂腐地,C 标准不保证函数指针适合泛型 void*(所以严格来说我的 printf 可能是错误的);实际上,在 Linux 和 POSIX 上,它确实适合。

如果您想以编程方式在运行时从函数的名称中找到某个函数的地址,请使用dlsym(3),也许在通过将NULL 传递给dlopen(3) 获得的程序句柄上(以及带有 GNU libc 的 Linux,dladdr(3) 正在做相反的转换)。您可能希望将您的程序与 -rdynamic 链接并了解有关 pluginsdynamic loading 的更多信息。

但是(在 Linux 上),C standard library 可能(并且通常是)共享库(ELF 共享对象)libc.so,而system 可能指向Procedure Linkage Table 条目(请参阅@987654330 @Levine 关于链接器和加载器的书); PLT 条目是到函数的第一条实际指令的跳转。请参阅this 关于 ELF 共享对象的答案和参考。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-04-09
    • 1970-01-01
    • 2017-10-29
    • 2019-01-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-16
    相关资源
    最近更新 更多