缓冲区溢出以后

我在CSDN发的一个帖子,很久没写日志了,拿来充数,也回顾一下。

C代码如下:

#include<stdio.h>
#include<string.h>
#include<stdlib.h>

void func1(char *s)
{
    char buf[12];
    strcpy(buf,s);
}
void func2(void)
{
    printf("Why I can be printed ?\n");
    exit (0);
}
int main(void)
{
    char badcode[]="abcdefghijklmnopqrstuvwxyz";
    unsigned *p=(unsigned*)&badcode[16];
    *p=(unsigned)func2;

    func1(badcode);
    return 0;

}
这段代码在有的编译器(比如VC6)编译后,运行会打印“Why I can be printed?"。

试分析原因:

概括说就是溢出的字符串覆盖了main函数中“保存fun1返回地址“的栈区,使程序跳转到fun2。

下面是cygwin下gcc反汇编的代码:

_mystrcpy:
pushl %ebp
movl %esp, %ebp
subl $
16, %esp
movl
8(%ebp), %eax
movl %eax, -
4(%ebp)
L2:
movl
12(%ebp), %eax
movzbl (%eax), %edx
movl
8(%ebp), %eax
movb %dl, (%eax)
movl
8(%ebp), %eax
movzbl (%eax), %eax
testb %al, %al
setne %al
addl $
1, 8(%ebp)
addl $
1, 12(%ebp)
testb %al, %al
jne L2
movl -
4(%ebp), %eax
leave
ret
.globl _func1
.def _func1
; .scl 2; .type 32; .endef
_func1:
pushl %ebp
movl %esp, %ebp
subl $
24, %esp
movl
8(%ebp), %eax
movl %eax,
4(%esp)
leal -
12(%ebp), %eax
movl %eax, (%esp)
call _mystrcpy
leave
ret
.section .rdata,
"dr"
LC0:
.ascii
"Why I can be printed ?\0"
.text
.globl _func2
.def _func2
; .scl 2; .type 32; .endef
_func2:
pushl %ebp
movl %esp, %ebp
subl $
8, %esp
movl $LC0, (%esp)
call _puts
movl $
0, (%esp)
call _exit
.def ___main
; .scl 2; .type 32; .endef
.globl _main
.def _main
; .scl 2; .type 32; .endef
_main:
leal
4(%esp), %ecx
andl $-
16, %esp
pushl -
4(%ecx)
pushl %ebp
movl %esp, %ebp
pushl %ecx
subl $
36, %esp
call ___main
movl $
825307441, -29(%ebp)
movl $
842150450, -25(%ebp)
movl $
858993459, -21(%ebp)
movl $
875836468, -17(%ebp)
movl $
892679477, -13(%ebp)
movb $
0, -9(%ebp)
leal -
29(%ebp), %eax
addl $
16, %eax
movl %eax, -
8(%ebp)
movl $_func2, %edx
movl -
8(%ebp), %eax
movl %edx, (%eax)
leal -
29(%ebp), %eax
movl %eax, (%esp)
call _func1
movl $
0, %eax
addl $
36, %esp
popl %ecx
popl %ebp
leal -
4(%ecx), %esp
ret
尤其需要注意的是fun1中的这几句。
        pushl %ebp
        保存main函数的栈帧,占用4个字节。
leal -12(%ebp), %eax
movl %eax, (%esp)

        call
_mystrcpy

这三句可知fun1为拷贝留出的缓冲区大小是12个字节。

再注意到fun2的入口地址在badcode中的偏移恰好是16个字节,由于字符串的拷贝由低地址向高地址进行,所以

fun2覆盖的地方恰好是fun1执行ret语句返回时应该取出的地址。

于是程序欢快滴跳转了。

 
原文地址:https://www.cnblogs.com/liujiahi/p/2196397.html