uzbek-plus/b13/vnc-vencrypt.py

60 lines
3.3 KiB
Python

#!/usr/bin/env python3
# B13W test client: RFB 3.8 + VeNCrypt X509Plain/TLSPlain (wayvnc enable_auth), raw 32bpp screenshot -> PPM, optional key/pointer input.
# vnc-vencrypt.py HOST PORT USER PASSFILE OUT.ppm [TEXT_TO_TYPE] [CERT_SHA256]
import socket, ssl, struct, sys, time, hashlib
h, p, user, pwf, out = sys.argv[1], int(sys.argv[2]), sys.argv[3], sys.argv[4], sys.argv[5]
text = sys.argv[6] if len(sys.argv) > 6 else ''; fp = sys.argv[7].replace(':', '').lower() if len(sys.argv) > 7 else ''
pw = open(pwf).read().strip()
s = socket.create_connection((h, p), 10)
def rx(n, c=None):
c = c or s; b = b''
while len(b) < n:
d = c.recv(n - len(b))
if not d: raise SystemExit('EOF')
b += d
return b
ver = rx(12); s.sendall(b'RFB 003.008\n')
n = rx(1)[0]
if n == 0: raise SystemExit('server refused: ' + rx(struct.unpack('>I', rx(4))[0]).decode())
types = list(rx(n)); print('security types:', types, 'None offered:', 1 in types)
assert 19 in types, 'no VeNCrypt'
s.sendall(b'\x13'); sv = rx(2); s.sendall(b'\x00\x02'); assert rx(1) == b'\x00'
m = rx(1)[0]; subs = [struct.unpack('>I', rx(4))[0] for _ in range(m)]; print('vencrypt subtypes:', subs)
st = 262 if 262 in subs else 259; s.sendall(struct.pack('>I', st)); assert rx(1) == b'\x01'
ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT); ctx.check_hostname = False; ctx.verify_mode = ssl.CERT_NONE
t = ctx.wrap_socket(s); cert = t.getpeercert(binary_form=True)
cfp = hashlib.sha256(cert).hexdigest() if cert else '-'; print('tls', t.version(), t.cipher()[0], 'cert sha256', cfp[:16], 'pinned-match' if fp and cfp == fp else '')
if fp: assert cfp == fp, 'certificate fingerprint mismatch'
s = t
s.sendall(struct.pack('>II', len(user), len(pw)) + user.encode() + pw.encode())
r = struct.unpack('>I', rx(4))[0]
if r != 0:
try: reason = rx(struct.unpack('>I', rx(4))[0]).decode()
except SystemExit: reason = ''
print('AUTH FAIL', reason); sys.exit(3)
print('AUTH OK subtype', st)
s.sendall(b'\x01'); w, hh = struct.unpack('>HH', rx(4)); rx(16); name = rx(struct.unpack('>I', rx(4))[0]).decode(); print('desktop', name, w, 'x', hh)
s.sendall(struct.pack('>BxxxBBBBHHHBBBxxx', 0, 32, 24, 0, 1, 255, 255, 255, 16, 8, 0)); s.sendall(struct.pack('>BxHi', 2, 1, 0))
def grab(path):
s.sendall(struct.pack('>BBHHHH', 3, 0, 0, 0, w, hh)); img = bytearray(w * hh * 3); got = 0
while got < w * hh:
mt = rx(1)[0]
if mt == 2: continue
if mt == 1: rx(5); continue
if mt != 0: raise SystemExit('msg %d' % mt)
rx(1); nr = struct.unpack('>H', rx(2))[0]
for _ in range(nr):
x, y, rw, rh, enc = struct.unpack('>HHHHi', rx(12))
if enc != 0: continue
px = rx(rw * rh * 4)
for j in range(rh):
for i in range(rw):
v = px[(j*rw+i)*4:(j*rw+i)*4+4]; o = ((y+j)*w + x+i)*3; img[o:o+3] = bytes((v[2], v[1], v[0]))
got += rw * rh
open(path, 'wb').write(b'P6 %d %d 255\n' % (w, hh) + img); print('saved', path)
grab(out)
if text:
s.sendall(struct.pack('>BBHH', 5, 0, 64, 64)); time.sleep(0.2) # pointer to the centre (virtual pointer)
for ch in text:
k = ord(ch); s.sendall(struct.pack('>BBxxI', 4, 1, k)); s.sendall(struct.pack('>BBxxI', 4, 0, k)); time.sleep(0.05)
time.sleep(1.5); grab(out.replace('.ppm', '-typed.ppm'))