首页
社区
课程
招聘
unlink 系列
发表于: 2018-9-26 11:32 20989

unlink 系列

2018-9-26 11:32
20989

昨天接触到了一个新的堆溢出技巧——unlink。

unlink 用来将一个双向链表(只存储空闲的 chunk)中的一个元素取出来,可能在以下地方使用

malloc

从恰好大小合适的 large bin 中获取 chunk。

这里需要注意的是 fastbin 与 small bin 就没有使用 unlink,这就是为什么漏洞会经常出现在它们这里的原因。

依次遍历处理 unsorted bin 时也没有使用 unlink 的。

从比请求的 chunk 所在的 bin 大的 bin 中取 chunk。

Free

后向合并,合并物理相邻低地址空闲 chunk。

前向合并,合并物理相邻高地址空闲 chunk(除了 top chunk)。

malloc_consolidate

后向合并,合并物理相邻低地址空闲 chunk。

前向合并,合并物理相邻高地址空闲 chunk(除了 top chunk)。

realloc

前向扩展,合并物理相邻高地址空闲 chunk(除了top chunk)。


unlink的原理介绍网上很多资料介绍的都很详细了,这里推荐一个unlink,我下面分析的题目也都是这个链接所提供的题目。前辈的文章已经非常详尽了,我前人的肩膀上做一个补充。

这里再简单的介绍一下unlink。

unlink 用来将一个双向链表(只存储空闲的 chunk)中的一个元素取出来,可能在以下地方使用

malloc

从恰好大小合适的 large bin 中获取 chunk。

这里需要注意的是 fastbin 与 small bin 就没有使用 unlink,这就是为什么漏洞会经常出现在它们这里的原因。

依次遍历处理 unsorted bin 时也没有使用 unlink 的。

从比请求的 chunk 所在的 bin 大的 bin 中取 chunk。

Free

后向合并,合并物理相邻低地址空闲 chunk。

前向合并,合并物理相邻高地址空闲 chunk(除了 top chunk)。

malloc_consolidate

后向合并,合并物理相邻低地址空闲 chunk。

前向合并,合并物理相邻高地址空闲 chunk(除了 top chunk)。

realloc

前向扩展,合并物理相邻高地址空闲 chunk(除了top chunk)。


关于unlink的漏洞利用效果最终是指向前方三个内存单元处,我觉得这里需要注意的是,也是让我混乱过的是,到底指向谁的前方三个内存单元处?这个需要好好思考一下,有一些绕。
我们来观察一下这个语句(非正常情况的前提下),BK->fd = FD ,即将FD指向的内容存储到BK->fd地址当中去(表达可能并不是十分准确)。

2014 HITCON stkof


首先明确一下本文的参考unlink小结 && 2014_hitcon_stkof,前辈解释的很详细清楚。

-virtual-machine:~/Desktop/CTF/summer/unlink/2014_hitcon_stkof$ checksec stkof
[*] '/home/wby/Desktop/CTF/summer/unlink/2014_hitcon_stkof/stkof'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)

-virtual-machine:~/Desktop/CTF/summer/unlink/2014_hitcon_stkof$ checksec stkof
[*] '/home/wby/Desktop/CTF/summer/unlink/2014_hitcon_stkof/stkof'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)

基本功能:
1.申请内存
2.释放内存
3.向内存中写入数据(存在堆溢出

其他信息:
通过分析申请内存的函数可知,申请到的内存块都被管理在一个全局变量当中。分析如下图可得上面结果:


还有一个有意思的情况是,这道题目的源代码开始部分没有setbuf()/setvbuf()函数,又涨了一个新姿势。以前看到的题目都有这个函数也没有思考过这个函数的作用,前辈的文章指出,再参考一些资料。大多数题目的setbuf()/setvbuf()函数的作用是用来关闭I/O缓冲区,本题没有关闭缓冲区,函数运行开始阶段在fgets()函数以及printf()函数运行的时候,会malloc()两块内存区域。   和题目本身没有太大的影响,介绍一下这个有意思的现象。

基本情况介绍完毕,下面我们开始介绍如何利用:

首先讲一下利用思路,为了获得shell权限,我们可以运行system("/bin/sh"),也可以one_gadget,怎么获得运行system函数呢?本文有free/malloc函数的运用,既可以将__malloc_hook()/__free/hook()指向system,还可以赋写GOT表,将system覆盖到free/malloc的GOT表中。怎么完成写入操作呢?我们可以利用unlink来进行写入操作。
将__free_hook指向system()的利用方式在Asis 2016 b00ks(off by one)已经呈现过一次,现在我们采用赋写GOT的方式。上面是逆向思维,简而言之就是思考过程,下面我们按照正常的思考方式将利用流程解释一下:
1.利用unlink修改修改GOT表。
2.泄露libc基址。
3.将free_got改成system_addr.
4.free一个内存块,其中的内容是"/bin/sh"。

首先malloc四块内存,每块都有相应的用处。
new(0x20)
new(0x30)
new(0x80) #最后free的chunk必须不是fastbin
new(0x20)
查看一下现在的内存信息:
pwndbg> heap
0x18df000 PREV_INUSE {            这一个是fgets申请的输入缓冲
  prev_size = 0x0, 
  size = 0x1011, 
  fd = 0xa0a32330a31, 
  bk = 0x0, 
  fd_nextsize = 0x0, 
  bk_nextsize = 0x0
}
0x18e0010 FASTBIN {    new 1            
  prev_size = 0x0, 
  size = 0x31, 
  fd = 0x0, 
  bk = 0x0, 
  fd_nextsize = 0x0, 
  bk_nextsize = 0x0
}
0x18e0040 PREV_INUSE {  printf申请的输出缓冲
  prev_size = 0x0, 
  size = 0x411, 
  fd = 0xa4b4f, 
  bk = 0x0, 
  fd_nextsize = 0x0, 
  bk_nextsize = 0x0
}
0x18e0450 FASTBIN {            new 2
  prev_size = 0x0, 
  size = 0x41, 
  fd = 0x0, 
  bk = 0x0, 
  fd_nextsize = 0x0, 
  bk_nextsize = 0x0
}
0x18e0490 PREV_INUSE {         new 3  必须不在fastbin范围中,不然free操作时不会向前合并空闲内存
  prev_size = 0x0, 
  size = 0x91, 
  fd = 0x0, 
  bk = 0x0, 
  fd_nextsize = 0x0, 
  bk_nextsize = 0x0
}
0x18e0520 FASTBIN {                new  4 最后用来防止"/bin/sh\00"字符串
  prev_size = 0x0, 
  size = 0x31, 
  fd = 0x0, 
  bk = 0x0, 
  fd_nextsize = 0x0, 
  bk_nextsize = 0x0
}
0x18e0550 PREV_INUSE {
  prev_size = 0x0, 
  size = 0x20ab1, 
  fd = 0x0, 
  bk = 0x0, 
  fd_nextsize = 0x0, 
  bk_nextsize = 0x0
}

查看一下存储申请的全局变量,那我们给他一个名字global:
pwndbg> x/6xg 0x602140
0x602140:	0x0000000000000000	0x00000000018e0020
0x602150:	0x00000000018e0460	0x00000000018e04a0
0x602160:	0x00000000018e0530	0x0000000000000000

new(0x20)
new(0x30)
new(0x80) #最后free的chunk必须不是fastbin

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

最后于 2019-11-3 08:55 被Seclusion编辑 ,原因:
上传的附件:
收藏
免费 1
支持
分享
最新回复 (9)
雪    币: 18
活跃值: (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
2018-9-26 15:09
0
雪    币: 18
活跃值: (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
星星眼膜拜✨
2018-9-26 15:10
0
雪    币: 1689
活跃值: (178)
能力值: ( LV7,RANK:103 )
在线值:
发帖
回帖
粉丝
4
orz,大佬就这么写writeup
2018-10-10 20:18
0
雪    币: 1
活跃值: (47)
能力值: ( LV3,RANK:27 )
在线值:
发帖
回帖
粉丝
5

最后于 2018-12-22 11:01 被siriuswhiter编辑 ,原因:
2018-12-21 19:49
0
雪    币: 3136
活跃值: (97)
能力值: ( LV9,RANK:165 )
在线值:
发帖
回帖
粉丝
6
大佬能解释下note3题目中,【payload4 = p64(puts_plt)[:-1]  #点睛     解决了只能包含“\n”只能发送八个字节的问题】的原因么?为啥只能发送8字节
2019-1-24 21:53
0
雪    币: 61
活跃值: (2390)
能力值: ( LV9,RANK:260 )
在线值:
发帖
回帖
粉丝
7
demoLin 大佬能解释下note3题目中,【payload4 = p64(puts_plt)[:-1] #点睛 解决了只能包含“\n”只能发送八个字节的问题】的原因么?为啥只能发送8字节
用gdb调试跟踪到这一步,查看一下执行前后的内存的变化,分别用payload4=p64(puts_plt)[:-1]    payload4 = p64(puts_plt)这两条命令各试一遍。看看能解决疑惑么,我也记不太清了,如果不能的话我再去看看。
2019-1-30 09:03
0
雪    币: 223
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
8
博主 文件解压密码是啥?
2020-3-10 14:49
0
雪    币: 61
活跃值: (2390)
能力值: ( LV9,RANK:260 )
在线值:
发帖
回帖
粉丝
9
wildbloom 博主 文件解压密码是啥?
可能是看雪统一的压缩密码,我之前没加过密?
2020-3-11 10:08
0
雪    币: 425
活跃值: (525)
能力值: ( LV4,RANK:48 )
在线值:
发帖
回帖
粉丝
yyp
10
压缩密码是多少?
2020-7-8 15:41
0
游客
登录 | 注册 方可回帖
返回
//