Windows内存漏洞——栈溢出漏洞及其利用分析

栈溢出漏洞及其利用分析

栈帧的标识

  • ESP:扩展栈指针寄存器,其存放的指针指向栈顶
  • EBP:扩展基址指针寄存器,其存放的指针指向栈底
  • EIP:扩展指令指针寄存器,其存放的指针指向下一条要执行的指令

栈帧中的内容

一个函数栈帧中主要包含的信息:

  • 前一个栈帧的栈底位置,也就是前栈帧的EBP,用于在函数调用结束后恢复主调函数的栈帧
  • 该函数的局部变量
  • 函数调用的参数
  • 函数的返回地址RET,用于保存函数调用前指令的位置,以便函数返回时能恢复到调用前的代码区继续执行指令

栈溢出漏洞的基本原理

  • 在函数的栈帧中,局部变量是顺序排列的,局部变量下面紧跟着的是前栈帧EBP及函数返回地址RET。如果这些局部变量为数组,由于存在越界的漏洞,那么越界的数组元素将会覆盖相邻的局部变量,甚至覆盖前栈帧EBP及函数返回地址RET,从而造成程序的异常。

栈溢出修改相邻变量

void fun()
{
	char psaaword[6] = "ABCDE";
	char str[6];
	gets(str);
	srt[5] = '\0';
	if(strcmp(str,password)==0)
	{
		printf("OK.\n");
	}else
	{
		printf("NO.\n");
	}
}
int main()
{
	fun();
	return 0;
}
  • 由于c语言中没有越界检查,因此当用户输入的口令超过两个字节时,将会覆盖相邻的password数组。此时,password数组和str数组的内容就会是同一个字符串。因此,在不知道正确口令的情况下,只要输入13个字符,其中前五个字符与后五个字符相同,就可以绕过口令的验证了。
  • 如果用户增加输入字符串的长度,将会超过password数组的边界,从而覆盖前栈帧ESP,甚至是覆盖返回地址RET。当返回地址RET被覆盖后,将会造成进程跳转的异常。

栈溢出后修改返回地址RET

  • #include<stdio.h>
    #include<string.h>
    #include<stdlib.h>
    void Attack()
    {
    	printf("Hello\n");//当该函数被调用成功时,说明溢出攻击成功
    	exit(0);
    }
    void fun()
    {
    	char password[6] = "ABCDE";
    	char str[6];
    	FILE *fp;
    	if(!fp=fopen("password.txt","r"))
    	{
    		exit(0);
    	}
    	fscanf(fp,"%s",str);
    	
    	str[5]='\0';
    	if(strcmp(str,password)==0)
    	{
    		printf("OK.\n");
    	}else
    	{
    		printf("NO.\n");
    	}
    }
    int main()
    {
    	fun();
    	return
    }
    
  • 如果在password文件中存入23俄国字符,程序运行结果将与从键盘输入一致。为了让程序在调用fun()函数返回后去执行所希望的函数Attack(),必须将password文件中的最后四个字节改为Attack()函数的入口地址。(用OllyDbg工具查看得到地址为0x0040100F),利用十六进制编译软件UItraEdit打开password修改最后四个字节。

  • 这样,运行该程序,Attack函数被正常执行。

栈溢出攻击

  • 攻击者通过缓冲区改写的目标不再是一个变量,而是栈帧高地址的EBP和函数的返回地址等值。通过覆盖程序中的函数返回地址和函数指针等值,攻击者可以直接将程序跳转到其预先设定或已经注入到目标程序的代码上去执行。
JMP ESP覆盖方法

由于动态链接库的装入和卸载等原因,windows进程的函数栈帧可能发生移位,也就是说shellcode在内存中的地址是动态变化的,所以只采用简单方式链接进行跳转是极有可能出错的

  • 所以,可以在覆盖返回地址时用系统动态链接库中某条处于高地址且位置固定的跳转指令所在的地址进行覆盖,然后再通过这条指令指向动态变化的Shellcode地址。
  • 在这种方法中,输入被攻击程序的字符串格式为NN…NNRSS…SS,其中N表示可以填入的一些无关的数据,R表示JMP ESP的地址,S表示Shellcode。
  • 当函数返回时,取出JMP ESP覆盖法攻击,攻击者需要做如下工作
    • 分析调试有漏洞的被攻击程序,活得栈帧的状态
    • 获取本机JMP ESP指令的地址
    • 写出希望运行的Shellcode
    • 根据栈帧状态,构造输入字符串
SEH覆盖方法

Windows异常处理机制所依赖的便是SEH结构体,他包含两个DWORD指针

  • SHE链表指针prev,用于指向下一个SEH结构
    • 异常处理函数句柄handler,用于指向一场函数处理的指针。
  • 当线程初始化时,会自动向栈中安装一个异常处理结构,作为线程默认的异常处理,这样多个异常处理程序就连结成了一个由栈顶向栈底延申的单链表,链表头部位置通过TEB(线程控制块)0字节偏移处的指针标识。
  • 如果发生异常,OS会中断程序,并且首先从TEB的0字节处去除最顶端的SEH结构地址,使用异常处理函数句柄所指向的代码来处理异常。如果该异常函数运行失败,则顺着SHE链表依次尝试其他的异常处理函数。(如果程序预先安装的所有异常处理函数均无法处理,系统将采用默认的异常处理函数,弹出错误对话框并强制关闭程序)
  • SEH覆盖方法就是覆盖异常处理程序地址的一种攻击方式。由于SHE结构存放在栈中,因此攻击者可以利用栈溢出漏洞设计特定的溢出数据,将SEH结构中异常函数入口地址覆盖为Shellcode的其实地址或可以跳转到Shellcode的跳转指令地址,从而导致程序发生异常时,Windows异常处理机制执行的不是预设的异常处理函数,而是Shellcode。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
模糊测试是一种测试方法,通过输入非正常和不符合预期的数据来探测软件应用的安全漏洞。它是一种自动化的测试方法,广泛应用于软件开发、信息安全和网络安全领域。模糊测试的目标是发现软件中的潜在安全漏洞,以帮助开发者及时修复并改进软件的安全性。 模糊测试通过生成大量的随机、异常和非法输入数据,将其输入到被测软件中,然后监测软件的行为和反应。如果软件在处理这些异常输入时出现异常崩溃、内存溢出、拒绝服务等异常行为,那么就可能存在安全漏洞。通过分析异常行为,测试人员可以推断出可能存在的安全漏洞,并进行修复。 模糊测试的优势在于它可以自动化地生成大量的测试输入数据,大大提高了测试的覆盖率。它可以有效地发现软件中隐藏的安全漏洞,包括缓冲区溢出、代码注入、SQL注入、跨站脚本攻击等常见的安全问题。与传统的手工代码审查相比,模糊测试可以更全面、更高效地发现安全漏洞。 模糊测试是一把强力的武器,对于提高软件的安全性至关重要。它可以帮助开发者在软件发布之前,尽早发现并修复存在的安全漏洞,从而减少软件被黑客利用的风险。同时,模糊测试还可以帮助企业和组织提升对系统和应用的信心,保障信息安全。 总之,模糊测试是一种强制发掘安全漏洞的利器。它通过生成大量的异常输入数据,并监测软件的行为,可以有效地发现软件中的潜在安全问题。作为软件开发和信息安全领域的重要工具,模糊测试在保障软件安全方面发挥了重要作用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值