#!/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()