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如下: