感觉这个题调试着学到不少知识,单独放出来一篇 Orz
exp
1 | # encoding=utf-8 |
首先申请几个 chunk,然后对其中一个 free 两次,因为有 tcache 机制,所以可以 free,且会放在同一个 tcache 链表中 0x555555768e70
接下来申请回来 0x50,反手把 fd 指针改掉,改成 0x555555768e70-0x11e60=0x555555757010
不太理解这个分配机制,都改掉链表了啊!?为啥还会分到之前那里!?
可能是这样的,本来:0x555555768e70 -> 0x555555768e70
申请一个,同时把这个地方的 fd 指针给改为 0x555555757010
这时候成了 0x555555768e70 -> 0x555555757010
,再去申请的时候申请到了 0x555555768e70
然后 tcache 链表是这样的:0x555555757010
,然后再去申请的时候把 fd+0x40(不明白为啥是这样一个地方 fd+0x40 这样子,明白了看后面吧 hhhh)改成 0x555555768ec0,而 tcache 再去找的时候也确实是找了这个地方
然后我发现在一开始 remove 之后 0x555555757070
这里就有指向第 0 个的指针了,难道这是链表头部?
一点一点看看,首先是全部申请之后:啥都没有
对第 0 个 remove 一次之后:出现了第 0 个的地址
对第 0 个第二次 remove 后:第 0 个的 fd 也指向第 0 个了,合情合理
然后去 malloc 一个,同时把 fd 指针改成 0x0000555555757010
因为 free 了两次,所以应该还指向第 0 个,但是第 0 个的 fd 指针已经改变了
然后再去申请一个的话 tcache 就指向更改的那个 0x0000555555757010 了
我们再通过申请时写入到 0x555555757050 使得前面有个地方改成 0x0000555555768ec0
(这时候突然意识到 tcache 是每种大小的在一个链表),exp 中后面再去 malloc 的是 0x10,往后数一下,我们之前看到的 0x555555757070 正好是 0x50 大小的链表那里!!
也就是说如果下一个申请的是 0x10 大小的话就应该去 0x555555757050 去找指针
而我们写入的那个 0x0000555555768ec0 正好是第 1 个 chunk 的 chunk 头,也就是说这样我们就能控制第 1 个 chunk 的 size 了,我们在申请时将它的 size 改为了 0x100
另外 0x555555757010 这个地方正好对应着 tcache 的数量,比如一开始 remove 了两个以后这个地方成了 2
因为我们前面已经把除了我们要用的都改成了 0x61(’a’)了,所以即使 0x100 也会放入 unsorted bin 中
然后去 malloc 一个的同时把第 0 个的 fd 指针又改为了刚才释放的那一个,强行排队 2333
这样再去申请第三次的时候就会申请到 unsorted bin 的地址,通过给的 gift 就能知道 main_arena+96 的地址了,然后就能计算出 libc 的地址啦!
然后要做的就是 double free 编辑 free_hook 为 system 的地址,然后去 free 第三个就可以拿到 shell 了(因为前面我们把第三个上写入的是 “/bin/sh”)
当然,也可以直接编辑 free_hook 为 one gadget,这样随便 free 哪一个都可以啦!