目录

  • 一、准备 🧐
  • 二、疑问 🔍
  • 三、回答 💡
  • 四、总结 📃



本文在调试过程中发现

ldd

(gdb) info sharedlibrary 显示不同的动态库加载基地址,然后查了一些资料后,找到了这篇帖子【

传送门】,现做一下复现,但是还是不知道

ldd <目标文件> 这个命令打印的地址是什么地址,如果有哪位大佬知晓,望不吝相告,谢谢。

一、准备 🧐

/* test.c */
#include <stdio,h>
int main(int argc, const char *argv[])
{
	printf("hello world\n");
	while(1);
}

编译:gcc -m32 -no-pie -fno-stack-protector -z execstack -o test test.c

-m32:生成32位的可执行文件。
-no-pie:关闭可执行文件位置无关代码,默认是关闭的,所以可不加,有些加上该选项后还会报错。
-fno-stack-protector:关闭Stack Protector/Canary(栈保护)
-z execstack:关闭DEP/NX(堆栈不可执行)
-o:输出
test:编译生成文件的文件名
test.c:编译前的源文件

查看ASLRcat /proc/sys/kernel/randomize_va_space,如果为0表示处于关闭状态。

切换至root用户,关闭ASLRecho 0 > /proc/sys/kernel/randomize_va_space,当需要开启时,将 0 换成 1 或 2 即可。

这里复现时需要关闭掉 ASLR!!!

二、疑问 🔍

方式一、根据 ldd 命令可知 libc 的加载地址为 0xb7e40000

shared_preload_libraries一般设置哪些_gdb


方式二、使用 GDB 调试命令 info sharedlibrary 可知 libc 的加载地址为 0xb7e34f70

shared_preload_libraries一般设置哪些_linux_02


方式三、当我们用手动的方式通过符号计算动态加载基地址,首先通过 GDB 获得 system函数加载的基地址:0xb7e5d0b0

shared_preload_libraries一般设置哪些_加载_03


使用 IDA Pro 软件查看 system 函数在动态库中的偏移,得到 0x0003F0B0,则动态库加载基地址为:0xb7e5d0b0 - 0x0003F0B0 = 0xb7e1e000

shared_preload_libraries一般设置哪些_linux_04


总共获得了三种结果,所以哪一种结果是正确的?

方式一:0xb7e40000
方式二:0xb7e34f70
方式三:0xb7e1e000

三、回答 💡

方式三获得的地址正确

首先,ldd 命令并不能准确的确定动态库加载基地址,至于这个地址是什么的地址,目前还不知道。如果要获得动态库加载基地址,需要用到环境变量 LD_TRACE_LOADED_OBJECTS。(这里需要关闭ASLR,不然每次查找基地址时都会发生变化,也正是由于这种变化才能保护程序不容易被攻破。)

用法:LD_TRACE_LOADED_OBJECTS=1 <可执行程序> | grep libc 例如:LD_TRACE_LOADED_OBJECTS=1 ./test | grep libc(少 ./ 可能出错)

其次,如何查看程序在运行时动态库加载的基地址?

方法一:运用 /proc/<进程号>/maps,这里以libc.so.6(该动态库为libc-2.15.so的软链接)为例子,

  • ① grep libc /proc/<进程号>/maps | head -n1
  • ② cat /proc/<进程号>/maps | grep libc

方法二:在 GDB 调试中,使用 info proc mapping 查看。

验证:

shared_preload_libraries一般设置哪些_bc_05


已经知道动态库加载基地址的正确地址,那 info sharedlibrary 的地址是什么?

通过以下命令,查看代码段在动态库中的偏移地址为0x00016f70

shared_preload_libraries一般设置哪些_bc_06


在开启ASLR的情况下,动态库的每次加载地址都是随机的,但是当通过GDB进行调试的时候,会关闭ASLR功能。 通过 GDB 中的 info proc mapping 命令查看动态库加载的基地址为0xb7e1e000,通过 info sharedlibrary 命令查看动态库时的地址 0xb7e34f70 是什么地址?

如果将这三个数据进行一次运行,结果会很明了:0xb7e34f70 = 0xb7e1e000 + 0x00016f70 ,因此,可以推断出 info sharedlibrary 命令查看动态库代码段加载的基地址。

shared_preload_libraries一般设置哪些_动态库_07

四、总结 📃

  • ldd <目标文件> 方式并不能准确的查看某个动态库的加载基地址,目前该命令所显示的地址是什么地址还不明确。
  • 查看动态库的加载基地址方式有如下几种:
    LD_TRACE_LOADED_OBJECTS=1 <可执行程序> | grep <动态库名> ② 运用 /proc/<进程号>/maps ③ 在 GDB 调试中,使用 info proc mapping 查看
  • 如果系统开启 ASLR,则每次的加载地址都是变化的,但是GDB调试时会将该功能禁止。
  • 在 GDB 调试中,info sharedlibrary 命令查看的是动态库代码段的起始地址。

参考:
Why does `ldd` and `(gdb) info sharedlibrary` show a different library base address? 🚀