吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 4651|回复: 12
收起左侧

[调试逆向] Largebin_Attack知识点理解(附赠堆分配释放回忆!)

[复制链接]
peiwithhao 发表于 2022-9-30 14:25
本帖最后由 peiwithhao 于 2022-9-30 14:42 编辑

Largebin Attack
今天来整理以下我所刚学完的largebin attack的理解,以及堆分配过程的基础认识。首先我们在学习largebin attack 之前,先来回顾以下堆分配以及释放的过程。


bins 结构
我们先来看看main_arena中,各个bin的分布情况
112452wd3nqt1ngktqrkqn.png
不得不说这图画的真好,上面这布局是基于64位的,32位的布局也类似,我们就拿他来类比着看,
  • 首先可以看到fast bin是共有7个链条,每条链上的堆大小相等,分别对应0x20、0x30、、直到0x80。其中需要注意的是fastbin的inuse位始终为1,所以他不会被合并,FILO
  • 然后就是唯一的top chunk,这个topchunk就是再我们找不到对应可以分配的chunk时将会从topchunk切割,
  • 之后我们可以看到有last_remainder 和unsortedbin fd 以及 unsortedbin bk ,这三项可以拿在一起讲。在用户malloc请求分配内存之后,ptmalloc找到的chunk与目标申请的大小不一致时,会进行切割,剩余部分称为last remainder chunk,由 last_remainder 管理,存储在unsortedbin中。而这个unsortedbin在所有bin中就一条链,而且这个链条是可以链接不同大小块的,这里由于unsorted bin是双链条,所有main_arena上面保存着fd与bk指针,在unsorted bin只有一个块的时候,他这个fd与bk均指向那个唯一的unsoted bin中的额chunk,FIFO
  • 再然后就是small bins,其所属范围为0x20 ~ 0x3f0,且在结构体中军保存了0x20 fd,0x20 bk具体原因可以参考unsortedbin,且上述方差为0x10,至于这里为什么与fastbin的大小有重合我们等会儿讲,FIFO

下标 SIZE_SZ = 4(32位)             SIZE_SZ = 8(64位)
2 0x10 0x20
3 0x18 0x30
4 0x20 0x40
5 0x28 0x50
x 0x8*x 0x10*x
63 0x1f8 0x3f0
  • smallbins之后就是largebins,也就是今天的知识点,首先他与其他bins相比都十分特殊,所以我们接下来再来细讲,这里我们先概述以下,largebin的范围从0x400~0x80000,其每个链条上的chunk大小可以不尽相同
    数量 公差
    1 0x20 64B
    2 0x10 512B
    3 0x08 4096B
    4 0x04 32768B
    5 0x02 262144B
    6 0x01 不限制
    好了在结构体上的知识就说到这里,现在进入正题,开始回忆堆分配以及释放



堆分配过程
这里由于我们的重点在于bins,所以对于一些具体函数的实现就不过多赘述,这里只讨论bins哈
(注意这里我们讨论的是不包含tcache的情况)
  • 首先若我们申请的堆大小位于fastbin的范围内,那自然我们只需从中取得即可,若不属于其范围或fastbin为空,紧接着向下执行;
  • 若发现其处于smallbin中,与上述一样,若不属于其范围或smallbins为空,接着向下执行;
  • 当 fast bin、small bin 中的 chunk 都不能满足用户请求 chunk 大小时,就会考虑是不是 large bin。但是,其实在 large bin 中并没有直接去扫描对应 bin 中的 chunk,而是先利用 malloc_consolIDAte(参见 malloc_state 相关函数) 函数处理 fast bin 中的 chunk,将有可能能够合并的 chunk 先进行合并后放到 unsorted bin 中,不能够合并的就直接放到 unsorted bin 中,然后再在下面的大循环中进行相应的处理。为什么不直接从相应的 bin 中取出 large chunk 呢?这是 ptmalloc 的机制,它会在分配 large chunk 之前对堆中碎片 chunk 进行合并,以便减少堆中的碎片
  • 接下来执行大循环遍历unsortedbin,若程序运行到此,则说明fast以及small 中没有相匹配的堆块,此时我们进行如下操作:首先对unsortedbin进行遍历,从链尾遍历到链表,若其大小符合所需堆块,则进行分配,否则放入相应的bin中,此时注意若unsortedbin未分配成功,我们会从fastbin中取出所有堆块尝试合并,未合并成功则会放入smallbin,遍历完后尝试用largebin进行分配;
  • 如果请求的 chunk 在 large chunk 范围内,就在对应的 bin 中从小到大进行扫描,找到第一个合适的,若仍旧未找到合适大小的bin,则进行下一步;
  • 如果走到了这里,那说明对于用户所需的 chunk,不能直接从其对应的合适的 bin 中获取 chunk,所以我们需要来查找比当前 bin 更大的 fast bin , small bin 或者 large bin然后进行切割,其中的剩余部分将插入到usortedbin当中,如果这招也不行的话,那只能进行最后一步;
  • 从top chunk进行切割,注意这里切割的剩余部分不会放入unsortedbin,如果这一步也不行、、、再再再进行最后一步,那就是使用sysmalloc进行系统分配(哈哈哈这里就不多说了,感兴趣的可以去ctf-wiki上面看看,这里我们主要是了解堆块与bins间的分配过程)



堆释放过程
相比于分配,释放过程就简单多了,也就是说如果你释放的堆块处于fastbin范围,则将其正常插入,除此之外会将其放入unsorted bin当中。这里要注意unlink的时机(毛遂自荐以下,这里可以看看我之前写的unlink文章哈,我觉得还行
2014_hitcon_stkof学习(以及unlink的个人理解)
https://www.52pojie.cn/thread-1681720-1-1.html
(出处: 吾爱破解论坛)

),也就是除了释放的是fastbin范围的堆块,其他的相邻堆块都会进行unlink合并,这也是防止内存中过多小碎块的存在,如果你所释放的堆块与topchunk相邻,则会并入topchunk中。


以上真的建议大家在自己的脑海里面仔细审查一遍,这个理清楚了做题才不会模模糊糊。
接下来我们来了解large bin的知识
largebin基础知识
首先咱们已经知道了largebin与其他的bin十分不同,什么?你已经知道了?(不就是一条链上的大小不一样么,还有什么特别的么),那当然也有,他比较特别的就是多了两个指针,fd_nextsize , bk_nextsize.这里我先贴出来ctfwiki上的解释
[C] 纯文本查看 复制代码
/*
  This struct declaration is misleading (but accurate and necessary).
  It declares a "view" into memory allowing access to necessary
  fields at known offsets from a given base. See explanation below.
*/
struct malloc_chunk {

  INTERNAL_SIZE_T      prev_size;  /* Size of previous chunk (if free).  */
  INTERNAL_SIZE_T      size;       /* Size in bytes, including overhead. */

  struct malloc_chunk* fd;         /* double links -- used only if free. */
  struct malloc_chunk* bk;

  /* Only used for large blocks: pointer to next larger size.  */
  struct malloc_chunk* fd_nextsize; /* double links -- used only if free. */
  struct malloc_chunk* bk_nextsize;
};

而以上的注释部分也说得很清楚,这个fd_nextsize与bk.nextsize只有在largebin中才会享有,他的具体含义我这里来语言描述以下:
fd_nextsize:指向前一个与当前chunk_size不小同的块(注意是同意链条上)
bk_nextsize:指向后一个与当前chunk_size大小不同的块(同上)
其中还有几个注意点那就是在相同大小的chunk中,只有首chunk的fd_nextsize和bk_nextsize才有具体值,之后的全按0处理,还有就是largebin的链条分配是按从大到小排序的,如果size相同则按free时间前后来排序,这里有个漏洞点那就是在放入largebin过程中若释放的堆块比当前链条尾的短,则程序会直接放入链尾而不进行过多的检查(这里有点模糊,以后我来修改)。
说到这里相信也有很多刚接触的师傅不太明白,因为这文字实在是过于抽象,所以我这里来画个图给大家看看
屏幕截图 2022-09-30 134135.png
这张图大致就可以讲出largebin中的链接关系了,请大伙务必仔细看,千万别嫌麻烦,这里弄懂了其他的就自然通了,这里也可以看出来fd,bk指针与普通堆块是一样链接的,所以为了让大家更方便观看,我这里就再去除掉fd、bk指针
屏幕截图 2022-09-30 134409.png
从这张图我来简单带大家看看,这里不同大小堆块中的首块我都运用了不同颜色来进行标识,可以看到只有颜色标记的堆块采用到了fd_nextsize与bk_nextsize,并且这两个指针也分别指向了下一个带颜色的堆块,所以说其实我们在一个largebin链条中除了fd、bk链条之外还有额外的链条,这样也是为了方便我们寻找堆块,大家可以稍微思考思考,如果没有fd_nextsize与bk_nextsize的话,由于这条链上块的大小并不都是相同,难道我们要依次一个一个遍历搜寻堆块嘛,那就太笨了一点,所以说添加这两个链接可以加快我们搜寻不同堆块的速度,并且始终记住我们这里是双循环链表,相信这样大家看这个图就会理解的更加顺畅。


how2heap中的large_bin_attack练习
由于没找到合适的题目,但是看有的师说说2e4zu这题好像挺好,我先mark以下以后写,这里我使用的本机2.34的环境,因为我考虑着这个实验用不到tcache就没管。先给出主函数给大家看看
[C] 纯文本查看 复制代码
int main(){
  /*Disable IO buffering to prevent stream from interfering with heap*/
  setvbuf(stdin,NULL,_IONBF,0);
  setvbuf(stdout,NULL,_IONBF,0);
  setvbuf(stderr,NULL,_IONBF,0);

  size_t target = 0;
  printf("Here is the target we want to overwrite (%p) : %lu\n\n",&target,target);
  size_t *p1 = malloc(0x428);
  printf("First, we allocate a large chunk [p1] (%p)\n",p1-2);
  size_t *g1 = malloc(0x18);
  printf("And another chunk to prevent consolidate\n");

  printf("\n");

  size_t *p2 = malloc(0x418);

  size_t *g2 = malloc(0x18);

  free(p1);

  size_t *g3 = malloc(0x438);

  free(p2);

  p1[3] = (size_t)((&target)-4);

  size_t *g4 = malloc(0x438);

  return 0;
}

程序不复杂,这里删除了多余的注释部分,这个程序是先分配了一个chunk_p1(0x430),然后申请一个0x20的块来进行防合并,之后以同样的方法分配了一个chunk_p2(0x420),这里我们就先不说完过程,免得大家看着一股脑赛这么多东西过来不好理解。程序执行到这里我们首先来看看堆栈的内存布局
屏幕截图 2022-09-30 140505.png
然后我们继续执行程序,由于我们已经掌握堆的分配机制(确信)(如果忘记的话建议去上面的部分再多思考思考)所以我们此时首先free掉p1,此时由于其不在fastbin范围内,所以放入unsorted bin,从调试中也可以证实
屏幕截图 2022-09-30 140950.png
然后我们再分配一个0x440,为什么要如此分配呢,那是因为我们想要进行依次大循环遍历,借此将0x430也就是p1这块放入largebin中
屏幕截图 2022-09-30 141135.png
这里看到我们成功放入了,然后就是free掉p2,此时放入到unsorted bin中,之后p1的bk_nextsize位修改为target-0x20,这样就使得程序以为我们的头链表还不是p1,而是我们的target了。
屏幕截图 2022-09-30 141542.png
此时我们再重操旧业,将chunk_p2也放入到largebin当中且只检查了链尾的p1并发现比他小,所以就将p2直接变为链尾,所以此时我们的p2的fd_nextsize指针就会指向我们的target(与unsorted bin很像有没有)
屏幕截图 2022-09-30 142141.png
实验结束!!!!!!
怎么感觉十分的水,不过前期的分配以及largebin讲解感觉还行,今天的实验变成配菜了感觉,之后找到了合适的题目会第一时间分享给大家。
112452wd3nqt1ngktqrkqn.png

免费评分

参与人数 12威望 +2 吾爱币 +110 热心值 +12 收起 理由
zjun777 + 1 + 1 用心讨论,共获提升!
李佑辰 + 1 用心讨论,共获提升!
willJ + 2 + 100 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
yyyao2008 + 1 + 1 热心回复!
OYyunshen + 1 + 1 我很赞同!
Xiangzhisuoxin + 1 + 1 我很赞同!
zlnxlzht + 1 + 1 热心回复!
为之奈何? + 1 + 1 我很赞同!
lingyun011 + 1 + 1 热心回复!
HighLightFanYa + 1 + 1 用心讨论,共获提升!
杨辣子 + 1 + 1 用心讨论,共获提升!
loo1221ool + 1 + 1 我很赞同!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

lwedwin 发表于 2022-9-30 19:43
楼主厉害了    感谢分享
HighLightFanYa 发表于 2022-9-30 20:18
ysysc 发表于 2022-9-30 21:04
kanxue2018 发表于 2022-10-1 08:11
好好学习,不断进步,感谢!
viponlyyan 发表于 2022-10-1 10:37
在线学习。。。
xy0225 发表于 2022-10-2 00:34
学习了,谢谢分享
benzuncaonima 发表于 2022-10-2 00:48
学习一下
simmtech 发表于 2022-10-6 08:58
知识性 好强,学习 了,支持             。
foxesp 发表于 2022-10-13 19:10
支持作者大大
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则 警告:本版块禁止灌水或回复与主题无关内容,违者重罚!

快速回复 收藏帖子 返回列表 搜索

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-3-29 22:48

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表