记录黑客技术中优秀的内容, 传播黑客文化,分享黑客技术精华

初探缓冲区溢出 C++ strcpy

2015-04-11 15:55
87eee72be03b0cea216e37b0ec22567b

Author:sco4x0

Team:www.secbox.cn

Blog:http://www.sco4x0.com
花了两天时间看这个东西,很多知识都是刚刚接触到的,如果各位看到有什么地方是错误的,请麻烦指正一下,不胜感激
以下都是从这两天看的资料中抽出来的
缓冲区是可以抽象成一段可以进行读写的内存区域,按照冯诺依曼存储体系,程序代码作为二进制数据存储在内存中,程序的数据也在内存中,包括ebp以及ret,因此直接从内存的二进制形式上无法区分什么是数据什么代码,但是这都给缓冲区溢出提供了可能

1.jpg

进程地址空间分布可以用上面这个图来表示,代码存储了用户程序的所有可执行代码,在程序正常执行的情况下,程序计数器(PC指针)只会在代码段和操作系统地址空间(内核态)内寻址。数据段内存储了用户程序的全局变量,文字池等。栈空间存储了用户程序的函数栈帧(包括参数、局部数据等),实现函数调用机制,它的数据增长方向是低地址方向。堆空间存储了程序运行时动态申请的内存数据等,数据增长方向是高地址方向。除了代码段和受操作系统保护的数据区域,其他的内存区域都可能作为缓冲区,因此缓冲区溢出的位置可能在数据段,也可能在堆、栈段。

一些名词:
ESP(Extended stack pointer)是指针寄存器的一种(另一种为EBP)。用于堆栈指针。

栈帧:栈是从高地址向低地址延伸的。每个函数的每次调用,都有它自己独立的一个栈帧,这个栈帧中维持着所需要的各种信息。寄存器ebp指向当前的栈帧的底部(高地址),寄存器esp指向当前的栈帧的顶部(低地址)

栈(操作系统):由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈

缓冲溢出(Buffer overflow):当计算机向缓冲区内填充数据位数时超过了缓冲区本身的容量,使得溢出的数据覆盖在合法数据上,理想的情况是程序检查数据长度并不允许输入超过缓冲区长度的字符,但是绝大多数程序都会假设数据长度总是与所分配的储存空间相匹配,这就为缓冲区溢出埋下隐患。操作系统所使用的缓冲区又被称为”堆栈”.。在各个操作进程之间,指令会被临时储存在”堆栈”当中,”堆栈”也会出现缓冲区溢出

我在本机上使用VC++6.0,使用strcpy来进行测试,写一段小程序


1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

void foo(){
  printf("Hello OverFlow\n");
}

void main(){
  char name[10];
  char output = "AAAAA";
  strcpy(name,output);
  printf("%p\n",&foo);
}

定义一个foo函数,函数实现打印Hello OverFlow这句话,main函数中,定义一个char数组,给了10个字节的长度,再定义一个char数组,给了AAAA的值,然后使用strcpy进行字符串的复制操作,最后一句话是打印出foo函数在内存中的地址。运行程序,得到foo函数的地址,这个时候并没有做其他非法操作,程序很流畅地运行并打印出了foo函数的地址

3.png

我们知道char在内存中占1字节的空间,这里给name给了10字节的空间,也就是说strcpy复制的时候,buffer区域是10个字节,我们将output数组的内容改一下,改成AAAAAAAAAAA,是一个A,这时候超出了10个字节,运行之后却发现并没有出什么问题,完全就是正常运行,这个问题出在字节对齐这上面

结构是一种复合数据类型,构成元素可以是基本数据类型,也可以是复合数据类型,在结构中,编译器为每个成员按其自然边界分配空间,第一个成员的地址和整个结构的地址相同,也就是首地址,字节对齐可以便于cpu的快速访问,也可以有效地节省存储空间,32位机中,4字节对齐是最优,可以使cpu访问速度提高,如果跨过4字节边界,那么就要读多次,而1,2字节反而会使访问速度降低,所以这是处理器类型和编译器类型来决定,我用的是VC++6.0,在VC中默认是4字节对齐
关于4字节对齐,我在VC++6.0中做过测试,char a[1],a[2],a[3],a[4] 在汇编代码中,很清楚地看到,开辟局部变量空间的时候,只会增加4个字节的空间,5-8长度的时候,又增加4字节。所以我测试代码中10长度的数组,在内存空间中的真正长度是12,那么输入13个A,然后运行看看效果

5.png

程序自己崩溃了,但是这仅仅是存在溢出,然后就是利用这个溢出点
输入13个A之后,进入调试模式往下走,执行完strcpy之后,查看这时ebp的值

6.png

可以很明显地看到,ebp中多出了1个字母A。而上面13个字母,刚好是多出了buffer1个A字母,再改成AAAAAAAAAAAAAAAx,执行之后看监控

7.png

78是x,41是A,也就是说16个字节的字符串,就能够完成溢出缓冲区并覆盖掉ebp,然后再写入4个字节的覆盖掉ret,让他返回到foo函数的地址,所以构造出来最终的payload是:AAAAAAAAAAAAAAAA\x19\x10\x40\x00,重新运行,即可看到,程序中并没有调用foo函数,但是也将foo函数执行了一次

8.png

转载初探缓冲区溢出 C++ strcpy请注明出自:安全盒子

知识来源: www.secbox.cn/hacker/program/c/2350.html

阅读:166370 | 评论:0 | 标签:C++ C# strcp 缓冲区溢出 溢出

想收藏或者和大家分享这篇好文章→复制链接地址

“初探缓冲区溢出 C++ strcpy”共有0条留言

发表评论

姓名:

邮箱:

网址:

验证码:

公告

九层之台,起于累土;黑客之术,始于阅读

推广

工具

标签云