在查看一些程序集时,我遇到了一些使用段前缀的指令。例如
<address>: .... mov eax,DWORD PTR gs:0x20
我了解内存段的基础知识,但是如何获得此处访问的数据的“绝对”内存地址(尤其是在 GDB 中)?例如,我可能想中断进一步访问,或检查该区域的内存。
编辑:我知道如何获取 的值$gs
,但不确定如何通过给定指令使用该信息来获取内存的实际地址。是的,这是在 Linux 下。
在查看一些程序集时,我遇到了一些使用段前缀的指令。例如
<address>: .... mov eax,DWORD PTR gs:0x20
我了解内存段的基础知识,但是如何获得此处访问的数据的“绝对”内存地址(尤其是在 GDB 中)?例如,我可能想中断进一步访问,或检查该区域的内存。
编辑:我知道如何获取 的值$gs
,但不确定如何通过给定指令使用该信息来获取内存的实际地址。是的,这是在 Linux 下。
在 Linux 上,在保护模式下,段寄存器不再是标准的“段”,相反,它们被称为选择器,并包含该段是否可读/可写/可执行的信息。他们指向的真实地址“隐藏”在内核的一个表中,段寄存器用作该表的索引,但无论如何物理地址对您来说并不重要,因为您的应用程序处理虚拟仅内存,并且 gs 映射到的虚拟地址甚至无法在您的“正常”、ds/ss 引用的虚拟地址空间中访问。
Linux 使用 gs 寄存器为进程提供一些 per-cpu 信息。您在示例中使用的特殊偏移量 0x20 被初始化为某个随机值,编译器在进入函数时读取该值并写入堆栈,并检查函数何时终止,以检测缓冲区溢出。
在wikipedia上阅读更多关于溢出保护的信息,以及更多关于linux 内核源代码中的 percpu 结构。