CS:APP缓冲区溢出攻击练习题

CS:APP一书的第三章最后的练习题是一个练习缓冲区溢出攻击的题目

程序是这样的

要求是输出0xdeadbeef

先谈在VC6.0下的攻击,一般有两种方法进行攻击

第一种较为简单,分析test()的反汇编代码

在调用完getbuf()之后,将返回值,即eax中的值放入栈中,然后入栈,作为调用printf的参数,思路就是修改入栈的第一个参数值然后返回地址直接设置到第二个参数入栈的地址,即push offset string "getbuf returned 0x%x/n"(0042301c),地址是00401271

第一个参数入栈的地址就是返回地址在栈区的位置+4,相对于getbuf()的栈帧,就是ebp+8,那么我们进行攻击的目标就是ebp的值保持不变,返回地址设置为00401271,[ebp+8]的位置设置为0xdeadbeef,攻击代码为

00 00 00 00 00 00 00 00 00 00 00 00 a0 ef 12 00 71 12 40 00 ef be ad de

前12个字节是任意的

攻击的结果会得到0xdeadbeef,但是会出现错误,位置是

00401286 E8 95 04 00 00       call        __chkesp (00401720)

因为并没有将deadbeef入栈,只是设置了栈区的值,esp的值没有-4,所以导致esp的值校验错误,程序非正常终止。

第二种方法是将汇编代码写入栈中以buf开头的地址中,然后让返回地址跳转到buf的位置,执行我们写入的指令,然后正常终止程序,这种攻击需要对运行时栈帧有正确的理解

相对于getbuf的栈帧从高地址到低地址是,[ebp+4]是返回地址,然后就是getbuf的栈帧,ebp,然后是buf区,原题给的是12个字节的buf,但是相对于VC6.0,12个字节攻击不够用,所以我给改成了16个字节,首先我们需要指令做什么呢,getbuf返回后,eax中的值为0x1,作为返回值,首先把eax中的值修改成我们想要的,就是0xdeadbeef,汇编代码是

mov eax $0xdeadbeef,code bytes就是b8 ef be ad de

其次,我们需要正确返回,原先保存的ebp值不能变,就是0x0012efa0,同时要设置好返回地址,返回地址就是buf的地址,分析汇编代码可知,就是ebp-16,0x0012ef38,这样,程序在从getbuf返回后就会跳转到buf处,执行mov eax $0xdeadbeef,然后,我们需要继续可以返回到原代码中调用getbuf()的下一条指令的地址,这时候需要执行push 返回地址,就可以将返回地址压入原返回地址的位置,

返回地址为0x0040126a,push $0x0040126a,code bytes就是68 6a 12 40 00,接下来的指令就是ret,code bytes为c3,然后为了对齐可以设置一个nop指令,90,然后的四个字节随意设置,因为紧系chkesp的时候这四个字节会被覆盖掉,这也是为什么要16个字节攻击,ebp的值设置为0x0012efa0,返回地址设置成0x0012ef38,这样完整的序列就是

b8 ef be ad de 68 6a 12 40 00 c3 90 00 00 00 00 a0 ef 12 00 38 ef 12 00

实验结果是成功返回deadbeef,并且正确退出

在GCC中的情况相同,但是第二种方法只是在gdb模式下才成功攻击,应该是有某种缓冲区溢出防护机制?

 

阅读更多
个人分类: C
上一篇关于未定义行为的一些研究
下一篇CS:APP中的tsh示例
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭