CTFshow PWN162
此文章参考了:
CTFshow PWN162 堆利用技巧大杂烩_ctfshow-pwn-162-CSDN博客
好好说话之IO_FILE利用(1):利用_IO_2_1_stdout泄露libc_libc泄露方式-CSDN博客
使用realloc函数来调整栈帧让one_gadget生效 - ZikH26 - 博客园
感谢师傅的讲解
本文章只描述了本地是操作是如何打通程序的,远程需要爆破出I0_2_1_stderr_ 的第四位 1/16 概率
本题使用了double_free,unsortedbin_attack 、_IO_2_1_stdout、house of spirit,UAF
经典的增删改查
add 后会有一个固定的 0x28 大小的 chunk,和一个自行输入 size 大小的 chunk,size 被限制大小,add 的 chunk 数量也被限制为 0x13,并且 s->data 为 inuse
此时的堆结构
show 是假函数,无法 show
delete 函数中,if 检测 chunk_s+v1 实际上并不是inuse 的值,所以这边是一个假判断
edit 函数也是假的
目前我们只有 add 函数和 delete 函数是正常的,所以我们只能使用增加和删除进行 exp 编写
首先程序是本地我使用的是 2.23-0ubuntu3_amd64,并不是本地远程,并且程序开启了 pie 保护
1 | $ sudo sysctl -w kernel.randomize_va_space=0 |
首先第一步我们需要将 chunk 放入unsortedbin 中,使其 fb 指针指向 main_arena+0x58,这边的值也是 libcbase+main_arena 基值+0x58,所以我们可以通过覆盖掉后四位使其到达 IO_2_1_stderr 中(后三位 0x5dd 是确定的,我们通过尝试得到第四位是 0x45dd),
首先先申请 5 个堆块
#0 将堆块的地址网上抬使其后续更好操作,并且后续还会用到
#1、2 进行 double free
#3 申请释放后会进入unsortedbin 中使其 fd 为 main_arena+0x58
#4 进行于 top chunk 隔离避免被融合
后续我们申请一个 size 为 0x68 大小的 chunk,此时我们的#0 chunk 就派上用场了,再进行 add 操作中程序会先申请一个 0x28 大小的 chunk(实际为 0x30),此时就会优先将 fastbin 中的 0x30 申请出去(原先#0 chunk 被 free 后存入),就不会和我们抢 #3 unsortedbin 中的
此时被申请出来后我们修改低四位为 0x45dd
切割后:
这边原本是 fd 和 bk,现在 fd 被进行了修改
成功将 fd 指向 stderr
后续我们进行 double free,将 chunk5 的地址改到 chunk1 中
71 行申请的 add 将 chunk 的 fd 末尾改为 0xd0 为 chunk5 的地址,这样可以成功的将 chunk5 挂入 fastbin 的链表中
再将前面的 chunk 申请出来即可申请出以0x7ffff7bc45dd (IO_2_1_stderr+157)为地址的 chunk
我们再来看一下stderr 中的结构
此处是 flag 的地址,我们需要修改为0xfbad1800 即可绕过 IO 的检查机制使其输出_IO_2_1_stderr 其中的内容,借此我们就可以进行计算 libc 的基地址,打 mallco-hook one_gadget
具体为什么修改为0xfbad1800 可以看,好好说话之IO_FILE利用(1):利用_IO_2_1_stdout泄露libc_libc泄露方式-CSDN博客,师傅讲的很详细
输出的为_IO_2_1_stderr_+192 的地址我们减去_IO_2_1_stderr_ 和 192 即可获取到基地址
后续再进行一次 double free 将fake_chunk 挂在进链表即可再使用realloc_hook 调整使 one_gadget 可执行,可以参考以下文章
使用realloc函数来调整栈帧让one_gadget生效 - ZikH26 - 博客园
1 | from pwn import * #引用pwntools库 |