【原创】缓冲区溢出

 

缓冲区溢出

相信大家对缓冲区溢出并不陌生,此片文章将带领大家从最基础的缓冲区开始了解缓冲区溢出攻击。

主要原理就是通过往程序的缓冲区写超出其长度的内容,造成缓冲区的溢出,从而破坏程序的堆栈,使程序转而执行其它指令,以达到攻击的目的。造成缓冲区溢出的原因是程序中没有仔细检查用户输入的参数。

拿个简单的C/C++程序引入:

 

int main()

 

{

char name[10];

scanf("%s", name);

printf("输入的是:%s\n", name);

system("pause");

return 0;

}

 

环境:win10+VS2013+VC6.0+OD

实验前关一下安全检测。

 

 

先不说问题存在哪,编译完我们直接运行。

 

 

我们连续输入了9个字符后程序是正常执行流程的,最后打印出来了。

可当我们连续输入11个字符后。

 

 

崩溃了。。。

我们知道SCANF()当没有对NAME进行长度检验的时候就会造成数组溢出。

对程序下个断点后跑起来看看问题。

在调试前,建议大家把异常处理的忽略都关掉。

关掉后所有的错误都可以看到了,方便我们知道哪里的异常提示。

 

 

 

 

CALL之后呢008F1BC8会被压入堆栈,再CALL之后008F1BCD也会被压入进去。

原因是当CALL执行完调用的函数后,EIP指针能够返回到CALL指令的下一跳执行的指令地址了。但是原来的返回ret eip地址被改了。

跟进main函数入口。

Push ebp

Mov ebp,esp

Sub esp,0D4H

经典的main入口汇编代码。

 

 

虽然调试器不一样汇编代码也有区别,但结果是一样的。

 

 

执行完后的样子

 

 

套个此生大牛的图就是这样的,最原理的图。

 

此图让刚入门的朋友更好理解。

 

不好意思,拿错了。

 

 

上图流程就是我们从scanf()读取输入的数据写入到name的地址中,但是分配的只有10,超过10后的字符将被写入到函数执行完后的EIP地址(ret eip)

 

 

也就是说把正常程序执行的流程给覆盖掉了,来张比较形象一些的图。

 

 

攻击代码这里所说的就是shell code的,通过上图我们可以知道RET EIP的地址了,也就是name+14的地址。

为了可观一些我把该代码转用VC6.0编译。

 

 

程序提示了616161就是a

 

我们的输入的A把RET EIP地址给覆盖掉了,操作系统不明白aaaa是啥玩意儿,所以程序提示了不能读。当程序发生异常后会优先发给调试器,调试器就中断了。

 

断在了异常处理函数

 

这里不用管他了,我们使用windbg来找ret eip 的地址。

0012FF7D就是我们要的地址了,这里我的操作系统并没有kernel栈随机化。

 

总结:在整个溢出过程中申明了空间,但是所操作的数据超过了buff空间,也就是操作越界,覆盖了栈中的ret eip单元数据,把main函数的返回地址改了,这样以来main操作结束后返回的就是这个地址作为返回地址运行。

可在实际情况中是没有源码的,我们还需要对buff写入多长后会发生溢出等进行逆向分析动态调试,还需要考虑程序流及shellcode空间的存放(shellcode本质上就是一段机器码)等以及ASLR,以上所涉及知识也是最简单同时最为核心的。

参考资料:https://blog.csdn.net/lanuage/article/details/52985499

https://blog.csdn.net/pianogirl123/article/details/53748761

https://blog.csdn.net/x_nirvana/article/details/68921334

 

posted @ 2018-03-26 15:36  blck  阅读(351)  评论(1编辑  收藏  举报