为什么这个内存地址%fs:0x28(fs )有一个随机值?

我写了一段C代码,我已经拆解了它,并且读取了寄存器以了解程序在汇编中的工作原理。

int test(char *this){ char sum_buf[6]; strncpy(sum_buf,this,32); return 0; } 

我一直在研究的代码是测试function。 当我反汇编输出我的测试function时,我得到…

  0x00000000004005c0 : mov %fs:0x28,%rax => 0x00000000004005c9 : mov %rax,-0x8(%rbp) ... stuff .. 0x00000000004005f0 : xor %fs:0x28,%rdx 0x00000000004005f9 : je 0x400600  0x00000000004005fb : callq 0x4004a0  0x0000000000400600 : leaveq 0x0000000000400601 : retq 

我想知道的是mov %fs:0x28,%rax真的在做什么?

在x86_64上,不再使用分段寻址,但FSGS寄存器都可以用作基指针地址,以便访问特殊的操作系统数据结构。 因此,您所看到的是一个值,它与FS寄存器中保存的值的偏移量FS ,而不是FS寄存器内容的位操作。

特别是正在发生的事情是,Linux上的FS:0x28存储了一个特殊的标记栈保护值,并且代码正在执行堆栈保护检查。 例如,如果您进一步查看代码,您将看到FS:0x28值存储在堆栈中,然后调用堆栈的内容并执行XOR ,其原始值位于FS:0x28 。 如果两个值相等,这意味着已经设置了零位,因为XOR两个相同的值导致零值,那么我们跳转到test例程,否则我们跳转到一个特殊函数,指示堆栈以某种方式被破坏,并且存储在堆栈上的sentinel值已更改。

如果使用GCC, 可以禁用此function

 -fno-stack-protector 

看http://www.imada.sdu.dk/Courses/DM18/Litteratur/IntelnATT.htm ,我认为%fs:28实际上是与%fs的地址%fs 28个字节的偏移量。 所以我认为它正在从%fs + 28位置加载一个完整的寄存器大小到%rax。