为什么libc.so符号table中没有main_arena,而glibc2.23的malloc.c中有?
Why there isn't main_arena in libc.so symbol table, while there is one in malloc.c of glibc2.23?
正在研究glibc的heap
libc.so 中没有 main_arena 符号,即使我尝试使用 pwntool 转储它。但是,当我调试测试程序时,我可以打印 main_arena 结构。
gdb-peda$ p main_arena
= {
mutex = 0x0,
flags = 0x0,
fastbinsY = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
top = 0x0,
last_remainder = 0x0,
bins = {0x0 <repeats 254 times>},
binmap = {0x0, 0x0, 0x0, 0x0},
next = 0x7ffff7dd1b20 <main_arena>,
next_free = 0x0,
attached_threads = 0x1,
system_mem = 0x0,
max_system_mem = 0x0
}
另外,我用-m32编译测试程序时,也找不到main_arena
libc.so.6 被剥离。
它的调试版本不是。
这就是 readelf 不显示 main_arena.
的原因
我仍然想知道 gdb 是如何知道符号名称的,即使在库被剥离时也是如此。
main_arena
是本地符号,具体 不导出 。导出符号列表通过 glibc 源代码树中的 Version
文件控制。这是为了防止人们 link 反对 glibc 内部使用的随机符号(以免污染 POSIX 和其他标准所要求的命名空间)。
gdb 可以找到它,因为您有可用的调试符号……C lib 没有被剥离,或者您在 /usr/lib/debug/
中有拆分调试符号,gdb 正在找到它们。当你启动 gdb 时,它会告诉你类似 Reading symbols from /usr/lib/debug/xxxxx
.
的信息
能够 link 反对该符号的唯一方法是从源代码重建 glibc 并修改导出列表。
或者,您可以在您的应用程序中编写一些代码,使其表现得像 gdb。即,打开调试文件,处理其中的 ELF/DWARF 信息,使用活动加载的库信息应用重定位(参见 dl_iterate_phdr
),然后直接开始戳内存。
如果工作量太大,一个 hackery 解决方案可能是 fork()
+popen()
gdb 针对您自己的进程,然后 运行 它以批处理模式转储符号信息。
char *cmd;
FILE *fp;
asprintf(&cmd, "gdb -q -p %i -batch -ex 'p &main_arena'", getpid());
fp = popen(cmd, "r");
// parse the output of |fp| here looking for the address.
free(cmd);
fclose(fp);
正在研究glibc的heap
libc.so 中没有 main_arena 符号,即使我尝试使用 pwntool 转储它。但是,当我调试测试程序时,我可以打印 main_arena 结构。
gdb-peda$ p main_arena
= {
mutex = 0x0,
flags = 0x0,
fastbinsY = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
top = 0x0,
last_remainder = 0x0,
bins = {0x0 <repeats 254 times>},
binmap = {0x0, 0x0, 0x0, 0x0},
next = 0x7ffff7dd1b20 <main_arena>,
next_free = 0x0,
attached_threads = 0x1,
system_mem = 0x0,
max_system_mem = 0x0
}
另外,我用-m32编译测试程序时,也找不到main_arena
libc.so.6 被剥离。 它的调试版本不是。 这就是 readelf 不显示 main_arena.
的原因我仍然想知道 gdb 是如何知道符号名称的,即使在库被剥离时也是如此。
main_arena
是本地符号,具体 不导出 。导出符号列表通过 glibc 源代码树中的 Version
文件控制。这是为了防止人们 link 反对 glibc 内部使用的随机符号(以免污染 POSIX 和其他标准所要求的命名空间)。
gdb 可以找到它,因为您有可用的调试符号……C lib 没有被剥离,或者您在 /usr/lib/debug/
中有拆分调试符号,gdb 正在找到它们。当你启动 gdb 时,它会告诉你类似 Reading symbols from /usr/lib/debug/xxxxx
.
能够 link 反对该符号的唯一方法是从源代码重建 glibc 并修改导出列表。
或者,您可以在您的应用程序中编写一些代码,使其表现得像 gdb。即,打开调试文件,处理其中的 ELF/DWARF 信息,使用活动加载的库信息应用重定位(参见 dl_iterate_phdr
),然后直接开始戳内存。
如果工作量太大,一个 hackery 解决方案可能是 fork()
+popen()
gdb 针对您自己的进程,然后 运行 它以批处理模式转储符号信息。
char *cmd;
FILE *fp;
asprintf(&cmd, "gdb -q -p %i -batch -ex 'p &main_arena'", getpid());
fp = popen(cmd, "r");
// parse the output of |fp| here looking for the address.
free(cmd);
fclose(fp);