从 shell 代码访问未链接的 libc 全局变量

发布于 2025-01-15 08:20:03 字数 206 浏览 2 评论 0原文

有没有办法找到 libc 中尚未链接到可执行文件中的全局变量的地址(因此不在 get/plt 中)?我想在 shell 代码中访问 __environ 全局变量。

到目前为止,网络搜索只找到了一种方法,首先从 plt 中的实体查找共享库中的偏移量,然后将偏移量添加到 plt 中的运行时值,以获取所需变量的运行时地址共享库。还有另一种不依赖于共享库版本的方法吗?

谢谢。

Is there any way to find the address of a global variable in libc that hasn't been linked into the executable (therefore not in the got/plt)? I'd like to access the __environ global variable in my shell code.

Web searches have so far only turned up an approach where you first find the offset in the shared library from an entity that is in the plt, and add the offset to the runtime value in the plt to get the runtime address of the desired variable in the shared library. Is there another way that would not depend on the version of the shared library?

Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

冰葑 2025-01-22 08:20:03

是否有另一种不依赖于共享库版本的方法?

不。

__environ 的地址可以通过多种方式轻松找到,除了“首先从 plt 中的实体查找共享库中的偏移量,然后将偏移量添加到 plt 中的运行时值”之外。 plt 获取所需变量的运行时地址”,但该地址取决于libc.so.6的确切构建,并且会因版本而异(对于完全相同的 GLIBC 版本)来自发行版分发(例如不同的编译器会产生不同的结果)。

那么还有哪些其他方法可以找到这个地址呢?

您需要两件事:

  1. libc.so.6 中变量的地址,由 nmreadelf 打印:
nm -D /usr/lib64/libc.so.6 | grep __environ
0000000000202d00 B __environ@@GLIBC_2.2.5
  1. libc 的位置.so.6本身在给定的进程中,可以通过例如/proc/$pid/maps发现。
 grep libc.so.6 /proc/37/maps
7f34d2865000-7f34d2891000 r--p 00000000 08:10 67606                      /usr/lib64/libc.so.6
7f34d2891000-7f34d2a07000 r-xp 0002c000 08:10 67606                      /usr/lib64/libc.so.6
...

上面的输出告诉我,__environ应该位于进程37中的0x7f34d2865000+0x0000000000202d00

gdb -q -p 37
...
(gdb) p/a 0x7f34d2865000+0x0000000000202d00
$1 = 0x7f34d2a67d00 <environ>

(gdb) p &__environ
$2 = (char ***) 0x7f34d2a67d00 <environ>

量子电子器件。

PS 还有其他方法可以发现 (1) - 您可以直接读取 .dynsym 而不使用 nm,以及 (2) - 您可以使用 dladdr( ) 在目标进程内。

Is there another way that would not depend on the version of the shared library?

No.

The address of __environ can be trivially found via many ways other than "first find the offset in the shared library from an entity that is in the plt, and add the offset to the runtime value in the plt to get the runtime address of the desired variable", but that address will depend on the exact build of libc.so.6, and will vary from version to version (and for the exact same GLIBC version) from distribution to distribution (e.g. different compilers will produce different result).

So what other methods of finding this address exist?

You need two things:

  1. The address of the variable within libc.so.6, printed by nm and readelf:
nm -D /usr/lib64/libc.so.6 | grep __environ
0000000000202d00 B __environ@@GLIBC_2.2.5
  1. Location of libc.so.6 itself in a given process, discoverable via e.g. /proc/$pid/maps.
 grep libc.so.6 /proc/37/maps
7f34d2865000-7f34d2891000 r--p 00000000 08:10 67606                      /usr/lib64/libc.so.6
7f34d2891000-7f34d2a07000 r-xp 0002c000 08:10 67606                      /usr/lib64/libc.so.6
...

Above output tells me that __environ should be at 0x7f34d2865000+0x0000000000202d00 in process 37.

gdb -q -p 37
...
(gdb) p/a 0x7f34d2865000+0x0000000000202d00
$1 = 0x7f34d2a67d00 <environ>

(gdb) p &__environ
$2 = (char ***) 0x7f34d2a67d00 <environ>

QED.

P.S. There are other ways of discovering (1) -- you could read .dynsym directly without using nm, and (2) -- you could use dladdr() within the target process.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文