什么是装配中的%gs

Ale*_*x F 15 linux x86 assembly

void return_input (void)
{ 
   char array[30]; 

   gets (array); 
   printf("%s\n", array); 
}

在gcc中编译后,此函数将转换为以下汇编代码:

push   %ebp
mov    %esp,%ebp
sub    $0x28,%esp
mov    %gs:0x14,%eax
mov    %eax,-0x4(%ebp)
xor    %eax,%eax
lea    -0x22(%ebp),%eax
mov    %eax,(%esp)
call   0x8048374 
lea    -0x22(%ebp),%eax
mov    %eax,(%esp)
call   0x80483a4 
mov    -0x4(%ebp),%eax
xor    %gs:0x14,%eax
je     0x80484ac 
call   0x8048394 
leave  
ret  

我不明白两行:

mov    %gs:0x14,%eax
xor    %gs:0x14,%eax

什么是%gs,这两条线到底是做什么的?

这是编译命令:

cc -c -mpreferred-stack-boundary=2 -ggdb file.c

Nec*_*lis 20

GS是一个段寄存器,它在linux中的使用可以在这里读取(它主要用于每个进程数据).

mov    %gs:0x14,%eax
xor    %gs:0x14,%eax
Run Code Online (Sandbox Code Playgroud)

此代码用于验证堆栈未爆炸或已被破坏,使用存储在GS + 0x14的金丝雀值,请参阅此信息.

  • 你好,你的链接失效了。 (2认同)

dig*_*dig 5

在 AT&T 风格的汇编语言中,百分号符号通常表示寄存器。在 386 以后的 x86 系列处理器中,GS 是所谓的段寄存器之一。然而,在保护模式环境中,段寄存器充当选择器寄存器

\n\n

虚拟内存选择器代表其自己的虚拟地址空间映射及其自己的访问机制。实际上,%gs:0x14可以将其视为对原点保存在 %gs 中的数组的引用(尽管 CPU 会进行一些额外的取消引用)。在现代 GNU/Linux 系统上,%gs通常用于指向线程本地存储区域。然而,在您询问的代码中,只有一项 TLS 很重要 \xe2\x80\x94\xc2\xa0the stack canary。

\n\n

这个想法是尝试通过放置一个随机但恒定的值 \xe2\x80\x94 来检测缓冲区溢出错误,它被称为堆栈金丝雀,以纪念金丝雀煤矿工人用来通过死亡来发出有毒气体水平增加的信号\ xe2\x80\x94 在被调用之前进入堆栈,在其堆栈帧上方,并在返回 gets()后检查它是否仍然存在。没有必要覆盖堆栈 \xe2\x80\x94 的这一部分,它位于自己的堆栈框架之外,并且没有给出指向它 \xe2\x80\x94 的指针,因此如果堆栈金丝雀已经死亡,则某些东西已经消失以危险的方式错误。(C 作为一种编程环境,恰好特别容易出现这种错误,安全研究人员在过去二十年左右的时间里已经学会了利用其中的许多错误。而且,它恰好是一个本身就存在安全风险的函数。溢出其目标缓冲区。)您尚未在代码中提供地址,但 0x80484ac 可能是 的地址,并且在不匹配的情况下执行(即在匹配的情况下跳过),可能是对gets()gets()gets()leavecall 0x8048394je 0x80484ac__stack_chk_fail(),由 libc 提供,用于通过逃离隐喻的毒矿来处理堆栈损坏。

\n\n

堆栈金丝雀的规范值保存在线程本地存储中的原因是,这样每个线程都可以拥有自己的堆栈金丝雀。堆栈本身通常不在线程之间共享,因此自然也不共享金丝雀值。

\n