汇编中的 %gs 是什么
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
void return_input (void) { char array[30]; gets (array); printf("%s\n", array); }
After compiling it in gcc, this function is converted to the following Assembly code:
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
I don't understand two lines:
mov %gs:0x14,%eax xor %gs:0x14,%eax
What is %gs, and what exactly these two lines do?
This is compilation command:
cc -c -mpreferred-stack-boundary=2 -ggdb file.c
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
GS 是一个段寄存器,它在 Linux 中的使用可以在这里阅读< /a> (它基本上用于每个线程数据)。
此代码用于验证堆栈没有爆炸或损坏,使用存储在 GS+0x14 的金丝雀值,请参阅 这个。
gcc -fstack-protector=strong
在许多现代发行版中默认处于启用状态;您可以使用 gcc -fno-stack-protector 来不添加这些检查。 (在 x86 上,线程本地存储很便宜,因此 GCC 将随机金丝雀值保留在那里,使其更难以泄漏。)GS is a segment register, its use in linux can be read up on here (its basically used for per thread data).
this code is used to validate that the stack hasn't exploded or been corrupted, using a canary value stored at GS+0x14, see this.
gcc -fstack-protector=strong
is on by default in many modern distros; you can usegcc -fno-stack-protector
to not add those checks. (On x86, thread-local storage is cheap so GCC keeps the randomized canary value there, making it somewhat harder to leak.)在 AT&T 风格的汇编语言中,百分号符号通常表示寄存器。在 386 及以上的 x86 系列处理器中,GS 是所谓的段寄存器之一。然而,在保护模式环境中,段寄存器充当选择器寄存器。
虚拟内存选择器代表其自己的虚拟地址空间映射及其自己的访问机制。实际上,
%gs:0x14
可以被认为是对原点保存在 %gs 中的数组的引用(尽管 CPU 做了一些额外的取消引用)。在现代 GNU/Linux 系统上,%gs
通常用于指向线程本地存储区域。然而,在您询问的代码中,只有 TLS 的一项很重要 - 堆栈金丝雀。这个想法是尝试通过放置一个随机但恒定的值来检测缓冲区溢出错误 - 它被称为“堆栈金丝雀”,以纪念金丝雀煤矿工人用来通过以下方式发出有毒气体水平增加信号的信号:死亡 - 在调用
gets()
之前进入堆栈,在其堆栈帧上方,并在gets()
返回后检查它是否仍然存在。 gets() 没有必要覆盖堆栈的这一部分 - 它位于自己的堆栈框架之外,并且没有给出指向它的指针 - 因此,如果堆栈金丝雀已经死亡,那么某些东西就消失了以危险的方式错误。 (C 作为一种编程环境,恰好特别容易出现此类错误,安全研究人员在过去二十年左右的时间里已经学会了利用其中的许多错误。此外,gets()
也会发生是一个本身就存在目标缓冲区溢出风险的函数。)您尚未在代码中提供地址,但 0x80484ac 可能是leave
的地址,并且调用0x8048394
,在不匹配的情况下执行(即在匹配的情况下被je 0x80484ac
跳过),可能是对__stack_chk_fail()
的调用,由 libc 提供,用于通过逃离隐喻的毒矿来处理堆栈损坏。堆栈金丝雀的规范值保存在线程本地存储中的原因是,这样每个线程都可以拥有自己的堆栈金丝雀。堆栈本身通常不在线程之间共享,因此自然也不共享金丝雀值。
In the AT&T style assembly languages, the percent sigil generally indicates a register. In x86 family processors from 386 onwards, GS is one of the so-called segment registers. However, in protected mode environments segment registers work as selector registers.
A virtual memory selector represents its own mapping of virtual address space together with its own access regime. In practical terms,
%gs:0x14
can be thought of as a reference into an array whose origin is held in %gs (albeit the CPU does a bit of extra dereferencing). On modern GNU/Linux systems,%gs
is usually used to point at the thread-local storage region. In the code you're asking about, however, only one item of the TLS matters — the stack canary.The idea is to attempt to detect a buffer overflow error by placing a random but constant value — it's called a stack canary in memory of the canaries coal miners used to employ to signal increase in levels of poisonous gases by dying — into the stack before
gets()
gets called, above its stack frame, and check whether it is still there aftergets()
will have returned.gets()
has no business overwriting this part of the stack — it is outside its own stack frame, and it is not given a pointer to it —, so if the stack canary has died, something has gone wrong in a dangerous way. (C as a programming environment happens to be particularly prone to this kind of wrong-goings, and security researchers have learnt to exploit many of them over the last twenty years or so. Also,gets()
happens to be a function that is inherently at risk to overflow its target buffer.) You have not offered addresses with your code, but 0x80484ac is likely the address ofleave
, and thecall 0x8048394
which is executed in case of mismatch (that is, jumped over byje 0x80484ac
in case of match), is probably a call to__stack_chk_fail()
, provided by libc to handle the stack corruption by fleeing the metaphorical poisonous mine.The reason the canonical value of the stack canary is kept in the thread-local storage is that this way, every thread can have its own stack canary. Stacks themselves are normally not shared between threads, so it is natural to also not share the canary value.
ES、FS、GS:额外段寄存器
可用作额外的段寄存器;也用于跨段的特殊指令(如字符串副本)。
取自此处
http://www.hep.wisc.edu/~pinghc/x86AssmTutorial。 htm
希望有帮助
ES, FS, GS: Extra Segment Registers
Can be used as extra segment registers; also used in special instructions that span segments (like string copies).
taken from here
http://www.hep.wisc.edu/~pinghc/x86AssmTutorial.htm
hope it helps