我正在研究glibc的堆。
libc.o中没有main_arena符号,即使我尝试用pwntool倾倒它。但是,当我调试测试程序时,我可以打印main_arena结构。
gdb-peda$ p main_arena
$1 = {
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。
main_arena
是本地符号,是专门未导出的。导出符号的列表通过GLIBC源树中的Version
文件控制。通过设计,这是为了防止人们能够与Glibc内部使用的随机符号链接(以免按POSIX和其他标准污染名称空间)。
gdb可以找到它,因为您有可用的调试符号... c lib未剥离,或者您在 /usr/lib/debug/
中有拆分调试符号,而gdb正在找到这些符号。当您启动GDB时,它将告诉您Reading symbols from /usr/lib/debug/xxxxx
。
能够链接到符号的唯一方法是从源重建GLIBC并修改导出列表。
另外,您可以在应用程序中编写一些代码,以表现为GDB。也就是说,打开调试文件,处理其中的精灵/矮人信息,使用主动加载的库信息应用重新安置(请参阅dl_iterate_phdr
),然后直接开始戳内存。
如果工作太多,则可能是针对您自己的流程的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);
libc.so.6被剥离。它的调试版本不是。这就是为什么readelf不显示main_arena。
我仍然想知道gdb即使删除了库,也知道符号名称。