谁能帮我解释一下gcc的堆栈溢出检查机制?

软件和网站开发以及相关技术探讨
回复
头像
konglinglong
帖子: 90
注册时间: 2008-04-14 13:19
来自: 广东 茂名
联系:

谁能帮我解释一下gcc的堆栈溢出检查机制?

#1

帖子 konglinglong » 2008-06-09 16:21

原C代码:

代码: 全选

#include <stdio.h>
void return_input (void){
char array[10];
gets (array);
printf("%s\n", array);
}
int main()
{
return_input();
return 0;
}

用GCC反汇编后的代码:

代码: 全选

.file "test11.c"
.text
.globl return_input
.type return_input, @function
return_input:
pushl    %ebp
movl     %esp, %ebp
subl      $24, %esp
movl     %gs:20, %eax              //这个%gs:20值是什么,希望能详细解释下
movl      %eax, -4(%ebp)
xorl       %eax, %eax
leal      -14(%ebp), %eax
movl     %eax, (%esp)
call    gets
leal      -14(%ebp), %eax
movl     %eax, (%esp)
call   puts
movl    -4(%ebp), %eax
xorl      %gs:20, %eax
je .L3
call __stack_chk_fail          
.L3:
leave
ret
.size return_input, .-return_input
.globl main
.type main, @function
main:
leal      4(%esp), %ecx
andl     $-16, %esp
pushl    -4(%ecx)
pushl    %ebp
movl     %esp, %ebp
pushl    %ecx
subl      $4, %esp
call     return_input
movl     $0, %eax
addl      $4, %esp
popl      %ecx
popl      %ebp
leal      -4(%ecx), %esp
ret
.size main, .-main
.ident "GCC: (GNU) 4.2.3 (Ubuntu 4.2.3-2ubuntu7)"
.section .note.GNU-stack,"",@progbits
上次由 konglinglong 在 2008-10-06 12:01,总共编辑 2 次。
头像
tscmga
帖子: 274
注册时间: 2008-03-16 23:09

#2

帖子 tscmga » 2008-06-11 1:47

哈哈 在ubuntu里或者ubuntu的irc里面,有难度的问题,最好在晚上英文频道去问。。
头像
command
帖子: 306
注册时间: 2007-10-14 0:50
来自: GUCAS

#3

帖子 command » 2008-06-11 2:34

代码: 全选

movl %gs:20, %eax //这个不懂,希望能详细解释 
这句的意思是将gs+20这个地址放入eax中,在你提供的列子中gs+20中放的可能是字符数组的首地址,这样在调用gets时就会将输入的字符放入gs+20中。gets是滋生溢出的温床,因此

代码: 全选

movl -4(%ebp), %eax
xorl %gs:20, %eax 
movl -4(%ebp), %eax
xorl %gs:20, %eax
je .L3
call __stack_chk_fail //这里应该就是检查溢出问题
.L3: 
这段代码进行溢出检查,查看输入的字符数是不是超过了数组的长度,如果超过即产生溢出,否则没有溢出。
OS: Debian GNU/Linux
Version: lenny
Kernel: 2.6.36
Xorg: 1.4.2
CPU: Intel(R) Core(TM)2 Duo CPU E8400 @ 3.00GHz
HD: 320G SATA
Memory: 2G DDRIII
Graphics:Mobility Radeon HD 3450
头像
tscmga
帖子: 274
注册时间: 2008-03-16 23:09

#4

帖子 tscmga » 2008-06-11 4:22

我不知道楼上的说的对不对。我也是猜的。只是给个我的想法。
gs:20可能是个和程序无关的随机数。编译器会把这个放到分配在栈里的缓存的结尾。用完了,就再检查这个数看有没有改动。有些内存调试的也这么做的。
就是在字符串的末尾放上一个数,在退出的时候检查这个数是不是有没有变化,没有变化,就是正确的。如果你写越界了,覆盖了这个多余的字符,我就能检测到。
头像
tscmga
帖子: 274
注册时间: 2008-03-16 23:09

#5

帖子 tscmga » 2008-06-11 4:25

我说过这么样有难度的问题在这里是不能得到答案的。到什么www.freebsdchian.org去问问这样的问题。
头像
tscmga
帖子: 274
注册时间: 2008-03-16 23:09

#6

帖子 tscmga » 2008-06-11 4:30

就是这样的。一个帖子分几个发分多些 哈哈呵呵

代码: 全选


void cc(  )
{
char v[10];//编译器会在v[10]放上一个数.
puts(v);
gets(v);
//完了检查
}
头像
konglinglong
帖子: 90
注册时间: 2008-04-14 13:19
来自: 广东 茂名
联系:

#7

帖子 konglinglong » 2008-06-15 21:06

虽然还是不太清楚,不过谢谢大家的帮忙。 :o :o :o
头像
BigSnake.NET
帖子: 12522
注册时间: 2006-07-02 11:16
来自: 廣州
联系:

#8

帖子 BigSnake.NET » 2008-06-15 21:18

subl $24, %esp
movl %gs:20, %eax
movl %eax, -4(%ebp) 在栈顶放一个数
xorl %eax, %eax
leal -14(%ebp), %eax
movl %eax, (%esp)
call gets
leal -14(%ebp), %eax
movl %eax, (%esp)
call puts
movl -4(%ebp), %eax 取栈顶
xorl %gs:20, %eax 检查是不是变了
je .L3 没变就跳到后面
call __stack_chk_fail 否则, 溢出
.L3:
^_^ ~~~
要理解递归,首先要理解递归。

地球人都知道,理论上,理论跟实际是没有差别的,但实际上,理论跟实际的差别是相当大滴。
头像
aobi
帖子: 921
注册时间: 2008-06-22 12:27

#9

帖子 aobi » 2008-06-22 20:26

小脸美女,我用C代码对过才说的。就是
void cc( )
{
char v[10];//编译器会在v[10]放上一个数.
puts(v);
gets(v);
//完了检查
}
这个代码和lz很相似。用编译器gcc- -S -...stack .... 的。

我想他那个不是栈顶。 他那个是subl $24, %esp 。
hgshlg
帖子: 222
注册时间: 2007-08-30 14:45

#10

帖子 hgshlg » 2008-08-30 19:34

最近在看cs:app,在作缓冲区溢出攻击那题,发现ggc竟然有了这个机制 :o
回复