pwn入门-栈溢出进阶
pwn入门-栈溢出进阶
stack smash
当栈溢出时,输出了文件名,可以猜测在程序执行一开始就读到内存中,进一步猜测,如果把flag读到内存中,知道了flag地址,就可以通过栈溢出输出flag
如果能溢出flag的地址,栈溢出就会输出
多进程下的爆破
爆破canary
依次爆破
stack_pivot
ciscn_2019_es_2
看看能不能溢出,好像不太行因为到Ebp 0x28,只能输入0x30,不够
看看能不能栈迁移栈迁移原理深入理解以及实操 - 先知社区
这里为什么要栈迁移呢?明明可以跳转到system函数,因为上面那个输出flag是假的,只是输出了字符”flag”
要想真的输出还需要传参,一传参,空间就不够了,就需要栈迁移
gdb调试一下:
上图的第一个框是参数s的地址
第二个框是main函数的ebp的地址,这里我要解释一下了,我们此时是步进入了vul()函数,此时上图显示的ebp是vul()的ebp,我们的框中的才是main()的ebp
所以我们此时知道参数s的地址了,就是ebp_addr-0x38
首先,泄露ebp的地址
IDA分析vul()发现提供了 printf 这一输出函数,printf函数在输出的时候遇到’\0‘会停止,如果我们将参数s全部填满,这样就没法在末尾补上’\0‘,那样就会将ebp连带着输出
之后就是布置s栈上的值
先画一下栈帧,结合栈帧进行讲解
IDA看s的栈结构,我们构造的payload大致可以分为这7个框
- 第一个框,这里是填充的aaaa字符串,这里是填入的我们前面进行gdb测试的字符串,这里存储的第二次pop ebp的弹出的内容,为的是接下来将system@plt存储到eip中
- 第二个框,这里是存放的是system@plt的地址
- 第三个框,这里存放的是system_ret_addr,这里随便填充即可,这里目的主要是维持栈的完整性
- 第4个框,这里存放的是放置binsh的地址,其实通俗的理解就是放置跳转到/bin/sh的地址
- 第5个框,是我们输入/bin/sh字符串之后存储的地方,这里顺便说一下为什么要利用8个字节进行存放我们的/bin/sh,因为/bin/sh占用7个字节,一个内存空间是远远不够的,所以我们调用2个内存空间进行存储。
- 第6个框,是我们进行覆盖ebp的地方,我们将这里覆盖为参数s的地址,这样的话,当我们pop ebp的时候,会跳转到参数s的地址,就可以输入0x28个字节的内容,从而可以将我们的ROP链构造
- 第7个框,这里就是随便写入一个leave;ret的地址即可
[原创]ciscn_2019_es_2栈转移-Pwn-看雪-安全社区|安全招聘|kanxue.com:
当然此处我们还有一个问题就是’/bin/sh’的地址我们不知道。我们可以通过泄露原来ebp的值来确定(就是上图中蓝色ebp的值),我们将此地址叫做addr,以免和ebp寄存器混淆.
printf函数会打印s字符串,且遇到0就会停止打印,所以如果我们将addr之前的内容全部填充不为0的字符,就能将addr打印出来,我们通过地址再计算出addr到s的距离,我们就可以通过addr来表示’/bin/sh’所在的地址了。
很明显啊,我们先通过第一个read传入payload,然后通过printf打印出addr的值(栈中蓝色ebp的值,为了不和寄存器ebp混淆,我们将其称之为addr),然后通过第二个read函数构造栈转移,执行systeam(‘/bin/sh’)
这里解释下为什么要泄露ebp的地址,因为我们做题都是在自己机器上做然后去打远程,我们不知道远程的ebp的地址,要先算,而且ebp是在内存中的,地址不定
1 | from pwn import * |