欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  科技

简单实现栈溢出实验(IDA)

程序员文章站 2022-05-25 08:01:25
有关栈溢出的相关知识最近学校讲到了栈溢出,并有一道很基础的题,在此可以记录一下,感兴趣的人可以了解了解...

有关栈溢出的相关知识

最近学校讲到了栈溢出,并有一道很基础的题,在此可以记录一下,感兴趣的人可以了解了解.
/
栈溢出:
/
首先谈到栈溢出,要先说windows系统典型漏洞分析。
/
栈溢出也是其中的一种。
/
要了解栈溢出,要先了解:

1.主角:栈 与 栈帧

栈(音:zhan四声)是一种特殊的线性计算机内部存储结构,服从先进后出的一种特殊线性结构,如同弹夹里的子弹,先放入的子弹,在最下面。栈的结构使其只能在栈的顶端进行增加数据和删除数据的操作,压入数据称为(push),弹出数据称为(pop).
/

2.内存结构

在win32环境下,由高级语言生成的可执行文件,即PE文件,(Portable Executable)文件。在运行可执行文件时,系统会将其加载到内存,并映射出4GB的虚拟存储空间,然后继续运行,形成所谓的进程空间。(教材原话)
/
在win32中将进程使用的内存按功能可以分为4个区域,如下图:
/

名称 作用
栈区(stack) 用于动态存储函数之间的调用关系 低地址
堆区 该内存区域由进程利用相关函数和运算符动态申请
代码区 存放程序汇编之后的机械代码和只读程序,计算机运行程序,会在该区域读取命令并执行。
数据区 用于存储全局变量和静态变量 高地址

/
其在计算机内存中的结构也如下图:

栈区 ↑栈增长方向
堆区 ↓堆增长方向
代码区
数据区

代码实现

/

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void attack()
{
	printf("TRY IT!.\n");       //attack函数
}
void func()                     //func函数
{
	char password[6] = "ABCDEF";
	char str[6];
	FILE *fp;
	if(!(fp=fopen("D:\\password.txt","r"))) //打开D盘的password.txt文件
		exit(0);
	fscanf(fp,"%s",str);           //将str的内容写入fp
	str[5]='\0';
	if(strcmp(str,password)==0)    //判断str是否与password相同
		printf("OK.\n");
	else
		printf("NO.\n");            
}
int main()
{
	func();          //运行func函数
	return 0;
}

/

用软件IDA实现栈溢出实验(步骤)

/简单实现栈溢出实验(IDA)
在D盘的password.txt中输入一定量的字符串,运行程序,AAAAA…与指定的password并不相同,所以返回了“NO”。

现在打开IDA.

1.打开

简单实现栈溢出实验(IDA)
得到如下:
/简单实现栈溢出实验(IDA)
/
现在展示的IDA适用静态调试,左边可以清晰地看到函数体,这是IDA比较清晰简便的一个优点。

2.寻找函数名称

简单实现栈溢出实验(IDA)
点击左侧的函数名可以进入。右侧也可以查看十六进制视图:简单实现栈溢出实验(IDA)
IDA快捷键,按F5可以查看伪代码。伪代码可以让人较为清晰地了解函数的部分构造,但不是能运行的代码。在这里,用鼠标左键双击左侧函数名称中的func(),再按F5可以进入func函数查看伪代码:

3. F5查看伪代码

简单实现栈溢出实验(IDA)

简单实现栈溢出实验(IDA)
在上图中点击各个变量,可以查看栈。

4.查看栈

简单实现栈溢出实验(IDA)

查看到str,password,fp在栈中的位置

/

注意到最下面有一个"r"

/

这里"r"指的是return adress,这里简述为ret,ret指的是返回地址,ret在汇编中也有涉及。
这里的ret主要功能是返回下一个函数的地址,用于在一个函数运行完后跳转到下一个函数,栈溢出攻击在这里运行的原理是,通过文本中读入过量的数据,从而,是数据在栈上溢出,使其覆盖正常的数据,从而引起漏洞与异常。

/

如果,溢出的数据覆盖了ret地址,那么函数可以跳转到一个指定的函数,即上文的“attack”函数。

/

所以在这里开始,找到attack函数的地址:

简单实现栈溢出实验(IDA)
然后,只要将attack()的地址,输入到文本的末尾即可。但是,要满足其刚好能将ret的地址覆盖,使函数跳转异常,从而跳转到指定的攻击函数。
/

那么,来计算一下,在文本中输入多少个字符会刚刚覆盖到“r”,处:

/

这里查看到这个信息: [esp+10h] [ebp-18h] (如下图)
/

5.分析怎么实现栈溢出

简单实现栈溢出实验(IDA)

由于内存栈区的地址由高地址向低地址增长,当4个字节压入栈帧时,即为 ESP=ESP-4, 有4个字节弹出栈帧时, ESP=ESP+4.

ESP(extended stack point)是扩展栈指针寄存器,其存放地址指向这个栈帧的栈顶
/
EBP(extended base point)是扩展基址指针寄存器,其存放地址指向这个栈帧的栈底。

/
ESP与EBP之间是当前栈帧的空间。

上图意为,从前栈底到str存放的位置还有18个字节。即[ebp-18h]的含义。

其实从IDA中也能清晰看出来:

简单实现栈溢出实验(IDA)
上图中,可以看到变量str,password,fp存放在栈中的位置,可以看到上图用红色框框选的,有18个字节,也就是上文的[ebp-18h],下面蓝色框有10个字节,即到r为止。
/
数据从上方加入,那我们只要在文本前加入(10+18)=28个字节,就可以刚刚覆盖到r处,r是运行完后要跳转的函数地址,那我们在28个直接之后加入,攻击函数attack()的地址即可。
/

简单实现栈溢出实验(IDA)
将D盘的password.txt文件拖入软件“HxD”中,一种文本编辑软件,notepad++也可。
输入28个字母,之后将attack()的地址加入,即"00 40 13 50",但这里是小端序。

这里讲一讲:

6.小端序和大端序

字节序即为多字节对象存储在内存中的字节顺序,有两种不同的存储方案:大端法和小端法。现代的处理器大多为双端法,大小端都支持,可以配置称大端法或者小端法。
/
大端序:(Big-endian):高位字节存入低地址,低位字节存入高地址
小端序:(Little-endian):低位字节存入低地址,高位字节存入高地址

7.继续,运行结果,原理

一般x86位的CPU都为小端序:所以在编辑时将地址反着写,写作"50 13 40 00",
然后,点击“保存”文件。
/
再打开编译器,运行:
/
简单实现栈溢出实验(IDA)
运行结果出现了TRY IT!,明显这是attack()函数的内容,已经完成了栈溢出,使函数运行出了指定的内容,这就是用IDA实现的简单的栈溢出攻击实验。
/
通过栈上数据的溢出,覆盖了,正确的r返回地址,从而使函数跳转出现失误,或指向性的跳转。可以加以利用。

本文地址:https://blog.csdn.net/fightte/article/details/108834167