首页
社区
课程
招聘
[原创]PWN:unsafe unlink
发表于: 2020-8-8 08:57 7419

[原创]PWN:unsafe unlink

2020-8-8 08:57
7419

主要是内存布局好之后,通过 unlink 来修改指针


正常的 unlink 是当我们去 free 一个 chunk 的时候,如果这个 chunk 的前一个或后一个是 free 的状态,glibc 会把它从链表里面取出来,与现在要 free 的这个合并再放进去,取出来的这个过程就是 unlink


wiki 上面的一个示意图,Fd 是前置指针,Bk 是后置指针

image


ulink 有一个保护检查机制,他会检查这个 chunk 的前一个 chunk 的 bk 指针是不是指向这个 chunk(后一个也一样)我们需要绕过他的检查


how2heap 这个程序展示了怎样利用 free 改写全局指针 chunk0_ptr 达到任意内存写的目的,即 unsafe unlink

ulink 有一个保护检查机制,他会检查这个 chunk 的前一个 chunk 的 bk 指针是不是指向这个 chunk(后一个也一样)

先在 main 函数上设置一个断点,然后单步走一下,走到第 13 行(不包括)


我们来看一下,申请了两个堆之后的情况


image.png


上面说的那个检查 fd/bk 指针是通过 chunk 头部的相对地址来找的,我们可以用全局指针 chunk0_ptr 构造一个假的 chunk 来绕过


再单步走到第 20 行(不包括)


image.png


这两行代码做了个减法,使得从这个地方数起来正好可以数到我们伪造的哪一个 fake chunk

chunk0_ptr[2] = (uint64_t) &chunk0_ptr-(sizeof(uint64_t)*3);

chunk0_ptr[3] = (uint64_t) &chunk0_ptr-(sizeof(uint64_t)*2);


image.png


上面那个图没对齐,用文本来解释一下

我们的 fake chunk 的 fd 指向 0x601058 然后 0x601058 的 bk 指向 0x601070

fake chunk 的 bk 指向 0x601060 然后 0x601060 的 fd 指向 0x601070,可以保证前后都指向我们伪造的这个 chunk,完美!


另外我们利用 chunk0 的溢出来修改 chunk1 的 prev_size 为 fake chunk 的大小,修改 PREV_INUSE 标志位为 0,将 fake chunk 伪造成一个 free chunk。


接下来释放掉 chunk1 因为 fake chunk 和 chunk1 是相邻的一个 free chunk,所以会将他两个合并,这就需要对 fake chunk 进行 unlink,进行如下操作

FD = P->fd

BK = P->bk

FD->bk = BK

BK->fd = FD


通过前面的赋值操作

P->fd =  &P - 3 * size(int)

P->bk = &P - 2 * size(int)

也就是说:FD = &P - 3 * size(int),BK = &P - 2 * size(int)

FD->bk 按照偏移寻址,就是 FD+3*size(int) 也就等于 &P,FD->bk = P,同理 BK->fd = P

这样执行下来,最终实现的效果是 P = &P - 3 * size(int)


也就是说,chunk0_ptr 和 chunk0_ptr[3] 现在指向的是同一个地址


image.png



这个师傅注释很详细,帮了大忙,下面也是根据这个 exp 复现的

https://blog.csdn.net/weixin_42151611/article/details/97016767


完整 exp:


运行连个菜单都不给...

把名字改一下


image.png


create 功能,输入一个 size,然后申请 size 大小的堆块


image.png


会把申请的堆块的地址写到这里(并不是,是 s[1],因为先 ++ 了)


image.png


edit 功能,编辑已经创建好的堆块,但是没有对长度进行检查,所以存在堆溢出


image.png


wp 说没有 setbuf,会先申请 1024 的堆空间??

要先提前申请个 chunk 来防止他们干扰??

怎么就能防止干扰了??

其实只要先申请一个,让程序把两个缓冲区分配好了,别后面插在我们申请的两个之间就可以吧

黄色指的是提前申请的一个用来占空的

两个白色是缓冲区占用的,这样后面再申请就连起来了


image.png


这时候来改写第 2 个(从 1 开始计数)伪造一个 free 的 chunk(黄线分割了第 2 和第 3 个)


image.png


payload 如下:

这样填充完了就是这样的,在原本第 2 个 chunk 里面伪造了一个 free 的 chunk,大小是 0x20,然后把 fd 跟 bk 指针写为了 p64(head+16-0x18) 和 p64(head+16-0x10)。同时把下一个堆块的 prev_size 位写成了 0x30(前一个 chunk 加上开头的大小),以及 size 位的 prev_inuse 为 0


image.png


这样,对第 3 个进行 free 的时候会发生 unlink,head + 16 与 head +16 -0x18

那么最终的效果就是我们编辑第二个的时候就是编辑的 head + 16 - 0x18,也就是 0x602138


image.png



[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

上传的附件:
收藏
免费 3
支持
分享
最新回复 (2)
雪    币: 3072
活跃值: (20)
能力值: ( LV1,RANK:40 )
在线值:
发帖
回帖
粉丝
2
赞! 学习一下
2020-8-8 10:21
0
雪    币: 6064
活跃值: (12624)
能力值: ( LV12,RANK:312 )
在线值:
发帖
回帖
粉丝
3
思路清晰
2020-8-8 10:54
0
游客
登录 | 注册 方可回帖
返回
//