C语言 查找fs:28h的内存地址

qqrboqgw  于 2023-08-03  发布在  其他
关注(0)|答案(1)|浏览(98)

为了好玩,我用gdb调试了一个程序,用了stack guard,所以它把金丝雀从fs:28 h写到了堆栈。出于好奇,我试图找到fs:28 h所指向的内存地址。我遇到两个问题。首先,gdb不能显示gdtr/ldtr中的值,因为它不在环零中运行。第二,当用gdb阅读fs时,它包含0,这有什么意义?我知道gdt/ldt在返回无效地址的第一个索引中包含0,并且RPL关闭,所以我在这里遗漏了什么?如果有人知道如何找到段寄存器fs指向的地址,我想知道。

file: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), statically linked

字符串

vmdwslir

vmdwslir1#

您似乎正在使用x86_64-linux-gnu,即x86-64 CPU、Linux内核和GNU C库的全部三个。通过硬件和系统软件的这种组合,FS段被设置为使得存储器操作数%fs:0引用当前执行线程的 * 线程控制块 * 的开始。(线程控制块是描述运行线程的内部C库数据结构。您可以将其视为pthread_t线程句柄所引用的对象。
正是因为x86在历史上不容易让非特权代码查找%fs:xxx%gs:xxx内存操作数引用的“实际”地址(更准确地说是“线性虚拟地址”),所以x86_64-linux-gnu上线程控制块的第一个字段是指向线程控制块本身的指针。因此,在本发明中,

void *read_fs(void) {
    void *rv;
    asm("movq %%fs:0, %0" : "=r" (rv));
    return rv;
}

字符串
将返回您想要的地址。请记住,这 * 仅 * 保证在x86_64-linux-gnu上为真。如果您切换到不同的Unix内核(例如FreeBSD)或不同的C库(例如musl libc),FS段很有可能仍然指向线程控制块,但是该空间中的数据可能会有很大的不同。

相关问题