From f4c77886bddd8d97a93f2e389195e7c038992551 Mon Sep 17 00:00:00 2001 From: Matias Fernandez Date: Tue, 27 Mar 2018 10:45:54 -0300 Subject: [PATCH] Initial commit --- pyvncs/__init__.py | 22 + pyvncs/__pycache__/__init__.cpython-36.pyc | Bin 0 -> 202 bytes pyvncs/__pycache__/server.cpython-36.pyc | Bin 0 -> 15820 bytes pyvncs/server.py | 816 ++++++++++++++++++++ requeriments.txt | 2 + server.py | 339 ++++++++ server2.py | 854 +++++++++++++++++++++ server3.py | 821 ++++++++++++++++++++ server4.py | 102 +++ test.php | 49 ++ test.py | 15 + test2.py | 12 + test3.py | 43 ++ testtkinker.py | 79 ++ 14 files changed, 3154 insertions(+) create mode 100644 pyvncs/__init__.py create mode 100644 pyvncs/__pycache__/__init__.cpython-36.pyc create mode 100644 pyvncs/__pycache__/server.cpython-36.pyc create mode 100644 pyvncs/server.py create mode 100644 requeriments.txt create mode 100755 server.py create mode 100755 server2.py create mode 100755 server3.py create mode 100644 server4.py create mode 100755 test.php create mode 100644 test.py create mode 100755 test2.py create mode 100755 test3.py create mode 100644 testtkinker.py diff --git a/pyvncs/__init__.py b/pyvncs/__init__.py new file mode 100644 index 0000000..7b7400f --- /dev/null +++ b/pyvncs/__init__.py @@ -0,0 +1,22 @@ +# coding=utf-8 +# pyvncs +# Copyright (C) 2017-2018 Matias Fernandez +# +# This program is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the Free +# Software Foundation, either version 3 of the License, or (at your option) any +# later version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +# details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program. If not, see . + +""" +The main pyvncs module +""" + +from . import server diff --git a/pyvncs/__pycache__/__init__.cpython-36.pyc b/pyvncs/__pycache__/__init__.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..65bdec779b1b8f39732359767d5e61fdce8c8bf4 GIT binary patch literal 202 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 BlNta3 literal 0 HcmV?d00001 diff --git a/pyvncs/server.py b/pyvncs/server.py new file mode 100644 index 0000000..6bf81a5 --- /dev/null +++ b/pyvncs/server.py @@ -0,0 +1,816 @@ +# coding=utf-8 +# pyvncs +# Copyright (C) 2017-2018 Matias Fernandez +# +# This program is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the Free +# Software Foundation, either version 3 of the License, or (at your option) any +# later version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +# details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program. If not, see . + +from struct import * +from pyDes import * +from time import sleep +from pynput import mouse, keyboard + +import socket +import select +import os +import sys +import random +import zlib +import numpy as np + +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) + + +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 + + + +class VncServer(): + + class ENCODINGS: + raw = 0 + zlib = 6 # zlib + cursor = -239 # mouse cursor pseudo encoding + + class CONFIG: + _8bitdither = False + + def __init__(self, socket, password): + self.RFB_VERSION = '003.008' + self.RFB_SECTYPES = [ + 2, # VNC auth + 19 # VeNCrypt + ] + self.initmsg = ("RFB %s\n" % self.RFB_VERSION) + self.socket = socket + self.framebuffer = None + self.password = password + self.sectypes = self.RFB_SECTYPES + self.remotecursor = False + + 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(self.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 = (self.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 + + + kbdmap = { + 0xff08: keyboard.Key.backspace, + 0xff09: keyboard.Key.tab, + 0xff0d: keyboard.Key.enter, + 0xff1b: keyboard.Key.esc, + 0xff63: keyboard.Key.insert if hasattr(keyboard.Key, "insert") else None, + 0xffff: keyboard.Key.delete, + 0xff50: keyboard.Key.home, + 0xff57: keyboard.Key.end, + 0xff55: keyboard.Key.page_up, + 0xff56: keyboard.Key.page_down, + 0xff51: keyboard.Key.left, + 0xff52: keyboard.Key.up, + 0xff53: keyboard.Key.right, + 0xff54: keyboard.Key.down, + 0xffbe: keyboard.Key.f1, + 0xffbf: keyboard.Key.f2, + 0xffc0: keyboard.Key.f3, + 0xffc1: keyboard.Key.f4, + 0xffc2: keyboard.Key.f5, + 0xffc3: keyboard.Key.f6, + 0xffc4: keyboard.Key.f7, + 0xffc5: keyboard.Key.f8, + 0xffc6: keyboard.Key.f9, + 0xffc7: keyboard.Key.f10, + 0xffc8: keyboard.Key.f11, + 0xffc9: keyboard.Key.f12, + 0xffca: keyboard.Key.f13, + 0xffcb: keyboard.Key.f14, + 0xffcc: keyboard.Key.f15, + 0xffcd: keyboard.Key.f16, + 0xffce: keyboard.Key.f17, + 0xffcf: keyboard.Key.f18, + 0xffd0: keyboard.Key.f19, + 0xffd1: keyboard.Key.f20, + 0xffe1: keyboard.Key.shift_l, + 0xffe2: keyboard.Key.shift_r, + 0xffe3: keyboard.Key.ctrl_l, + 0xffe4: keyboard.Key.ctrl_r, + 0xffe7: None, # "KEY_MetaLeft" + 0xffe8: None, # "KEY_MetaRight" + 0xffe9: keyboard.Key.cmd_l, + 0xffea: keyboard.Key.alt_gr, # "KEY_AltRight" + 0xff14: keyboard.Key.scroll_lock if hasattr(keyboard.Key, "scroll_lock") else None, + 0xff15: keyboard.Key.print_screen if hasattr(keyboard.Key, "print_screen") else None, # "KEY_Sys_Req" + 0xff7f: keyboard.Key.num_lock if hasattr(keyboard.Key, "num_lock") else None, + 0xffe5: keyboard.Key.caps_lock, + 0xff13: keyboard.Key.pause if hasattr(keyboard.Key, "pause") else None, + 0xffeb: keyboard.Key.cmd_r, # "KEY_Super_L" + 0xffec: keyboard.Key.cmd_r, # "KEY_Super_R" + 0xffed: None, # "KEY_Hyper_L" + 0xffee: None, # "KEY_Hyper_R" + 0xffb0: None, # "KEY_KP_0" + 0xffb1: None, # "KEY_KP_1" + 0xffb2: None, # "KEY_KP_2" + 0xffb3: None, # "KEY_KP_3" + 0xffb4: None, # "KEY_KP_4" + 0xffb5: None, # "KEY_KP_5" + 0xffb6: None, # "KEY_KP_6" + 0xffb7: None, # "KEY_KP_7" + 0xffb8: None, # "KEY_KP_8" + 0xffb9: None, # "KEY_KP_9" + 0xff8d: None, # "KEY_KP_Enter" + 0x002f: "/", # KEY_ForwardSlash + 0x005c: "\\", # KEY_BackSlash + 0x0020: keyboard.Key.space, # "KEY_SpaceBar" + 0xff7e: keyboard.Key.alt_gr, # altgr, at least on a mac (?) + 0xfe03: keyboard.Key.alt_l, + } + + if sys.platform == "darwin": + kbdmap[0xffe2] = keyboard.Key.shift + + 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.cursor in self.client_encodings: + print("Remote cursor encoding present") + self.remotecursor = True + self.cursorchanged = True + + 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) + + if self.remotecursor and self.cursorchanged: + # FIXME: send cursor to remote client + self.cursorchanged = False + continue + + if data[0] == 4: + kbdkey = '' + data2 = sock.recv(7) + # B = U8, L = U32 + (downflag, key) = unpack("!BxxL", data2) + print("KeyEvent", downflag, hex(key)) + + # special key + if key in kbdmap: + kbdkey = kbdmap[key] + else: # normal key + try: + kbdkey = keyboard.KeyCode.from_char(chr(key)) + except: + kbdkey = None + + try: + print("KEY:", kbdkey) + except: + print("KEY: (unprintable)") + + try: + if downflag: + keyboard.Controller().press(kbdkey) + else: + keyboard.Controller().release(kbdkey) + except: + print("Error sending key") + + continue + + if data[0] == 5: # PointerEvent + data2 = sock.recv(5, socket.MSG_WAITALL) + (buttonmask, x, y) = unpack("!BHH", data2) + 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 + + mouse.Controller().position = (x, y) + + if buttons[0] and not left_pressed: + print("LEFT PRESSED") + mouse.Controller().press(mouse.Button.left) + left_pressed = 1 + elif not buttons[0] and left_pressed: + print("LEFT RELEASED") + mouse.Controller().release(mouse.Button.left) + left_pressed = 0 + + if buttons[1] and not middle_pressed: + print("MIDDLE PRESSED") + mouse.Controller().press(mouse.Button.middle) + middle_pressed = 1 + elif not buttons[1] and middle_pressed: + print("MIDDLE RELEASED") + mouse.Controller().release(mouse.Button.middle) + middle_pressed = 0 + + if buttons[2] and not right_pressed: + print("RIGHT PRESSED") + mouse.Controller().press(mouse.Button.right) + right_pressed = 1 + elif not buttons[2] and right_pressed: + print("RIGHT RELEASED") + mouse.Controller().release(mouse.Button.right) + right_pressed = 0 + + if buttons[3]: + print("SCROLLUP PRESSED") + mouse.Controller().scroll(0, 2) + + if buttons[4]: + print("SCROLLDOWN PRESSED") + mouse.Controller().scroll(0, -2) + + #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() + + firstUpdateSent = False + + # 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)) + try: + sock.sendall(sendbuff) + except: + return False + 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: + #FIXME: improve 8 bit routines up!, image looks awful! + 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=self.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() ) + + + if self.encoding == self.ENCODINGS.zlib - 9998: + if not firstUpdateSent: + firstUpdateSent = True + compress = zlib.compressobj( + zlib.Z_DEFAULT_COMPRESSION, # level: 0-9 + zlib.DEFLATED, # method: must be DEFLATED + -15, # window size in bits: + # -15..-8: negate, suppress header + # 8..15: normal + # 16..30: subtract 16, gzip header + 1, # mem level: 1..8/9 + zlib.Z_DEFAULT_STRATEGY # strategy: + # 0 = Z_DEFAULT_STRATEGY + # 1 = Z_FILTERED + # 2 = Z_HUFFMAN_ONLY + # 3 = Z_RLE + # 4 = Z_FIXED + ) + + 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 = compress.compress( image.tobytes() ) + zlibdata += compress.flush() + l = pack("!I", len(zlibdata) ) + + sendbuff.extend( l ) # send length + sendbuff.extend( zlibdata ) # send compressed data + + 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...") + + + if not firstUpdateSent: + firstUpdateSent = True + zlibdata = zlib.compress( image.tobytes() )[2:] + print("FIRSTTTTTTTTTTTTTTTTTTTTTTTTTT") + else: + zlibdata = zlib.compress( image.tobytes() )[2:-4] + + #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) ) + sendbuff.extend( l ) # send length + sendbuff.extend( zlibdata ) # send compressed data + #sendbuff.extend( pack("!B", 0) ) + + #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() ) + + else: + print("[!] Unsupported BPP: %s" % self.bpp) + + self.framebuffer = lastshot + try: + sock.sendall(sendbuff) + except: + # connection closed? + return False + sock.settimeout(stimeout) + #print("end SendRectangles") diff --git a/requeriments.txt b/requeriments.txt new file mode 100644 index 0000000..50504bc --- /dev/null +++ b/requeriments.txt @@ -0,0 +1,2 @@ +pyuserinput + diff --git a/server.py b/server.py new file mode 100755 index 0000000..aa1420d --- /dev/null +++ b/server.py @@ -0,0 +1,339 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +import socket, os, sys, wx +from threading import Thread +from time import sleep +from struct import * +from pyDes import * + +def hexdump(data): + print(" ".join(hex(ord(n)) for n in data)) + +class VncServer(): + def __init__(self, socket, ip, port): + self.initmsg = "RFB 003.008\n" + self.socket = socket + + self.sectypes = [ + 2, # VNC auth + 19 # VeNCrypt + ] + + 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) + if data == self.initmsg.encode(): + print("init OK") + else: + print("init NOT OK!! '%s' '%s'" % (data, self.initmsg.encode())) + sock.send(pack("BB", 1, 0)) + self.sendmessage("RFB protocol not supported") + sock.close() + return False + + # 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)) + + # ServerInit + screen = wx.ScreenDC() + print("screen", repr(screen)) + size = screen.GetSize() + print("size", repr(size)) + + width = size[0] + height = size[1] + bpp = 32 # FIXME: get real bpp + depth = 24 # FIXME: get real depth + self.depth = depth + self.bpp = 32 + bigendian = 0 + truecolor = 1 + red_maximum = 255 + green_maximum = 255 + blue_maximum = 255 + red_shift = 16 + self.red_shift = red_shift + green_shift = 8 + self.green_shift = green_shift + blue_shift = 0 + self.blue_shift = blue_shift + padding1 = 0 + padding2 = 0 + padding3 = 0 + + 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("!BBB", padding1, padding2, padding3) + + 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) + + return True + + + def protocol(self): + sock = self.socket + sock.settimeout(1) # set nonblocking socket + + screen = wx.ScreenDC() + size = screen.GetSize() + width = size[0] + height = size[1] + + while True: + 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: # SetPixelFormat + data2 = sock.recv(19) + 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("bpp", self.bpp) + print("depth", self.depth) + + if data[0] == 2: # SetEncoding + data2 = sock.recv(3) + print("Client Message Type: SetEncoding (2)") + h = unpack("xH", data2) + print("h", repr(h)) + data2 = sock.recv(4096) + + else: + data2 = sock.recv(4096) + print("RAW Server received data:", data+data2) + + #sleep(0.1) + #self.RAWSendRectangles(sock, 0, 0, width, height) + + def GetRectangle(self, x, y, w, h): + screen = wx.ScreenDC() + size = screen.GetSize() + bmp = wx.Bitmap(size[0], size[1], self.depth) + mem = wx.MemoryDC() + mem.SelectObject(bmp) + mem.Blit(0, 0, size[0], size[1], screen, 0, 0) + mem.SelectObject(wx.NullBitmap) + + rect = bmp.GetSubBitmap(wx.Rect(x, y, w, h)) + image = wx.Bitmap.ConvertToImage(rect) + + del mem + del bmp + del rect + + return image + + def RAWSendRectangles(self, sock, x, y, w, h): + image = self.GetRectangle(x, y, w, h) + pixelData = image.GetData() + + sendbuff = pack("!BBH", 0, 0, 1) + sendbuff += pack("!HHHH", x, y, w, h) + sendbuff += pack("!i", 0) + sock.send(sendbuff) + + sendbuff = bytearray() + print("Start...") + for b in range(0, len(pixelData), 3): + red = (pixelData[b] & 0x000000FF) >> self.red_shift + green = (pixelData[b+1] & 0x000000FF) >> self.green_shift + blue = (pixelData[b+2] & 0x000000FF) >> self.blue_shift + sendbuff.extend( pack("!BBBx", pixelData[b], pixelData[b+1], pixelData[b+2]) ) + #sendbuff += pack("BBBx", pixelData[b], pixelData[b+1], pixelData[b+2]) + #print(".", end='', flush=True) + + print("End...") + sock.sendall(sendbuff) + + #c = 0 + #for d in pixelData: + # if c == 3: + # c=0 + # sock.send( pack("x") ) + + # sock.send( pack("B", d)) + # c += 1 + + #sock.sendall(pack( "B" , pixelData)) + #print("Supossed data len:", w * h * self.depth) + #print("Real data len: ", len(pixelData)) + + +class ControlThread(Thread): + def __init__(self, threads): + Thread.__init__(self) + self.threads = threads + + def run(self): + # elimina los threads muertos + while True: + sleep(1) + for t in threads: + if not t.isAlive(): + threads.remove(t) + + +class ClientThread(Thread): + def __init__(self, sock, ip, port): + Thread.__init__(self) + self.ip = ip + self.port = port + self.sock = sock + + def __del__(self): + print("ClientThread died") + + def run(self): + print("[+] New server socket thread started for " + self.ip + ":" + str(self.port)) + server = VncServer(self.sock, self.ip, self.port) + status = server.init() + if not status: + print("Error negotiating client init") + return False + server.protocol() + + +# Multithreaded Python server +TCP_IP = '0.0.0.0' +TCP_PORT = 5901 + +VNC_PASSWORD='kaka80' + +app = wx.App(False) + +sockServer = socket.socket(socket.AF_INET, socket.SOCK_STREAM) +sockServer.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) +sockServer.bind((TCP_IP, TCP_PORT)) +threads = [] + +controlthread = ControlThread(threads) +controlthread.start() + +print("Multithreaded Python server : Waiting for connections from TCP clients...") +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) diff --git a/server2.py b/server2.py new file mode 100755 index 0000000..05bc2a0 --- /dev/null +++ b/server2.py @@ -0,0 +1,854 @@ +#!/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() diff --git a/server3.py b/server3.py new file mode 100755 index 0000000..72d86c9 --- /dev/null +++ b/server3.py @@ -0,0 +1,821 @@ +#!/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 pynput import mouse, keyboard + +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 + + + kbdmap = { + 0xff08: keyboard.Key.backspace, + 0xff09: keyboard.Key.tab, + 0xff0d: keyboard.Key.enter, + 0xff1b: keyboard.Key.esc, + 0xff63: keyboard.Key.insert if hasattr(keyboard.Key, "insert") else None, + 0xffff: keyboard.Key.delete, + 0xff50: keyboard.Key.home, + 0xff57: keyboard.Key.end, + 0xff55: keyboard.Key.page_up, + 0xff56: keyboard.Key.page_down, + 0xff51: keyboard.Key.left, + 0xff52: keyboard.Key.up, + 0xff53: keyboard.Key.right, + 0xff54: keyboard.Key.down, + 0xffbe: keyboard.Key.f1, + 0xffbf: keyboard.Key.f2, + 0xffc0: keyboard.Key.f3, + 0xffc1: keyboard.Key.f4, + 0xffc2: keyboard.Key.f5, + 0xffc3: keyboard.Key.f6, + 0xffc4: keyboard.Key.f7, + 0xffc5: keyboard.Key.f8, + 0xffc6: keyboard.Key.f9, + 0xffc7: keyboard.Key.f10, + 0xffc8: keyboard.Key.f11, + 0xffc9: keyboard.Key.f12, + 0xffca: keyboard.Key.f13, + 0xffcb: keyboard.Key.f14, + 0xffcc: keyboard.Key.f15, + 0xffcd: keyboard.Key.f16, + 0xffce: keyboard.Key.f17, + 0xffcf: keyboard.Key.f18, + 0xffd0: keyboard.Key.f19, + 0xffd1: keyboard.Key.f20, + 0xffe1: keyboard.Key.shift_l, + 0xffe2: keyboard.Key.shift_r, + 0xffe3: keyboard.Key.ctrl_l, + 0xffe4: keyboard.Key.ctrl_r, + 0xffe7: None, # "KEY_MetaLeft" + 0xffe8: None, # "KEY_MetaRight" + 0xffe9: keyboard.Key.cmd_l, + 0xffea: keyboard.Key.alt_gr, # "KEY_AltRight" + 0xff14: keyboard.Key.scroll_lock if hasattr(keyboard.Key, "scroll_lock") else None, + 0xff15: keyboard.Key.print_screen if hasattr(keyboard.Key, "print_screen") else None, # "KEY_Sys_Req" + 0xff7f: keyboard.Key.num_lock if hasattr(keyboard.Key, "num_lock") else None, + 0xffe5: keyboard.Key.caps_lock, + 0xff13: keyboard.Key.pause if hasattr(keyboard.Key, "pause") else None, + 0xffeb: keyboard.Key.cmd_r, # "KEY_Super_L" + 0xffec: keyboard.Key.cmd_r, # "KEY_Super_R" + 0xffed: None, # "KEY_Hyper_L" + 0xffee: None, # "KEY_Hyper_R" + 0xffb0: None, # "KEY_KP_0" + 0xffb1: None, # "KEY_KP_1" + 0xffb2: None, # "KEY_KP_2" + 0xffb3: None, # "KEY_KP_3" + 0xffb4: None, # "KEY_KP_4" + 0xffb5: None, # "KEY_KP_5" + 0xffb6: None, # "KEY_KP_6" + 0xffb7: None, # "KEY_KP_7" + 0xffb8: None, # "KEY_KP_8" + 0xffb9: None, # "KEY_KP_9" + 0xff8d: None, # "KEY_KP_Enter" + 0x002f: "/", # KEY_ForwardSlash + 0x005c: "\\", # KEY_BackSlash + 0x0020: keyboard.Key.space, # "KEY_SpaceBar" + 0xff7e: keyboard.Key.alt_gr, # altgr, at least on a mac (?) + 0xfe03: keyboard.Key.alt_l, + } + + if sys.platform == "darwin": + kbdmap[0xffe2] = keyboard.Key.shift + + 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)) + + # special key + if key in kbdmap: + kbdkey = kbdmap[key] + else: # normal key + try: + kbdkey = keyboard.KeyCode.from_char(chr(key)) + except: + kbdkey = None + + try: + print("KEY:", kbdkey) + except: + print("KEY: (unprintable)") + + try: + if downflag: + keyboard.Controller().press(kbdkey) + else: + keyboard.Controller().release(kbdkey) + except: + print("Error sending key") + + continue + + if data[0] == 5: # PointerEvent + data2 = sock.recv(5, socket.MSG_WAITALL) + (buttonmask, x, y) = unpack("!BHH", data2) + 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 + + mouse.Controller().position = (x, y) + + if buttons[0] and not left_pressed: + print("LEFT PRESSED") + mouse.Controller().press(mouse.Button.left) + left_pressed = 1 + elif not buttons[0] and left_pressed: + print("LEFT RELEASED") + mouse.Controller().release(mouse.Button.left) + left_pressed = 0 + + if buttons[1] and not middle_pressed: + print("MIDDLE PRESSED") + mouse.Controller().press(mouse.Button.middle) + middle_pressed = 1 + elif not buttons[1] and middle_pressed: + print("MIDDLE RELEASED") + mouse.Controller().release(mouse.Button.middle) + middle_pressed = 0 + + if buttons[2] and not right_pressed: + print("RIGHT PRESSED") + mouse.Controller().press(mouse.Button.right) + right_pressed = 1 + elif not buttons[2] and right_pressed: + print("RIGHT RELEASED") + mouse.Controller().release(mouse.Button.right) + right_pressed = 0 + + if buttons[3]: + print("SCROLLUP PRESSED") + mouse.Controller().scroll(0, 2) + + if buttons[4]: + print("SCROLLDOWN PRESSED") + mouse.Controller().scroll(0, -2) + + #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 + + 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() diff --git a/server4.py b/server4.py new file mode 100644 index 0000000..0a6afa2 --- /dev/null +++ b/server4.py @@ -0,0 +1,102 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +import pyvncs +from argparse import ArgumentParser +from threading import Thread +from time import sleep + +import sys +import socket + + +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 = pyvncs.server.VncServer(self.sock, VNC_PASSWORD) + server.CONFIG._8bitdither = CONFIG._8bitdither + 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, 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 + + 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() + \ No newline at end of file diff --git a/test.php b/test.php new file mode 100755 index 0000000..c0fb01b --- /dev/null +++ b/test.php @@ -0,0 +1,49 @@ +#!/usr/bin/php + 8){ + $cnt = 8; + } + + for($i=1; $i<=$cnt; $i++){ + $s = $arr[$i]; + $s = (($s >> 1) & 0x55) | (($s << 1) & 0xaa); + $s = (($s >> 2) & 0x33) | (($s << 2) & 0xcc); + $s = (($s >> 4) & 0x0f) | (($s << 4) & 0xf0); + $ret = $ret . chr($s); + } + return $ret; +} + +$passwd="kaka80\0\0"; +$data = "1234567890123456"; + +$iv = mcrypt_create_iv(mcrypt_get_iv_size (MCRYPT_DES, MCRYPT_MODE_ECB), MCRYPT_RAND); +$crypted = mcrypt_encrypt(MCRYPT_DES, mirrorBits($passwd), $data, MCRYPT_MODE_ECB, $iv); + +echo "Crypted: " . base64_encode($crypted); +echo "\n"; diff --git a/test.py b/test.py new file mode 100644 index 0000000..a05e776 --- /dev/null +++ b/test.py @@ -0,0 +1,15 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +from pynput import mouse, keyboard + +keyboard.Controller().press(keyboard.Key.shift) +keyboard.Controller().press('a') + +#keyboard.Controller().modifiers(keyboard.Key().shift) +#print("Shift:", keyboard.Controller().shift_pressed) +#keyboard.Controller().press('a') +#keyboard.Controller().release('a') +#keyboard.Controller().release(keyboard.Key.shift_r) + + diff --git a/test2.py b/test2.py new file mode 100755 index 0000000..0cec203 --- /dev/null +++ b/test2.py @@ -0,0 +1,12 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +zlibHeader = bytearray() +zlibLength = 300309 + +zlibHeader.append( (zlibLength>>24) & 0xFF ) +zlibHeader.append( (zlibLength>>16) & 0xFF ) +zlibHeader.append( (zlibLength>>8) & 0xFF ) +zlibHeader.append( zlibLength & 0xFF ) + +print(zlibHeader) diff --git a/test3.py b/test3.py new file mode 100755 index 0000000..c78f157 --- /dev/null +++ b/test3.py @@ -0,0 +1,43 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +from PIL import Image, ImageChops, ImageDraw + +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) + + +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] + +im = Image.open("/Users/radix/Downloads/IMG_20170929_185311.jpg") +print(im) + +p = Image.new("P",(16,16)) +p.putpalette(BGR233) + +#im2 = im.quantize(palette=p) + +im2 = quantizetopalette(im, p, dither=False) + +im2.show() + +print(im2.getpalette() == BGR233) \ No newline at end of file diff --git a/testtkinker.py b/testtkinker.py new file mode 100644 index 0000000..7f56386 --- /dev/null +++ b/testtkinker.py @@ -0,0 +1,79 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +import sys + +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 + + + +thickarrow_strings = ( #sized 24x24 + "XX ", + "XXX ", + "XXXX ", + "XX.XX ", + "XX..XX ", + "XX...XX ", + "XX....XX ", + "XX.....XX ", + "XX......XX ", + "XX.......XX ", + "XX........XX ", + "XX........XXX ", + "XX......XXXXX ", + "XX.XXX..XX ", + "XXXX XX..XX ", + "XX XX..XX ", + " XX..XX ", + " XX..XX ", + " XX..XX ", + " XXXX ", + " XX ", + " ", + " ", + " ") + + +buf = "" +for x in thickarrow_strings: + buf += x + +i = Image.frombytes("I", (24,24), str.encode(buf)) +print(i) +i.show() + +