ldd
由于ldd
一些原因,该程序是错误的。
首先,ldd
并不意味着确定加载地址是准确的。使用环境变量LD_TRACE_LOADED_OBJECTS
。
其次,ldd
如 Guntram 所示,在启用 ASLR 的情况下永远不会正确。如果您有sudo
访问权限,您可以非常简单地禁用它。
$ LD_TRACE_LOADED_OBJECTS=1 /bin/bash | grep libc
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f44dae1b000)
$ LD_TRACE_LOADED_OBJECTS=1 /bin/bash | grep libc
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f9b35341000)
$ LD_TRACE_LOADED_OBJECTS=1 /bin/bash | grep libc
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fef18efd000)
$ echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
0
$ LD_TRACE_LOADED_OBJECTS=1 /bin/bash | grep libc
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007ffff75e7000)
$ LD_TRACE_LOADED_OBJECTS=1 /bin/bash | grep libc
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007ffff75e7000)
$ LD_TRACE_LOADED_OBJECTS=1 /bin/bash | grep libc
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007ffff75e7000)
您可以通过在后台启动 bash 实例并检查其映射文件来验证这一点。
$ bash &
[1] 30398
[1] + 30398 suspended (tty input) bash
$ grep libc /proc/30398/maps | head -n1
7ffff75e7000-7ffff77a2000 r-xp 00000000 08:01 525269 /lib/x86_64-linux-gnu/libc-2.19.so
info sharedlibrary
上报info sharedlibrary
的地址是该.text
区域的地址。
请注意,在我拥有的特定 libc 中,.text 位于0x1f4a0
.
$ readelf --wide --section-headers /lib/x86_64-linux-gnu/libc-2.19.so | grep text
[12] .text PROGBITS 000000000001f4a0 01f4a0 145c23 00 AX 0 0 16
在 GDB 中,如果我们查看 的加载地址libc
,我们会看到它是在 加载的0x7ffff7a14000
。如果在系统上启用了 ASLR,这将在每次程序运行时发生变化。如果在 GDB 下运行它,它也会禁用 ASLR。set disable-randomization off
在运行目标之前运行命令,您将观察到它每次运行都会发生变化。
gdb-peda$ info proc mapping
...
0x7ffff7a14000 0x7ffff7bcf000 0x1bb000 0x0 /lib/x86_64-linux-gnu/libc-2.19.so
0x7ffff7bcf000 0x7ffff7dcf000 0x200000 0x1bb000 /lib/x86_64-linux-gnu/libc-2.19.so
0x7ffff7dcf000 0x7ffff7dd3000 0x4000 0x1bb000 /lib/x86_64-linux-gnu/libc-2.19.so
0x7ffff7dd3000 0x7ffff7dd5000 0x2000 0x1bf000 /lib/x86_64-linux-gnu/libc-2.19.so
...
您可以通过检查它是否以 ELF 标头开头来验证这一点。
gdb-peda$ hexdump 0x00007ffff7a14000 4
0x0000 0x00007ffff7a14000 │ 7f 45 4c 46 │ .ELF
0x0004 0x00007ffff7a14004
如果我们加上该区域的0x1f4a0
偏移量.text
,我们得到0x7ffff7a334a0
。
gdb-peda$ printf "%p\n",(0x00007ffff7a14000+0x1f4a0)
0x7ffff7a334a0
现在,如果我们查看info sharedlibrary
,我们会看到这个地址。
gdb-peda$ info sharedlibrary libc
From To Syms Read Shared Object Library
0x00007ffff7a334a0 0x00007ffff7b790c3 Yes /lib/x86_64-linux-gnu/libc.so.6
额外提示
在 GDB 中,您应该使用该info proc mapping
命令来获取已加载模块的基址。
但是,这在 FreeBSD 上不可用,因为 GDB 不支持获取模块基地址所需的 FreeBSD 特定 API。相反,您必须使用该info proc mapping
命令并自己执行转换(通过减去段的地址.text
)。