Exemplo n.º 1
0
def application_data(plugin):
    while True:
        data = memoryview((yield from iofree.read(5)))
        assert data[
            0] == 0x17, f"{data[0]} != application_data(23) {data.tobytes()}"
        assert (data[1:3] == plugin.tls_version
                ), f"{data[1:3].tobytes()} != version({plugin.tls_version})"
        size = int.from_bytes(data[3:], "big")
        assert size == size & 0x3FFF, f"{size} is over 2^14"
        data = yield from iofree.read(size)
        yield from iofree.write(data)
Exemplo n.º 2
0
def tls1_2_request(plugin):
    tls_version = plugin.tls_version
    tls_plaintext_head = memoryview((yield from iofree.read(5)))
    assert (tls_plaintext_head[:3] == b"\x16\x03\x01"
            ), "invalid tls head: handshake(22) protocol_version(3.1)"
    length = int.from_bytes(tls_plaintext_head[-2:], "big")
    assert length == length & 0x3FFF, f"{length} is over 2^14"
    fragment = memoryview((yield from iofree.read(length)))
    assert fragment[0] == 1, "expect client_hello(1), but got {fragment[0]}"
    handshake_length = int.from_bytes(fragment[1:4], "big")
    client_hello = fragment[4:handshake_length + 4]
    assert client_hello[:2] == tls_version, "expect: client_version(3.3)"
    verify_id = client_hello[2:34]
    # TODO: replay attact detect
    gmt_unix_time = int.from_bytes(verify_id[:4], "big")
    time_diff = (int(time()) & 0xFFFFFFFF) - gmt_unix_time
    assert abs(
        time_diff) < plugin.time_tolerance, f"expired request: {time_diff}"
    session_length = client_hello[34]
    assert session_length >= 32, "session length should be >= 32"
    session_id = client_hello[35:35 + session_length].tobytes()
    sha1 = hmac.new(plugin.server.cipher.master_key + session_id,
                    verify_id[:22], hashlib.sha1).digest()[:10]
    assert verify_id[22:] == sha1, "hmac verify failed"
    tail = client_hello[35 + session_length:]
    cipher_suites = tail[:2].tobytes()
    compression_methods = tail[2:3]
    (cipher_suites, compression_methods)
    random_bytes = pack_auth_data(plugin.server.cipher.master_key, session_id)
    server_hello = (tls_version + random_bytes +
                    session_length.to_bytes(1, "big") + session_id +
                    binascii.unhexlify(b"c02f000005ff01000100"))
    server_hello = b"\x02\x00" + pack_uint16(server_hello)
    server_hello = b"\x16" + tls_version + pack_uint16(server_hello)
    if random.randint(0, 8) < 1:
        ticket = os.urandom((struct.unpack(">H", os.urandom(2))[0] % 164) * 2 +
                            64)
        ticket = struct.pack(
            ">H",
            len(ticket) + 4) + b"\x04\x00" + pack_uint16(ticket)
        server_hello += b"\x16" + tls_version + ticket
    change_cipher_spec = b"\x14" + tls_version + b"\x00\x01\x01"
    finish_len = random.choice([32, 40])
    change_cipher_spec += (b"\x16" + tls_version +
                           struct.pack(">H", finish_len) +
                           os.urandom(finish_len - 10))
    change_cipher_spec += hmac.new(
        plugin.server.cipher.master_key + session_id, change_cipher_spec,
        hashlib.sha1).digest()[:10]
    yield from iofree.write(server_hello + change_cipher_spec)
    yield from ChangeCipherReader(plugin, plugin.server.cipher.master_key,
                                  session_id)
Exemplo n.º 3
0
def socks5_request(auth=False):
    ver, nmethods = yield from iofree.read_struct("!BB")
    assert ver == 5, f"bad socks version: {ver}"
    assert nmethods != 0, f"nmethods can't be 0"
    methods = yield from iofree.read(nmethods)
    if auth and b"\x02" not in methods:
        yield from iofree.write(b"\x05\x02")
        raise Exception("server needs authentication")
    elif b"\x00" not in methods:
        yield from iofree.write(b"\x05\x00")
        raise Exception("method not support")
    if auth:
        yield from iofree.write(b"\x05\x02")
        auth_ver, username_length = yield from iofree.read_struct("!BB")
        assert auth_ver == 1, f"invalid auth version {auth_ver}"
        username = yield from iofree.read(username_length)
        password_length = (yield from iofree.read(1))[0]
        password = yield from iofree.read(password_length)
        if (username, password) != auth:
            yield from iofree.write(b"\x01\x01")
            raise Exception("authenticate failed")
        else:
            yield from iofree.write(b"\x01\x00")
    else:
        yield from iofree.write(b"\x05\x00")
    ver, cmd, rsv = yield from iofree.read_struct("!BBB")
    if cmd == 1:  # connect
        pass
    elif cmd == 2:  # bind
        raise Exception("doesn't support bind yet")
    elif cmd == 3:  # associate
        raise Exception("doesn't support associate yes")
    else:
        raise Exception(f"unknown cmd: {cmd}")
    target_addr = yield from read_addr()
    return target_addr, cmd
Exemplo n.º 4
0
    def tls_response(self):
        while True:
            head = yield from iofree.read(5)
            assert head[
                1:3] == b"\x03\x03", f"bad legacy_record_version {head[1:3]}"
            length = int.from_bytes(head[3:], "big")
            content = memoryview((yield from iofree.read(length)))
            if head[0] == ContentType.alert:
                level = AlertLevel.from_value(content[0])
                description = AlertDescription.from_value(content[1])
                raise Alert(level, description)
            elif head[0] == ContentType.handshake:
                self.peer_handshake = self.unpack_handshake(content)
                assert (self.peer_handshake.handshake_type ==
                        HandshakeType.server_hello), "expect server hello"
                peer_pk = self.peer_handshake.extensions[
                    ExtensionType.key_share].key_exchange
                shared_key = crypto_scalarmult(bytes(self.private_key),
                                               peer_pk)
                TLSCipher = self.peer_handshake.cipher_suite
                key_scheduler = TLSCipher.tls_hash.scheduler(shared_key)
                secret = key_scheduler.server_handshake_traffic_secret(
                    self.get_context())
                # server handshake cipher
                self.peer_cipher = TLSCipher(secret)
                client_handshake_traffic_secret = key_scheduler.client_handshake_traffic_secret(
                    self.get_context())
            elif head[0] == ContentType.application_data:
                plaintext = self.peer_cipher.decrypt(content,
                                                     head).rstrip(b"\x00")
                content_type = ContentType.from_value(plaintext[-1])
                if content_type == ContentType.handshake:
                    self.unpack_handshake(plaintext[:-1])
                    if self.server_finished:
                        # client handshake cipher
                        self.cipher = TLSCipher(
                            client_handshake_traffic_secret)
                        context = b"".join(self.handshake_context)
                        client_finished = self.cipher.verify_data(context)
                        inner_plaintext = HandshakeType.finished.tls_inner_plaintext(
                            client_finished)
                        record = self.cipher.tls_ciphertext(inner_plaintext)
                        change_cipher_spec = ContentType.change_cipher_spec.tls_plaintext(
                            b"\x01")
                        yield from iofree.write(change_cipher_spec + record)
                        # server application cipher
                        server_secret = key_scheduler.server_application_traffic_secret_0(
                            self.get_context())
                        self.peer_cipher = TLSCipher(server_secret)
                        self.server_finished = False

                        # client application cipher
                        client_secret = key_scheduler.client_application_traffic_secret_0(
                            self.get_context())
                        self.cipher = TLSCipher(client_secret)

                elif content_type == ContentType.application_data:
                    yield from iofree.write(plaintext[:-1])
                elif content_type == ContentType.alert:
                    level = AlertLevel.from_value(plaintext[0])
                    description = AlertDescription.from_value(plaintext[1])
                    raise Alert(level, description)
                elif content_type == ContentType.invalid:
                    raise Exception("invalid content type")
                else:
                    raise Exception(f"unexpected content type {content_type}")
            elif head[0] == ContentType.change_cipher_spec:
                assert content == b"\x01", "change_cipher should be 0x01"
            else:
                raise Exception(f"Unknown content type: {head[0]}")
Exemplo n.º 5
0
def ss_reader(cipher):
    iv = yield from iofree.read(cipher.IV_SIZE)
    decrypt = cipher.make_decrypter(iv)
    while True:
        data = yield from iofree.read_more()
        yield from iofree.write(decrypt(data))
Exemplo n.º 6
0
 def reader(self):
     salt = yield from iofree.read(self.cipher.SALT_SIZE)
     self.decrypt = self.cipher.make_decrypter(salt)
     while True:
         payload = yield from self.read_some()
         yield from iofree.write(payload)