pwn(栈-攻防世界)

1:题目:repeater

checksec

64位小端序ELF程序

没有敏感字眼

main函数:

由于程序开启了pie保护,地址只剩下了后三位,我们需要先找到基地址才能继续解题。所以先要满足if判断来打印出main函数真实地址。

我们需要先第一次溢出使if判断相等打印出main函数地址,构造第一个payload来覆盖局部变量:p=flat(b'a'*(0x20),0x321321,word_size=64),然后接收main地址。

r.recvuntil("But there is gift for you :\n")

mainaddr=int(r.recvuntil("\n"),16)

然后mainaddr减去随机化的main后三位即为基地址

然后0x202040加上基地址即为真实地址,

这个地址可以读入shellcode,然后在溢出点的时候把返回地址覆盖为读入shellcode的地址即可getshell。构造第二个payload:p= b'a'*(0x30+8)+ p64(base + 0x202040)

exp如下:

2:题目:stack2

32位小端序ELF。

main函数:

分析代码逻辑,要求用户给定一个数组大小,然后输入数字。程序再提供展示,添加,更改,求平均值等的操作。1对应的是展示数组内容;2对应的是添加元素的操作。3对应的是更改元素的操作。4对应的是求取平均值操作。整个代码流程相对简单,但代码相对较长,仔细分析才能发现能利用的漏洞。

没有对数组索引值进行检验,意味着我们可以越界来修改数组以外的东西,那么目标就来了,我们可以把返回地址的内容修改为system并对其进行传参binsh的地址,当程序运行玩执行返回地址的内容的时候就拿到shell了。现在先确定数组的起始地址

对应的汇编代码

gdb调试:在0x80486d5处下断点,直接查看eax寄存器的内容

再来找程序运行完的返回地址:

gdb调试:在0x80488f2处下断点,注意:当函数运行到return语句的时候,栈顶一定是返回地址。

计算两者偏移。

然后在程序里选择3,执行更改内容的操作来更改返回地址里的内容,更改为system并传参binsh。

system地址

由于需要传参要知道binsh的地址

exp如下:

3:题目:dice_game

checksec

64位小端序ELF

main函数:

sub_A20函数:

程序逻辑就是每次这个函数返回值必须得是1,然后循环50次返回1,每次++v8,直到v8=50,也就是用户输入的数字随机数种子50次比对相等才能进入函数sub_B28

可以看到进入这个函数就能得到flag了。

要连续50次猜对随机数种子产生的随机数难如登天。那么就要改写随机数种子,使其每轮产生的随机数一致。构造payload:p1=flat(b'a'*(0x40),0x1,word_size=64)。

然后连续发送50次计算的随机数即可。

exp如下:

4:题目:pwn1

checksec

64位小端序ELF文件,开启了栈保护。

main函数:

存在明显的栈溢出点,扫了几眼程序,没有发现现成的system,ROPgadget找了一下,根本没有,只能从附件里的libc-2.23.so下手

执行函数找到之后,就要来泄露canary了。

canary存放的位置

距离s偏移位0x88

main函数里有puts

可以把用垃圾数据填充到canary处,但考虑canary是以'\x00'结尾,会防止canary被打印出来,所以构造payload时可以多发送一个\n来覆盖canary尾,p=b'a'*(0x88),然后sendline。(sendline会发送数据后再加一个\n),

canary泄露之后就可以来构造ROP链了,先泄露puts的got表来计算偏移,最后调用execve(/bin/sh)即可。

exp如下: