Last active
November 4, 2024 14:38
-
-
Save barneygale/f5dfcb1dd87a0533aeb13bda798223f2 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from os import urandom | |
from socket import create_connection | |
from cryptography.hazmat.primitives.asymmetric import padding | |
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes | |
from cryptography.hazmat.primitives.serialization import load_der_public_key | |
def read(sock, length): | |
result = b'' | |
while len(result) < length: | |
result += sock.recv(length - len(result)) | |
return result | |
def read_int(sock, length): | |
return int.from_bytes(read(sock, length), 'big') | |
def write(sock, data): | |
sock.sendall(data) | |
def pack_credential(data): | |
data = data.encode('utf-8') + b'\x00' | |
if len(data) < 64: | |
data += urandom(64 - len(data)) | |
else: | |
data = data[:64] | |
return data | |
def connect(host, port, username, password, public_key=None): | |
sock = create_connection((host, port)) | |
# Standard VNC version number exchange | |
write(sock, b'RFB 003.889\n') | |
read(sock, 12) | |
# Standard VNC auth types exchange | |
read(sock, read_int(sock, 1)) | |
write(sock, b'\x21') | |
# ---- begin Apple VNC auth ---- | |
if public_key is None: | |
write(sock, b'\x00\x00\x00\x0a' # packet length (10 bytes) | |
b'\x01\x00' # packet version | |
b'RSA1' # host key algorithm | |
b'\x00\x00' # has credentials? (no) | |
b'\x00\x00') # has AES key? (no) | |
read(sock, 4) # packet length | |
read(sock, 2) # packet version | |
public_key_length = read_int(sock, 4) | |
public_key = load_der_public_key(read(sock, public_key_length)) | |
read(sock, 1) # unknown (zero) | |
aes_key = urandom(16) | |
encryptor = Cipher(algorithms.AES(aes_key), modes.ECB()).encryptor() | |
write(sock, b'\x00\x00\x01\x8a' # packet length (394 bytes) | |
b'\x01\x00' # packet version | |
b'RSA1' # host key algorithm | |
b'\x00\x01' + # has credentials? (yes) | |
encryptor.update( | |
pack_credential(username) + | |
pack_credential(password)) + | |
b'\x00\x01' + # has AES key? (yes) | |
public_key.encrypt(aes_key, padding=padding.PKCS1v15())) | |
read(sock, 4) # unknown (all zeroes) | |
# ---- end Apple VNC auth ---- | |
# Standard VNC auth response | |
if read_int(sock, 4) != 0: | |
raise PermissionError("Authentication failed.") | |
# Standard VNC client init etc | |
write(sock, b'\x01') | |
connect('localhost', 5900, 'username', 'password') |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Things I'm fuzzy on:
RSA1
is null-terminated