0day安全2之栈溢出-修改邻接变量

前言

本片博客是复现《0day安全:软件漏洞分析技术》2.2节修改邻接变量,顺便加点自己在实践中的小问题。虽然这本书是2011年发行的,但对我这种小白来说还是颇为友好的。废话不多说正式开始。

原理

简单的说就是当局部变量var1在数组array1前声明时,如果没有array1对进行越界检查,则可能导致array1的在堆栈中超出原本的长度,对var1进行覆盖。如下图所示:
请添加图片描述

Windows

复现环境

操作系统:windows xp sp2 home
ollydbg:1.1
虚拟机:VMware16
程序:stack_overflow_var.exe

源代码

/*****************************************************************************
      To be the apostrophe which changed "Impossible" into "I'm possible"!
		
POC code of chapter 2.2 in book "Vulnerability Exploit and Analysis Technique"
 
file name	: stack_overflow_var.c
author		: failwest  
date		: 2006.9.20
description	: demo show nearby var overrun in stack
			  input 8 letters to bypass authentication  
Noticed		: complied with VC6.0 and build into begug version
version		: 1.0
E-mail		: failwest@gmail.com
		
	Only for educational purposes    enjoy the fun from exploiting :)
******************************************************************************/
#include <stdio.h>

#define PASSWORD "1234567"

int verify_password (char *password)
{
	int authenticated;
	char buffer[8];// add local buff
	authenticated=strcmp(password,PASSWORD);
	strcpy(buffer,password);//over flowed here!	
	return authenticated;
}


main()
{
	int valid_flag=0;
	char password[1024];
	while(1)
	{
		printf("please input password:       ");
		
		scanf("%s",password);
		
		valid_flag = verify_password(password);
		
		if(valid_flag)
		{
			printf("incorrect password!\n\n");
		}
		else
		{
			printf("Congratulation! You have passed the verification!\n");
			break;
		}
	}
}

操作步骤

  1. ollydbg 打开相应程序
    请添加图片描述
    打开后我们发现这不是我们编写好后main函数的位置,真正位置一般在GetCommandLineA()函数后第5个函数,如下如所示
    请添加图片描述F7单步步入,F2下断点,方便我们后续F9快速找到main函数,找到我们想要的入口点后,如下图所示
    在这里插入图片描述
    对照着源代码和相应的ascii码,我们不难看出1是printf函数,2是scanf函数,3是verify_password函数
    这里有个值得注意的地方,执行到scanf函数的时候,ollydbg红色标记的位置是不一样的,如下面两张图所示,只有运行到第一张图的时候,程序才接受用户输入,接着按回车,返回ollydbg,才能继续调试
    在这里插入图片描述
    在这里插入图片描述
    接着F7步入第三个函数,F8执行完strcmp函数后,如下图所示
    请添加图片描述
    因为我们输入的123456789比原密码1234567大,所以经过strcmp后EAX寄存器的值就变成了1,现在我们即将执行0x00401049,此处指令的含义是将EAX的值赋给EBP-4所指的地址当中,从图中可以看出EBP=0x0012FB24,那么EBP-4=0x0012FB20,从上图中可以看出0x0012FB20为0xCCCCCCCC,我们接下来执行以下,如下图所示
    请添加图片描述0x0012FB20确实变成了0x00000001,接着F8来到strcpy函数。由于没有做越界检查,我们输入了9个字节,但是程序只给buffer数组开辟了8个字节的栈空间,那么9肯定会覆盖到下一个字节上,也就是0x0012FB20的位置上,如下图所示
    请添加图片描述
    继续按F8,直到返回main函数,紧接着就是mov和cmp的指令
    请添加图片描述

意思是拿0和[EBP-4]比较,比较之后开始跳转,因此我们可以推断出[EBP-4]所代表的值就是源代码中的valid_flag,同时也是authenticated。[EBP-4]有时又EAX赋值的,EAX的值我们需要返回到verify_password中看,重新F9,F8,如下图所示
请添加图片描述EAX的值是又[EBP-4]=[0x0012FB20]的值也就是我们覆盖的9,这证明了通过栈溢出确实覆盖了邻接变量。
值得一提的是在verify_password中最后还有一个call调用,如下图所示,那个其实是做堆栈保护的,我们只是修改了邻接变量并没有改变函数流程,所以这个保护机制没有起到作用。
请添加图片描述

Linux

既然windows下会发生,Linux下也不会例外,下面我们看以下Ubuntu下的案例吧,这个是复现《黑客之道漏洞发掘的艺术》第二版

复现环境

操作系统:ubuntu21.04
gcc 10.3
gdb
虚拟机:VMware16
程序:stack_overflow_var.exe

源代码

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

int check_authentication(char *password){
	int auth_flag=0;
	char password_buffer[16];
	strcpy(password_buffer,password);
	if(strcmp(password_buffer,"brillig")==0)
		auth_flag=1;
	if(strcmp(password_buffer,"outgrabe")==0)
		auth_flag=1;
	return auth_flag;
}

int main(int argc,char* argv[]){
	if(argc<2){
		printf("usage:%s <password>\n",argv[0]);
		exit(0);
	}
	if(check_authentication(argv[1])){
		printf("\n===============================\n");
		printf("          Access Granted.\n");
		printf("\n===============================\n");
	}else{
		printf("          Access Denied.\n");
	}
	
}


从源代码中可以看出程序的本义是只有输入brillig或者outgrabe才能正确输出但实际上确是当我们输入大于28个字符时也能够使程序输出“Access Granted.”,至于为什么要28个以上就到gdb中调试看内存了。这里在编译时取消了gcc的安全优化。
请添加图片描述

操作步骤

  1. gcc -q auth_overflow

    list 查看代码,可以按回车看完所有的代码,我们在第8行和13行下断点,开始运行

在这里插入图片描述可以看出程序已停在第一个断点处,查看auth_flag以及password_buffer位置

在这里插入图片描述
0x7fffffffddac-0x7fffffffdd90=0x1c=28,意思是在栈中password_buffer起始位置距离auth_flag的位置有28个字节那么远,再查看password_buffer附近64个字节,不难看出两个变量在栈中的分布
,注意从右往左看。请添加图片描述接着cotinue,来到到第二个断点,同样方法查看内存,发现auth_flag位置也被覆盖了,这样就导致了即使输入了错误的字符串也能绕过程序。
请添加图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值