“mov rax, QWORD PTR fs:0x28”汇编指令是做什么用的?

17

在执行这条指令之前,fs包含0x0。

我还想知道如何在GDB中从该内存区域读取数据,对应的命令是什么?


5
为什么这个内存地址具有随机值? - Abhineet
请参考 https://dev59.com/uWkv5IYBdhLWcg3wzkHa 获取第一部分内容。 - Anton Kovalenko
2
当我们谈论保护模式时,“由于fs为0x0,它应该失败”更正确,但是在64位模式下,不使用分段:而是有一个隐藏的“fs基址”寄存器,fs的值是无关紧要的。 - Anton Kovalenko
3
在Windows中,FS用于指向线程信息块的开头。从FS偏移量读取数据是一种非常简单且廉价的获取当前线程ID、当前时间、最后错误等信息的方法。您确定这是Linux代码,而不是Windows代码吗?请参见http://en.wikipedia.org/wiki/Win32_Thread_Information_Block. 此外,在保护模式下,FS值为零也是完全合法的,只要在xDT [0]处存在段描述符即可。 - Seva Alekseyev
你是如何获得那个指令的,或者说有哪个程序可以解释它? - Ciro Santilli OurBigBook.com
显示剩余2条评论
1个回答

13
现代操作系统(如Linux和Windows)中的fsgs寄存器指向特定于线程和其他操作系统定义结构的位置。修改段寄存器是一项受保护的指令,因此只有操作系统可以为您设置这些寄存器。
这个问题应该有助于解释这些寄存器的确切作用:amd64 fs/gs registers in linux
实际上fs寄存器的值不是一个地址,而是一个选择器——GDT中的偏移量,描述了该段可用和不可用的情况。您无法看到隐藏的fs基址和限制寄存器的值——它们是内部CPU寄存器,只有通过将新的"选择器"写入fs寄存器时才会更新基址/限制寄存器。

谢谢,但是我如何在GDB内部自己读取这个内存? - ioctlvoid
1
在具有FSGSBASE功能的CPU上,64位代码可以使用rdfsbasewrfsbase。它们是非特权的。(我不确定这个扩展有多久了。) - Peter Cordes
此外,修改段寄存器本身并不需要特权;因为没有FSGSBASE,内核需要更新LDT中该段描述的基地址,而用户空间无法访问。如果有第二个段描述符具有所需的基地址,则可以在用户空间中使用“mov fs,eax”来在多个FS基础之间切换,而不必调用内核。 - Peter Cordes
@Peter 我感觉你在跟踪我 :-) 但是,非常感谢你对所有答案的跟进;我从你的评论中学到了很多。我会尽量记得在我有时间的时候跟进这个问题(和其他问题)。我认为你关于更改fs的想法是正确的。 - Jonathon Reinhart
还有相关的问题:查找fs:28h的内存地址 正在询问如何找到该位置的线性地址。要了解更多关于读取段基址的详细信息,请参阅读取包含指向列表的段寄存器(%gs)。(不过,我的旧评论可能对于64位模式下的mov fs, eax是错误的,除非它适用于地址空间低32位的基址。它可能仍然设置一个基址,但通常情况下,如果不使用wrfsbase,FS基址是通过MSR设置的。) - Peter Cordes

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接