在查看某些程序集时,我遇到了一些使用段前缀的说明。例如,

<address>: ....  mov eax,DWORD PTR gs:0x20


我了解内存段的基本知识,但是如何获得此处要访问的数据的“绝对”内存地址(尤其是在GDB中)?例如,我可能想中断进一步的访问,或者检查该区域中的内存。

编辑:我知道如何获取$gs的值,但不确定如何将这些信息与给定指令以获取内存的实际地址。是的,这是在Linux下。

评论

您应该指定目标操作系统,因为这些寄存器的使用取决于操作系统(尽管我认为这是基于Unix的系统,因为您引用的是GDB)。

您是在问如何获取GS的值,或者如何使用该值作为绝对地址吗?

#1 楼

在Linux上,在保护模式下,段寄存器不再是标准的“段”,而是被称为选择器,并包含有关段是否可读/可写/可执行的信息。他们指向的实际地址被“隐藏”在内核的一个表中,而段寄存器被用作该表的索引,但是物理地址对您来说无论如何都不重要,因为您的应用程序处理虚拟gs映射的虚拟地址甚至无法在您的“正常”,ds / ss引用的虚拟地址空间中访问。

Linux使用gs寄存器对每个地址进行该进程可用的cpu信息。在示例中使用的特殊偏移量0x20被初始化为某个随机值,编译器在进入函数时会读取该值,然后将其写入堆栈,然后检查函数何时终止,以检测缓冲区溢出。 />
了解有关Wikipedia上的溢出保护的更多信息,以及有关Linux内核源代码中的percpu结构的更多信息。

评论


在Windows上,可以在用户模式下使用GetThreadSelectorEntry()来获取段的基地址。但是正如@ guntram-blohm上面所说的,Linux似乎没有这种用户模式功能。

–詹森·格夫纳(Jason Geffner)
14年7月11日在18:11

在他的特定示例中,尽管线程本地存储通常也使用fs或gs,但看起来还是glibc堆栈canary代码。

–百老汇
2014年7月12日在0:09