我正在研究glibc的堆。
libc.so中没有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。
答案 0 :(得分:2)
main_arena
是本地符号,特别是不会导出。导出符号列表通过glibc源代码树中的Version
文件控制。根据设计,这是为了防止人们无法链接glibc内部使用的随机符号(以便不像POSIX和其他标准那样污染命名空间)。
gdb可以找到它,因为您有可用的调试符号... C lib未被剥离,或者您在/usr/lib/debug/
中有拆分调试符号,gdb正在查找这些符号。当你启动gdb时,它会告诉你像Reading symbols from /usr/lib/debug/xxxxx
。
能够链接符号的唯一方法是从源重建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);
答案 1 :(得分:0)
剥离了libc.so.6。 它的调试版本不是。 这就是为什么readelf没有显示main_arena的原因。
我仍然想知道gdb如何知道符号名称,即使文件被剥离了。