Files
pyvncs/server2.py
Matias Fernandez f4c77886bd Initial commit
2018-03-27 10:45:54 -03:00

855 lines
32 KiB
Python
Executable File

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import socket, select, os, sys, random, zlib
from threading import Thread
from time import sleep
from struct import *
from pyDes import *
from argparse import ArgumentParser
from pymouse import PyMouse
from pykeyboard import PyKeyboard
import numpy as np
from PIL import Image, ImageChops, ImageDraw, ImagePalette
if sys.platform == "linux" or sys.platform == "linux2":
from Xlib import display, X
# take screen images, that's not the best way, so here
# we use directly use xlib to take the screenshot.
class ImageGrab():
def grab():
dsp = display.Display()
root = dsp.screen().root
geom = root.get_geometry()
w = geom.width
h = geom.height
raw = root.get_image(0, 0, w ,h, X.ZPixmap, 0xffffffff)
image = Image.frombytes("RGB", (w, h), raw.data, "raw", "BGRX")
return image
elif sys.platform == "darwin":
import Quartz.CoreGraphics as CG
class ImageGrab():
def grab():
screenshot = CG.CGWindowListCreateImage(CG.CGRectInfinite, CG.kCGWindowListOptionOnScreenOnly, CG.kCGNullWindowID, CG.kCGWindowImageDefault)
width = CG.CGImageGetWidth(screenshot)
height = CG.CGImageGetHeight(screenshot)
bytesperrow = CG.CGImageGetBytesPerRow(screenshot)
pixeldata = CG.CGDataProviderCopyData(CG.CGImageGetDataProvider(screenshot))
i = Image.frombytes("RGBA", (width, height), pixeldata)
(b, g, r, x) = i.split()
i = Image.merge("RGBX", (r, g, b, x))
return i
else:
from PIL import ImageGrab
def selfRestart():
try:
p = psutil.Process(os.getpid())
for handler in p.get_open_files() + p.connections():
os.close(handler.fd)
except Exception as e:
print(e)
python = sys.executable
os.execl(python, python, *sys.argv)
def hexdump(data):
str = ""
for d in data:
str += hex(d)
str += "(%s) " % d
return str
def quantizetopalette(silf, palette, dither=False):
"""Convert an RGB or L mode image to use a given P image's palette."""
silf.load()
# use palette from reference image
palette.load()
if palette.mode != "P":
raise ValueError("bad mode for palette image")
if silf.mode != "RGB" and silf.mode != "L":
raise ValueError(
"only RGB or L mode images can be quantized to a palette"
)
im = silf.im.convert("P", 1 if dither else 0, palette.im)
# the 0 above means turn OFF dithering
# Later versions of Pillow (4.x) rename _makeself to _new
try:
return silf._new(im)
except AttributeError:
return silf._makeself(im)
def deflate(data, compresslevel=9, method=zlib.DEFLATED, winsize=-zlib.MAX_WBITS, memlevel=zlib.DEF_MEM_LEVEL, strategy=0):
compress = zlib.compressobj(
compresslevel, # level: 0-9
method, # method: must be DEFLATED
winsize, # window size in bits:
# -15..-8: negate, suppress header
# 8..15: normal
# 16..30: subtract 16, gzip header
memlevel, # mem level: 1..8/9
strategy # strategy:
# 0 = Z_DEFAULT_STRATEGY
# 1 = Z_FILTERED
# 2 = Z_HUFFMAN_ONLY
# 3 = Z_RLE
# 4 = Z_FIXED
)
deflated = compress.compress(data)
deflated += compress.flush()
return deflated
def inflate(data, winsize=-zlib.MAX_WBITS):
decompress = zlib.decompressobj(
winsize # see above
)
inflated = decompress.decompress(data)
inflated += decompress.flush()
return inflated
def getDictByValue(d, val):
try:
return [k for k,v in d.items() if v==val][0]
except:
return False
RFB_VERSION = '003.008'
RFB_SECTYPES = [
2, # VNC auth
19 # VeNCrypt
]
class VncServer():
class ENCODINGS:
raw = 0
zlib = -6 # disabled
def __init__(self, socket, ip, port):
self.initmsg = ("RFB %s\n" % RFB_VERSION)
self.socket = socket
self.framebuffer = None
self.sectypes = RFB_SECTYPES
self.BGR233 = [0, 0, 0, 0, 0, 85, 0, 0, 170, 0, 0, 255, 36, 0, 0, 36, 0, 85, 36, 0, 170, 36, 0, 255, 73, 0, 0, 73, 0, 85, 73, 0, 170, 73, 0, 255, 109, 0, 0, 109, 0, 85, 109, 0, 170, 109, 0, 255, 146, 0, 0, 146, 0, 85, 146, 0, 170, 146, 0, 255, 182, 0, 0, 182, 0, 85, 182, 0, 170, 182, 0, 255, 219, 0, 0, 219, 0, 85, 219, 0, 170, 219, 0, 255, 255, 0, 0, 255, 0, 85, 255, 0, 170, 255, 0, 255, 0, 36, 0, 0, 36, 85, 0, 36, 170, 0, 36, 255, 36, 36, 0, 36, 36, 85, 36, 36, 170, 36, 36, 255, 73, 36, 0, 73, 36, 85, 73, 36, 170, 73, 36, 255, 109, 36, 0, 109, 36, 85, 109, 36, 170, 109, 36, 255, 146, 36, 0, 146, 36, 85, 146, 36, 170, 146, 36, 255, 182, 36, 0, 182, 36, 85, 182, 36, 170, 182, 36, 255, 219, 36, 0, 219, 36, 85, 219, 36, 170, 219, 36, 255, 255, 36, 0, 255, 36, 85, 255, 36, 170, 255, 36, 255, 0, 73, 0, 0, 73, 85, 0, 73, 170, 0, 73, 255, 36, 73, 0, 36, 73, 85, 36, 73, 170, 36, 73, 255, 73, 73, 0, 73, 73, 85, 73, 73, 170, 73, 73, 255, 109, 73, 0, 109, 73, 85, 109, 73, 170, 109, 73, 255, 146, 73, 0, 146, 73, 85, 146, 73, 170, 146, 73, 255, 182, 73, 0, 182, 73, 85, 182, 73, 170, 182, 73, 255, 219, 73, 0, 219, 73, 85, 219, 73, 170, 219, 73, 255, 255, 73, 0, 255, 73, 85, 255, 73, 170, 255, 73, 255, 0, 109, 0, 0, 109, 85, 0, 109, 170, 0, 109, 255, 36, 109, 0, 36, 109, 85, 36, 109, 170, 36, 109, 255, 73, 109, 0, 73, 109, 85, 73, 109, 170, 73, 109, 255, 109, 109, 0, 109, 109, 85, 109, 109, 170, 109, 109, 255, 146, 109, 0, 146, 109, 85, 146, 109, 170, 146, 109, 255, 182, 109, 0, 182, 109, 85, 182, 109, 170, 182, 109, 255, 219, 109, 0, 219, 109, 85, 219, 109, 170, 219, 109, 255, 255, 109, 0, 255, 109, 85, 255, 109, 170, 255, 109, 255, 0, 146, 0, 0, 146, 85, 0, 146, 170, 0, 146, 255, 36, 146, 0, 36, 146, 85, 36, 146, 170, 36, 146, 255, 73, 146, 0, 73, 146, 85, 73, 146, 170, 73, 146, 255, 109, 146, 0, 109, 146, 85, 109, 146, 170, 109, 146, 255, 146, 146, 0, 146, 146, 85, 146, 146, 170, 146, 146, 255, 182, 146, 0, 182, 146, 85, 182, 146, 170, 182, 146, 255, 219, 146, 0, 219, 146, 85, 219, 146, 170, 219, 146, 255, 255, 146, 0, 255, 146, 85, 255, 146, 170, 255, 146, 255, 0, 182, 0, 0, 182, 85, 0, 182, 170, 0, 182, 255, 36, 182, 0, 36, 182, 85, 36, 182, 170, 36, 182, 255, 73, 182, 0, 73, 182, 85, 73, 182, 170, 73, 182, 255, 109, 182, 0, 109, 182, 85, 109, 182, 170, 109, 182, 255, 146, 182, 0, 146, 182, 85, 146, 182, 170, 146, 182, 255, 182, 182, 0, 182, 182, 85, 182, 182, 170, 182, 182, 255, 219, 182, 0, 219, 182, 85, 219, 182, 170, 219, 182, 255, 255, 182, 0, 255, 182, 85, 255, 182, 170, 255, 182, 255, 0, 219, 0, 20, 219, 85, 0, 219, 170, 0, 219, 255, 36, 219, 0, 36, 219, 85, 36, 219, 170, 36, 219, 255, 73, 219, 0, 73, 219, 85, 73, 219, 170, 73, 219, 255, 109, 219, 0, 109, 219, 85, 109, 219, 170, 109, 219, 255, 146, 219, 0, 146, 219, 85, 146, 219, 170, 146, 219, 255, 182, 219, 0, 182, 219, 85, 182, 219, 170, 182, 219, 255, 219, 219, 0, 219, 219, 85, 219, 219, 170, 219, 219, 255, 255, 219, 0, 255, 219, 85, 255, 219, 170, 255, 219, 255, 0, 255, 0, 0, 255, 85, 0, 255, 170, 0, 255, 255, 36, 255, 0, 36, 255, 85, 36, 255, 170, 36, 255, 255, 73, 255, 0, 73, 255, 85, 73, 255, 170, 73, 255, 255, 109, 255, 0, 109, 255, 85, 109, 255, 170, 109, 255, 255, 146, 255, 0, 146, 255, 85, 146, 255, 170, 146, 255, 255, 182, 255, 0, 182, 255, 85, 182, 255, 170, 182, 255, 255, 219, 255, 0, 219, 255, 85, 219, 255, 170, 219, 255, 255, 255, 255, 0, 255, 255, 85, 255, 255, 170, 255, 255, 255]
def __del__(self):
print("VncServer died")
def encrypt(self, key, data):
k = des(key, ECB, "\0\0\0\0\0\0\0\0", pad=None, padmode=PAD_PKCS5)
d = k.encrypt(data)
return d
def decrypt(self, challenge, data):
k = des(challenge, ECB, "\0\0\0\0\0\0\0\0", pad=None, padmode=PAD_PKCS5)
return k.decrypt(data)
def mirrorBits(self, key):
newkey = []
for ki in range(len(key)):
bsrc = key[ki]
btgt = 0
for i in range(8):
if ord(bsrc) & (1 << i):
btgt = btgt | (1 << 7-i)
newkey.append(btgt)
return newkey
def sendmessage(self, message):
''' sends a RFB message, usually an error message '''
sock = self.socket
message = bytes(message, 'iso8859-1')
# 4 bytes lenght and string
buff = pack("I%ds" % (len(message),), len(message), message)
sock.send(message)
def getbuff(self, timeout):
sock = self.socket
sock.settimeout(timeout)
try:
data = sock.recv(1024)
except socket.timeout:
data = None
print("getbuff() timeout")
return data
def init(self):
sock = self.socket
sock.send(self.initmsg.encode())
# RFB version handshake
data = self.getbuff(30)
print("init received: '%s'" % data)
server_version = float(RFB_VERSION)
try:
client_version = float(data[4:11])
except:
print("Error parsing client version")
return False
print("client, server:", client_version, server_version)
# security types handshake
sendbuff = pack("B", len(self.sectypes)) # number of security types
sendbuff += pack('%sB' % len(self.sectypes), *self.sectypes) # send available sec types
sock.send(sendbuff)
data = self.getbuff(30)
try:
sectype = unpack("B", data)[0]
except:
sectype = None
if sectype not in self.sectypes:
print("Incompatible security type: %s" % data)
sock.send(pack("B", 1)) # failed handshake
self.sendmessage("Incompatible security type")
sock.close()
return False
print("sec type data: %s" % data)
# VNC Auth
if sectype == 2:
# el cliente encripta el challenge con la contraseña ingresada como key
pw = (VNC_PASSWORD + '\0' * 8)[:8]
challenge = os.urandom(16) # challenge
sock.send(challenge) # send challenge
# obtener desde el cliente el dato encritado
data = self.getbuff(30)
# la encriptacion de challenge, con pw como key debe dar data
k = des(self.mirrorBits(pw))
crypted = k.encrypt(challenge)
if data == crypted:
# Handshake successful
sock.send(pack("I", 0))
print("Auth OK")
else:
print("Invalid auth")
return False
#unsupported VNC auth type
else:
return False
# get ClientInit
data = self.getbuff(30)
print("Clientinit (shared flag)", repr(data))
self.ServerInit()
return True
def ServerInit(self):
# ServerInit
sock = self.socket
screen = ImageGrab.grab()
print("screen", repr(screen))
size = screen.size
print("size", repr(size))
del screen
width = size[0]
self.width = width
height = size[1]
self.height = height
bpp = 32 # FIXME: get real bpp
depth = 32 # FIXME: get real depth
self.depth = depth
self.bpp = bpp
bigendian = 0
truecolor = 1
red_maximum = 255
self.red_maximum = red_maximum
green_maximum = 255
self.green_maximum = green_maximum
blue_maximum = 255
self.blue_maximum = blue_maximum
red_shift = 16
self.red_shift = red_shift
green_shift = 8
self.green_shift = green_shift
blue_shift = 0
self.blue_shift = blue_shift
sendbuff = pack("!HH", width, height)
sendbuff += pack("!BBBB", bpp, depth, bigendian, truecolor)
sendbuff += pack("!HHHBBB", red_maximum, green_maximum, blue_maximum, red_shift, green_shift, blue_shift)
sendbuff += pack("!xxx") # padding
desktop_name = "Test VNC"
desktop_name_len = len(desktop_name)
sendbuff += pack("!I", desktop_name_len)
sendbuff += desktop_name.encode()
print("width", repr(width))
print("height", repr(height))
sock.send(sendbuff)
def protocol(self):
self.socket.settimeout(None) # set nonblocking socket
screen = ImageGrab.grab()
size = screen.size
width = size[0]
height = size[1]
del screen
self.primaryOrder = "rgb"
self.encoding = self.ENCODINGS.raw
buttonmask = 0
buttons = [0, 0, 0, 0, 0, 0, 0, 0]
left_pressed = 0
right_pressed = 0
middle_pressed = 0
kdbmap = {
"KEY_BackSpace": 0xff08,
"KEY_Tab": 0xff09,
"KEY_Return": 0xff0d,
"KEY_Escape": 0xff1b,
"KEY_Insert": 0xff63,
"KEY_Delete": 0xffff,
"KEY_Home": 0xff50,
"KEY_End": 0xff57,
"KEY_PageUp": 0xff55,
"KEY_PageDown": 0xff56,
"KEY_Left": 0xff51,
"KEY_Up": 0xff52,
"KEY_Right": 0xff53,
"KEY_Down": 0xff54,
"KEY_F1": 0xffbe,
"KEY_F2": 0xffbf,
"KEY_F3": 0xffc0,
"KEY_F4": 0xffc1,
"KEY_F5": 0xffc2,
"KEY_F6": 0xffc3,
"KEY_F7": 0xffc4,
"KEY_F8": 0xffc5,
"KEY_F9": 0xffc6,
"KEY_F10": 0xffc7,
"KEY_F11": 0xffc8,
"KEY_F12": 0xffc9,
"KEY_F13": 0xFFCA,
"KEY_F14": 0xFFCB,
"KEY_F15": 0xFFCC,
"KEY_F16": 0xFFCD,
"KEY_F17": 0xFFCE,
"KEY_F18": 0xFFCF,
"KEY_F19": 0xFFD0,
"KEY_F20": 0xFFD1,
"KEY_ShiftLeft": 0xffe1,
"KEY_ShiftRight": 0xffe2,
"KEY_ControlLeft": 0xffe3,
"KEY_ControlRight": 0xffe4,
"KEY_MetaLeft": 0xffe7,
"KEY_MetaRight": 0xffe8,
"KEY_AltLeft": 0xffe9,
"KEY_AltRight": 0xffea,
"KEY_Scroll_Lock": 0xFF14,
"KEY_Sys_Req": 0xFF15,
"KEY_Num_Lock": 0xFF7F,
"KEY_Caps_Lock": 0xFFE5,
"KEY_Pause": 0xFF13,
"KEY_Super_L": 0xFFEB,
"KEY_Super_R": 0xFFEC,
"KEY_Hyper_L": 0xFFED,
"KEY_Hyper_R": 0xFFEE,
"KEY_KP_0": 0xFFB0,
"KEY_KP_1": 0xFFB1,
"KEY_KP_2": 0xFFB2,
"KEY_KP_3": 0xFFB3,
"KEY_KP_4": 0xFFB4,
"KEY_KP_5": 0xFFB5,
"KEY_KP_6": 0xFFB6,
"KEY_KP_7": 0xFFB7,
"KEY_KP_8": 0xFFB8,
"KEY_KP_9": 0xFFB9,
"KEY_KP_Enter": 0xFF8D,
"KEY_ForwardSlash": 0x002F,
"KEY_BackSlash": 0x005C,
"KEY_SpaceBar": 0x0020
}
# key mapping per SO (windows, osx, linux)
# FIXME: OSX maping
if sys.platform == "darwin":
keyboard.control_key = keyboard.key_code_translate_table['control']
mapping = {
"KEY_ControlLeft" : [keyboard.control_key, "Control", keyboard.control_l_key],
"KEY_ControlRight" : [keyboard.control_key, "Control", keyboard.control_r_key],
"KEY_AltLeft": [keyboard.alt_l_key, "Alternate", keyboard.alt_l_key],
"KEY_AltRight": [keyboard.alt_r_key, "Alternate", keyboard.alt_r_key],
"KEY_ShiftLeft": [keyboard.shift_l_key, "shift", keyboard.shift_l_key],
"KEY_ShiftRight": [keyboard.shift_r_key, "shift", keyboard.shift_r_key],
"KEY_Up": [keyboard.up_key, "Up", keyboard.up_key],
"KEY_Down": [keyboard.down_key, "Down", keyboard.down_key],
"KEY_Left": [keyboard.left_key, "Left", keyboard.left_key],
"KEY_Right": [keyboard.right_key, "Right", keyboard.right_key],
"KEY_Delete": [keyboard.delete_key, "delete", keyboard.delete_key],
"KEY_Insert": [keyboard.insert_key, "insert", keyboard.insert_key],
"KEY_Home": [keyboard.home_key, "home", keyboard.home_key],
"KEY_End": [keyboard.end_key, "end", keyboard.end_key],
"KEY_PageUp": [keyboard.page_up_key, "PageUp", keyboard.page_up_key],
"KEY_PageDown": [keyboard.page_down_key, "PageDown", keyboard.page_down_key],
}
# function keys mapping
for i in range(1,20):
mapping.update( { ("KEY_F%s" % i): [keyboard.function_keys[i], ("F%s" % i) , keyboard.function_keys[i]] } )
while True:
#print(".", end='', flush=True)
r,_,_ = select.select([self.socket],[],[],0)
if r == []:
#no data
sleep(0.1)
continue
sock = r[0]
try:
data = sock.recv(1) # read first byte
except socket.timeout:
#print("timeout")
continue
except Exception as e:
print("exception '%s'" % e)
sock.close()
break
if not data:
# clinet disconnected
sock.close()
break
if data[0] == 0: # client SetPixelFormat
data2 = sock.recv(19, socket.MSG_WAITALL)
print("Client Message Type: Set Pixel Format (0)")
(self.bpp, self.depth, self.bigendian, self.truecolor, self.red_maximum,
self.green_maximum, self.blue_maximum,
self.red_shift, self.green_shift, self.blue_shift
) = unpack("!xxxBBBBHHHBBBxxx", data2)
print("IMG bpp, depth, endian, truecolor", self.bpp, self.depth, self.bigendian, self.truecolor)
print("SHIFTS", self.red_shift, self.green_shift, self.blue_shift)
print("MAXS", self.red_maximum, self.green_maximum, self.blue_maximum)
if self.red_shift > self.blue_shift:
self.primaryOrder = "rgb"
else:
self.primaryOrder = "bgr"
print("Using order: ", self.primaryOrder)
continue
if data[0] == 2: # SetEncoding
data2 = sock.recv(3)
print("Client Message Type: SetEncoding (2)")
(nencodings,) = unpack("!xH", data2)
print("SetEncoding: total encodings ", repr(nencodings))
data2 = sock.recv(4 * nencodings, socket.MSG_WAITALL)
print("len", len(data2))
self.client_encodings = unpack("!%si" % nencodings, data2)
print("data", repr(self.client_encodings), len(self.client_encodings))
if self.ENCODINGS.zlib in self.client_encodings:
print("Using zlib encoding")
self.encoding = self.ENCODINGS.zlib
continue
if data[0] == 3: # FBUpdateRequest
data2 = sock.recv(9, socket.MSG_WAITALL)
#print("Client Message Type: FBUpdateRequest (3)")
#print(len(data2))
(incremental, x, y, w, h) = unpack("!BHHHH", data2)
#print("RFBU:", incremental, x, y, w, h)
self.SendRectangles(sock, x, y, w, h, incremental)
continue
if data[0] == 4:
kbdkey = ''
data2 = sock.recv(7)
# B = U8, L = U32
(downflag, key) = unpack("!BxxL", data2)
print("KeyEvent", downflag, hex(key))
spKey = getDictByValue(kdbmap, key)
if not spKey:
try:
kbdkey = chr(key)
except:
kbdkey = key
else:
kbdkey = key
if downflag:
func = getattr(keyboard, "press_key")
else:
func = getattr(keyboard, "release_key")
# dynamic keyboard mapping according to "mapping" obj
if spKey in mapping:
print("mapping:", mapping[spKey])
if sys.platform == "win32" or sys.platform == "win64" and 0 in mapping[spKey]:
kbdkey = mapping[spKey][0]
if sys.platform == "darwin" and 1 in mapping[spKey]:
kbdkey = mapping[spKey][1]
if sys.platform == "linux" and 2 in mapping[spKey]:
kbdkey = mapping[spKey][2]
print("getDictByValue", getDictByValue(kdbmap, key))
func(kbdkey)
continue
if data[0] == 5: # PointerEvent
data2 = sock.recv(5, socket.MSG_WAITALL)
(buttonmask, x, y) = unpack("!BHH", data2)
mouse.move(x, y)
buttons[0] = buttonmask & int("0000001", 2) # left button
buttons[1] = buttonmask & int("0000010", 2) # middle button
buttons[2] = buttonmask & int("0000100", 2) # right button
buttons[3] = buttonmask & int("0001000", 2) # scroll up
buttons[4] = buttonmask & int("0010000", 2) # scroll down
if buttons[0] and not left_pressed:
print("LEFT PRESSED")
mouse.press(x, y, 1)
left_pressed = 1
elif not buttons[0] and left_pressed:
print("LEFT RELEASED")
mouse.release(x, y, 1)
left_pressed = 0
if buttons[1] and not middle_pressed:
print("MIDDLE PRESSED")
mouse.press(x, y, 3)
middle_pressed = 1
elif not buttons[1] and middle_pressed:
print("MIDDLE RELEASED")
mouse.release(x, y, 3)
middle_pressed = 0
if buttons[2] and not right_pressed:
print("RIGHT PRESSED")
mouse.press(x, y, 2)
right_pressed = 1
elif not buttons[2] and right_pressed:
print("RIGHT RELEASED")
mouse.release(x, y, 2)
right_pressed = 0
if buttons[3]:
print("SCROLLUP PRESSED")
mouse.scroll(vertical=1)
if buttons[4]:
print("SCROLLDOWN PRESSED")
mouse.scroll(vertical=-1)
#print("PointerEvent", buttonmask, x, y)
continue
else:
data2 = sock.recv(4096)
print("RAW Server received data:", repr(data[0]) , data+data2)
def GetRectangle(self, x, y, w, h):
try:
scr = ImageGrab.grab()
except:
return False
(scr_width, scr_height) = scr.size
if scr.mode != "RGB":
img = scr.convert("RGB")
else:
img = scr
del scr
crop = img.crop((x, y, w, h))
del img
return crop
def SendRectangles(self, sock, x, y, w, h, incremental=0):
# send FramebufferUpdate to client
#print("start SendRectangles")
rectangle = self.GetRectangle(x, y, w, h)
if not rectangle:
rectangle = Image.new("RGB", [w, h], (0,0,0))
lastshot = rectangle
sendbuff = bytearray()
# try to send only the actual changes
if self.framebuffer != None and incremental == 1:
diff = ImageChops.difference(rectangle, self.framebuffer)
if diff.getbbox() is None:
rectangles = 0
sendbuff.extend(pack("!BxH", 0, rectangles))
sock.sendall(sendbuff)
sleep(0.3)
return
if diff.getbbox() is not None:
if hasattr(diff, "getbbox"):
rectangle = rectangle.crop(diff.getbbox())
(x, y, _, _) = diff.getbbox()
w = rectangle.width
h = rectangle.height
#print("XYWH:", x,y,w,h, "diff", repr(diff.getbbox()))
stimeout = sock.gettimeout()
sock.settimeout(None)
if self.bpp == 32 or self.bpp == 8:
if rectangle.mode is not "RGB":
image = rectangle.convert("RGB")
else:
image = rectangle
b = np.asarray(image)
a = b.copy()
del b
if self.bpp == 32:
redBits = 8
greenBits = 8
blueBits = 8
elif self.bpp == 8:
redBits = 4
greenBits = 4
blueBits = 4
#redMask = ((1 << redBits) - 1) << self.red_shift
#greenMask = ((1 << greenBits) - 1) << self.green_shift
#blueMask = ((1 << blueBits) - 1) << self.blue_shift
#print("redMask", redMask, greenMask, blueMask)
if self.primaryOrder == "bgr":
self.blue_shift = 0
blueMask = (1 << blueBits) - 1
self.green_shift = blueBits
greenMask = ((1 << greenBits) - 1) << self.green_shift
self.red_shift = self.green_shift + greenBits
redMask = ((1 << redBits) - 1) << self.red_shift
else: # RGB
self.red_shift = 0
redMask = (1 << redBits) - 1
self.green_shift = redBits
greenMask = ((1 << greenBits) - 1) << self.green_shift
self.blue_shift = self.green_shift + greenBits
blueMask = ((1 << blueBits) - 1) << self.blue_shift
a[..., 0] = ( a[..., 0] ) & redMask >> self.red_shift
a[..., 1] = ( a[..., 1] ) & greenMask >> self.green_shift
a[..., 2] = ( a[..., 2] ) & blueMask >> self.blue_shift
image = Image.fromarray(a)
del a
if self.primaryOrder == "rgb":
(b, g, r) = image.split()
image = Image.merge("RGB", (r, g, b))
del b,g,r
if self.bpp == 32:
image = image.convert("RGBX")
elif self.bpp == 8:
image = image.convert("P")
#image = image.convert("RGB")
#p = Image.new("P",(16,16))
#p.putpalette(self.BGR233)
#image = quantizetopalette(image, p, dither=CONFIG._8bitdither)
#image.putpalette(self.BGR233)
#del p
#print(image)
if self.encoding == self.ENCODINGS.zlib:
rectangles = 1
sendbuff.extend(pack("!BxH", 0, rectangles))
sendbuff.extend(pack("!HHHH", x, y, w, h))
sendbuff.extend(pack(">i", self.encoding))
print("Compressing...")
#zlibdata = zlib.compress( image.tobytes() )[2:-4] # no header and checksum
#zlibdata = zlib.compress( image.tobytes() )[:-4] # no checksum
zlibdata = zlib.compress( image.tobytes() )
l = pack("!I", len(zlibdata) )
print("LEN:", hexdump(l), len(zlibdata) )
sendbuff.extend( l ) # send length
print("ZLIB HEAD:", hexdump(zlibdata[0:2]) )
chksum = zlibdata[-4:]
print("ZLIB CHECKSUM:", hexdump(chksum) )
sendbuff.extend( zlibdata ) # send compressed data
#inf = inflate(zlibdata, winsize=-15)
del zlibdata, l
else:
# send with RAW encoding
rectangles = 1
sendbuff.extend(pack("!BxH", 0, rectangles))
sendbuff.extend(pack("!HHHH", x, y, w, h))
sendbuff.extend(pack(">i", self.encoding))
sendbuff.extend( image.tobytes() )
elif self.bpp == -8:
print("8BPP routines!")
if rectangle.mode is not "RGB":
image = rectangle.convert("RGB")
else:
image = rectangle
(r, g, b) = image.split()
image = Image.merge("RGB", (g, r, b))
del b,g,r
p = Image.new("P",(16,16))
p.putpalette(self.BGR233)
image = quantizetopalette(image, p, dither=CONFIG._8bitdither)
image.putpalette(self.BGR233)
del p
rectangles = 1
sendbuff.extend(pack("!BxH", 0, rectangles))
sendbuff.extend(pack("!HHHH", x, y, w, h))
sendbuff.extend(pack(">i", self.encoding))
sendbuff.extend( image.tobytes() )
else:
print("[!] Unsupported BPP: %s" % self.bpp)
self.framebuffer = lastshot
sock.sendall(sendbuff)
sock.settimeout(stimeout)
#print("end SendRectangles")
class ControlThread(Thread):
def __init__(self, threads):
Thread.__init__(self)
self.threads = threads
self.setDaemon(True)
def run(self):
# elimina los threads muertos
while True:
sleep(1)
for t in threads:
if not t.isAlive():
print("ControlThread removing dead", t)
threads.remove(t)
class ClientThread(Thread):
def __init__(self, sock, ip, port):
Thread.__init__(self)
self.ip = ip
self.port = port
self.sock = sock
self.setDaemon(True)
def __del__(self):
print("ClientThread died")
def run(self):
print("[+] New server socket thread started for " + self.ip + ":" + str(self.port))
#print("Thread", self)
server = VncServer(self.sock, self.ip, self.port)
status = server.init()
if not status:
print("Error negotiating client init")
return False
server.protocol()
def main(argv):
global CONFIG, TCP_IP, TCP_PORT, VNC_PASSWORD, mouse, keyboard, threads, controlthread
class CONFIG:
_8bitdither = False
parser = ArgumentParser()
parser.add_argument("-l", "--listen-address", dest="TCP_IP",
help="Listen in this address, default: %s" % ("0.0.0.0"), required=False, default='0.0.0.0')
parser.add_argument("-p", "--port", dest="TCP_PORT",
help="Listen in this port, default: %s" % ("5901"), type=int, required=False, default='5901')
parser.add_argument("-P", "--password", help="Sets password", required=True, dest="VNC_PASSWORD")
parser.add_argument("-8", "--8bitdither", help="Enable 8 bit dithering", required=False, action='store_true', dest="dither")
args = parser.parse_args()
# Multithreaded Python server
TCP_IP = '0.0.0.0' if not hasattr(args,"TCP_IP") else args.TCP_IP
TCP_PORT = '0.0.0.0' if not hasattr(args,"TCP_PORT") else args.TCP_PORT
VNC_PASSWORD = args.VNC_PASSWORD
CONFIG._8bitdither = args.dither
mouse = PyMouse()
keyboard = PyKeyboard()
sockServer = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sockServer.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sockServer.bind((TCP_IP, TCP_PORT))
controlthread = ControlThread(threads)
controlthread.start()
threads.append(controlthread)
print("Multithreaded Python server : Waiting for connections from TCP clients...")
print("Runing on:", sys.platform)
while True:
sockServer.listen(4)
(conn, (ip,port)) = sockServer.accept()
newthread = ClientThread(conn, ip, port)
newthread.setDaemon(True)
newthread.start()
threads.append(newthread)
#print(threads)
if __name__ == "__main__":
try:
threads = []
main(sys.argv)
except KeyboardInterrupt:
# quit
print("Exiting on ctrl+c...")
#for t in threads:
# print("Killing", t)
sys.exit()