gets()函数缓冲区溢出实验

6 篇文章 0 订阅
6 篇文章 0 订阅

用于测试的漏洞程序如下:

#include<stdio.h>
#include<windows.h>
void pf()
{
    char buf[50];
    gets(buf);
	printf("%s\n",buf);
	
}

int main()
{
	int a;
	printf("this is just a test\n"); 
	pf();
	system("pause");
		return 0;
}

pf函数中开启了一块大小为50字节的缓冲区,并调用

gets()函数获取用户输入。gets()函数,不受输入限制

可能会覆写掉栈中的返回地址。造成缓冲区溢出,人

为写入返回地址会导致程序执行恶意代码。

由于是在win10上实验,我又额外写了个小程序用于

重定向输入至一个txt文本文件,并用16进制编辑软件

来写入shellcode。

程序功能很简单,输入字符串,回显:

我测试让程序输出两次 欢迎字符串 “this is just a test”

win32下程序拥有固定的内存加载位置,所以可以通过反汇编软件找出

指令地址,我用了od实验。

40152c处字符串传参,下一条指令调用函数输出。

所以目标是将40152c这个地址覆写入pf()函数所在栈区的返回地址。

od中跟进,大概计算出偏移量3A+4 个字节便是返回地址之前要填充的

缓冲区,我不太明白为什么时3A(58字节)我的数组时50字节

现在构造一个输入,我只是测试一下缓冲区,所以也不弄shellcode了,前面

的缓冲区用字节填充,最后补上40152c用作返回地址,也就是之前 欢迎字符串

传参的地址。最后补上/r/n刷新缓冲区。

现在用一个重定向程序将文本的值刷入程序输入中,使用win32的管道就可以重

定向输入,输出了。

 

构造的输入保存在a.txt中

至此完成,程序除了输出回显外,有输出了一次我们的欢迎字符串

不过在这之后,也果不其然的崩溃掉了。

下面是我写的重定向的代码

#include "stdafx.h"
#include<Windows.h>
#include<iostream>

using namespace::std;

char name[256] = "\x00";
char app[256] = "\x00";
char wbuf[1024] = "\x00";
char rbuf[1024] = "\x00";
int size = 0;
void cancellast(char buf[]);
int _tmain(int argc, _TCHAR* argv[])
{
	
	HANDLE cproc = GetModuleHandle(NULL);
	GetModuleFileName((HMODULE)cproc,name,256);

	cancellast(name);
	cout<<"gets app name"<<endl;
	gets(app);
	strcat(name,app);

	STARTUPINFO si;
	HANDLE victim;
	HANDLE w1,r1;
	memset(&si,0,sizeof(si));
	si.cb = sizeof(si);      //置为默认
	SECURITY_ATTRIBUTES sa;

	sa.bInheritHandle = TRUE;
	sa.nLength = sizeof(sa);
	sa.lpSecurityDescriptor = NULL;  //进程权限
	if(CreatePipe(&r1,&w1,&sa,0))
		   cout<<"\npipe ready"<<endl;
	else  {cout<<"\npipe failed"<<endl; getchar(); return 0;}//通道

	si.hStdInput = r1;   //输入重定向到r1
	si.dwFlags= STARTF_USESTDHANDLES;

	PROCESS_INFORMATION ia;

	if(!CreateProcess(name,NULL,&sa,NULL,TRUE,CREATE_NEW_CONSOLE,NULL,NULL,&si,&ia))
	{
		cout<<"\nfailed! enter app again"<<endl;
		system("pause");
		return 0;
	}
	
	cancellast(name);
	cout<<"\nget txt name"<<endl;
	gets(app);

	strcat(name,app);
    while(1)
	{
		cout<<"\n------read file (Y/N)?----"<<endl;
		char confirm;
		cin>>confirm;
		if(confirm != 'y' && confirm != 'Y')
			break;

		FILE* intxt;

	    intxt = fopen(name,"r");
		if(intxt == NULL)
		{cout<<"failed open txt!! enter the name"<<endl;
		   break;
		}
		int words = fread(wbuf,1,1024,intxt);
		fclose(intxt);
		DWORD fwords = 0;
		WriteFile(w1,wbuf,1024,&fwords,NULL);

		cout<<"\n-------------------------"<<endl;
		
	}
	CloseHandle(w1);
	CloseHandle(r1);
	TerminateProcess(ia.hProcess,0);
	system("pause");
	return 0;
}

void cancellast(char buf[])  //获取目录
{
	int strsize = strlen(buf);
	while(name[strsize] != '\\')
	{
		strsize--;
	}
	buf[strsize+1] = '\0';
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值