Mejoras en general

This commit is contained in:
Matias Fernandez
2019-07-29 22:54:48 -04:00
parent 57623a6933
commit a6327060f9
16 changed files with 738 additions and 393 deletions

2
.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
__pycache__/
*.py[cod]

260
lib/bgr233_palette.py Normal file
View File

@@ -0,0 +1,260 @@
# BGR233 palette
palette = [
0, 0, 0,
36, 0, 0,
73, 0, 0,
109, 0, 0,
146, 0, 0,
182, 0, 0,
219, 0, 0,
255, 0, 0,
0, 36, 0,
36, 36, 0,
73, 36, 0,
109, 36, 0,
146, 36, 0,
182, 36, 0,
219, 36, 0,
255, 36, 0,
0, 73, 0,
36, 73, 0,
73, 73, 0,
109, 73, 0,
146, 73, 0,
182, 73, 0,
219, 73, 0,
255, 73, 0,
0, 109, 0,
36, 109, 0,
73, 109, 0,
109, 109, 0,
146, 109, 0,
182, 109, 0,
219, 109, 0,
255, 109, 0,
0, 146, 0,
36, 146, 0,
73, 146, 0,
109, 146, 0,
146, 146, 0,
182, 146, 0,
219, 146, 0,
255, 146, 0,
0, 182, 0,
36, 182, 0,
73, 182, 0,
109, 182, 0,
146, 182, 0,
182, 182, 0,
219, 182, 0,
255, 182, 0,
0, 219, 0,
36, 219, 0,
73, 219, 0,
109, 219, 0,
146, 219, 0,
182, 219, 0,
219, 219, 0,
255, 219, 0,
0, 255, 0,
36, 255, 0,
73, 255, 0,
109, 255, 0,
146, 255, 0,
182, 255, 0,
219, 255, 0,
255, 255, 0,
0, 0, 85,
36, 0, 85,
73, 0, 85,
109, 0, 85,
146, 0, 85,
182, 0, 85,
219, 0, 85,
255, 0, 85,
0, 36, 85,
36, 36, 85,
73, 36, 85,
109, 36, 85,
146, 36, 85,
182, 36, 85,
219, 36, 85,
255, 36, 85,
0, 73, 85,
36, 73, 85,
73, 73, 85,
109, 73, 85,
146, 73, 85,
182, 73, 85,
219, 73, 85,
255, 73, 85,
0, 109, 85,
36, 109, 85,
73, 109, 85,
109, 109, 85,
146, 109, 85,
182, 109, 85,
219, 109, 85,
255, 109, 85,
0, 146, 85,
36, 146, 85,
73, 146, 85,
109, 146, 85,
146, 146, 85,
182, 146, 85,
219, 146, 85,
255, 146, 85,
0, 182, 85,
36, 182, 85,
73, 182, 85,
109, 182, 85,
146, 182, 85,
182, 182, 85,
219, 182, 85,
255, 182, 85,
0, 219, 85,
36, 219, 85,
73, 219, 85,
109, 219, 85,
146, 219, 85,
182, 219, 85,
219, 219, 85,
255, 219, 85,
0, 255, 85,
36, 255, 85,
73, 255, 85,
109, 255, 85,
146, 255, 85,
182, 255, 85,
219, 255, 85,
255, 255, 85,
0, 0, 170,
36, 0, 170,
73, 0, 170,
109, 0, 170,
146, 0, 170,
182, 0, 170,
219, 0, 170,
255, 0, 170,
0, 36, 170,
36, 36, 170,
73, 36, 170,
109, 36, 170,
146, 36, 170,
182, 36, 170,
219, 36, 170,
255, 36, 170,
0, 73, 170,
36, 73, 170,
73, 73, 170,
109, 73, 170,
146, 73, 170,
182, 73, 170,
219, 73, 170,
255, 73, 170,
0, 109, 170,
36, 109, 170,
73, 109, 170,
109, 109, 170,
146, 109, 170,
182, 109, 170,
219, 109, 170,
255, 109, 170,
0, 146, 170,
36, 146, 170,
73, 146, 170,
109, 146, 170,
146, 146, 170,
182, 146, 170,
219, 146, 170,
255, 146, 170,
0, 182, 170,
36, 182, 170,
73, 182, 170,
109, 182, 170,
146, 182, 170,
182, 182, 170,
219, 182, 170,
255, 182, 170,
0, 219, 170,
36, 219, 170,
73, 219, 170,
109, 219, 170,
146, 219, 170,
182, 219, 170,
219, 219, 170,
255, 219, 170,
0, 255, 170,
36, 255, 170,
73, 255, 170,
109, 255, 170,
146, 255, 170,
182, 255, 170,
219, 255, 170,
255, 255, 170,
0, 0, 255,
36, 0, 255,
73, 0, 255,
109, 0, 255,
146, 0, 255,
182, 0, 255,
219, 0, 255,
255, 0, 255,
0, 36, 255,
36, 36, 255,
73, 36, 255,
109, 36, 255,
146, 36, 255,
182, 36, 255,
219, 36, 255,
255, 36, 255,
0, 73, 255,
36, 73, 255,
73, 73, 255,
109, 73, 255,
146, 73, 255,
182, 73, 255,
219, 73, 255,
255, 73, 255,
0, 109, 255,
36, 109, 255,
73, 109, 255,
109, 109, 255,
146, 109, 255,
182, 109, 255,
219, 109, 255,
255, 109, 255,
0, 146, 255,
36, 146, 255,
73, 146, 255,
109, 146, 255,
146, 146, 255,
182, 146, 255,
219, 146, 255,
255, 146, 255,
0, 182, 255,
36, 182, 255,
73, 182, 255,
109, 182, 255,
146, 182, 255,
182, 182, 255,
219, 182, 255,
255, 182, 255,
0, 219, 255,
36, 219, 255,
73, 219, 255,
109, 219, 255,
146, 219, 255,
182, 219, 255,
219, 219, 255,
255, 219, 255,
0, 255, 255,
36, 255, 255,
73, 255, 255,
109, 255, 255,
146, 255, 255,
182, 255, 255,
219, 255, 255,
255, 255, 255
]

View File

@@ -16,5 +16,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# at least, raw encoding is needed by the rfb protocol
from . import common as enc
from . import common
from . import raw
from . import zlib
from . import cursor

View File

@@ -15,5 +15,15 @@
# You should have received a copy of the GNU Lesser General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
encodings = {}
class ENCODINGS:
pass
raw = 0
zlib = 6
# supported pseudo-encodings
cursor = -239
encodings_priority = [
ENCODINGS.zlib,
ENCODINGS.raw
]

View File

@@ -16,5 +16,21 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from . import common
from struct import *
from lib import log
import zlib
common.ENCODINGS.cursor = -239
class Encoding:
name = 'Cursor'
id = -239
description = 'Cursor pseudo encoding'
enabled = True
pseudoEncoding = True
cursor_sent = False
def __init__(self):
log.debug("Initialized", __name__)
common.encodings[common.ENCODINGS.cursor] = Encoding
log.debug("Loaded encoding: %s (%s)" % (__name__, Encoding.id))

View File

@@ -17,16 +17,30 @@
from . import common
from struct import *
from lib import log
def send_image(x, y, w, h, image):
_buff = bytearray()
class Encoding:
_buff = None
name = 'raw'
id = 0
description = 'Raw VNC encoding'
enabled = True
firstUpdateSent = False
def __init__(self):
log.debug("Initialized", __name__)
def send_image(self, x, y, w, h, image):
self._buff = bytearray()
rectangles = 1
_buff.extend(pack("!BxH", 0, rectangles))
_buff.extend(pack("!HHHH", x, y, w, h))
_buff.extend(pack(">i", common.ENCODINGS.raw))
_buff.extend( image.tobytes() )
self._buff.extend(pack("!BxH", 0, rectangles)) # message type 0 == FramebufferUpdate
self._buff.extend(pack("!HHHH", x, y, w, h))
self._buff.extend(pack(">i", self.id))
self._buff.extend( image.tobytes() )
return _buff
return self._buff
common.ENCODINGS.raw = 0
common.ENCODINGS.raw_send_image = send_image
common.encodings[common.ENCODINGS.raw] = Encoding
log.debug("Loaded encoding: %s (%s)" % (__name__, Encoding.id))

54
lib/encodings/zlib.py Normal file
View File

@@ -0,0 +1,54 @@
from . import common
from struct import *
from lib import log
import zlib
class Encoding:
name = 'zlib'
id = 6
description = 'zlib VNC encoding'
enabled = True
firstUpdateSent = False
_compressObj = None
def __init__(self):
log.debug("Initialized", __name__)
self._compressObj = zlib.compressobj(
zlib.Z_DEFAULT_COMPRESSION, # level: 0-9
zlib.DEFLATED, # method: must be DEFLATED
zlib.MAX_WBITS, # window size in bits:
# -15..-8: negate, suppress header
# 8..15: normal
# 16..30: subtract 16, gzip header
zlib.DEF_MEM_LEVEL, # 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
)
def send_image(self, x, y, w, h, image):
sendbuff = bytearray()
rectangles = 1
sendbuff.extend(pack("!BxH", 0, rectangles)) # message type 0 == FramebufferUpdate
sendbuff.extend(pack("!HHHH", x, y, w, h))
sendbuff.extend(pack(">i", self.id))
#log.debug("Compressing...")
zlibdata = self._compressObj.compress( image.tobytes() )
zlibdata += self._compressObj.flush(zlib.Z_FULL_FLUSH)
#log.debug("LEN", len(zlibdata))
l = pack("!I", len(zlibdata) )
sendbuff.extend( l ) # send length
sendbuff.extend( zlibdata ) # send compressed data
return sendbuff
common.encodings[common.ENCODINGS.zlib] = Encoding
log.debug("Loaded encoding: %s (%s)" % (__name__, Encoding.id))

41
lib/imagegrab.py Normal file
View File

@@ -0,0 +1,41 @@
import sys
from PIL import Image
from lib import log
if sys.platform == "linux" or sys.platform == "linux2":
log.debug("ImageGrab: running on Linux")
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":
log.debug("ImageGrab: running on 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:
log.debug("ImageGrab: running on Unknown!")
from PIL import ImageGrab

47
lib/kbdctrl.py Normal file
View File

@@ -0,0 +1,47 @@
import sys
from struct import pack, unpack
from pynput import keyboard
from lib import log
from lib.kbdmap import *
class KeyboardController:
kbdmap = kbdmap
kbdkey = ''
downflag = None
key = None
controller = None
kbd = None
def __init__(self):
self.kbd = keyboard
self.controller = self.kbd.Controller()
def process_event(self, data):
# B = U8, L = U32
(self.downflag, self.key) = unpack("!BxxL", data)
log.debug("KeyEvent", self.downflag, hex(self.key))
# special key
if self.key in self.kbdmap:
self.kbdkey = self.kbdmap[self.key]
log.debug("SPECIAL KEY", self.kbdkey)
else: # normal key
try:
self.kbdkey = self.kbd.KeyCode.from_char(chr(self.key))
except:
self.kbdkey = None
# debug keypress to stdout
try:
log.debug("KEY:", self.kbdkey)
except:
log.debug("KEY: (unprintable)")
# send the actual keyboard event
try:
if self.downflag:
self.controller.press(self.kbdkey)
else:
self.controller.release(self.kbdkey)
except:
log.debug("Error sending key")

79
lib/kbdmap.py Normal file
View File

@@ -0,0 +1,79 @@
import sys
from pynput import keyboard
__all__ = ['kbdmap']
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,
0xffe9: keyboard.Key.alt,
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,
0xfe03: keyboard.Key.cmd_l,
}
if sys.platform == "darwin":
kbdmap[0xffe2] = keyboard.Key.shift

60
lib/mousectrl.py Normal file
View File

@@ -0,0 +1,60 @@
from struct import pack, unpack
from pynput import mouse
from lib import log
class MouseController():
def __init__(self):
self.buttonmask = 0
self.buttons = [0, 0, 0, 0, 0, 0, 0, 0]
self.left_pressed = 0
self.right_pressed = 0
self.middle_pressed = 0
def process_event(self, data):
(self.buttonmask, x, y) = unpack("!BHH", data)
self.buttons[0] = self.buttonmask & int("0000001", 2) # left button
self.buttons[1] = self.buttonmask & int("0000010", 2) # middle button
self.buttons[2] = self.buttonmask & int("0000100", 2) # right button
self.buttons[3] = self.buttonmask & int("0001000", 2) # scroll up
self.buttons[4] = self.buttonmask & int("0010000", 2) # scroll down
# set mouse position
mouse.Controller().position = (x, y)
# process mouse button events
if self.buttons[0] and not self.left_pressed:
log.debug("LEFT PRESSED")
mouse.Controller().press(mouse.Button.left)
self.left_pressed = 1
elif not self.buttons[0] and self.left_pressed:
log.debug("LEFT RELEASED")
mouse.Controller().release(mouse.Button.left)
self.left_pressed = 0
if self.buttons[1] and not self.middle_pressed:
log.debug("MIDDLE PRESSED")
mouse.Controller().press(mouse.Button.middle)
self.middle_pressed = 1
elif not self.buttons[1] and self.middle_pressed:
log.debug("MIDDLE RELEASED")
mouse.Controller().release(mouse.Button.middle)
self.middle_pressed = 0
if self.buttons[2] and not self.right_pressed:
log.debug("RIGHT PRESSED")
mouse.Controller().press(mouse.Button.right)
self.right_pressed = 1
elif not self.buttons[2] and self.right_pressed:
log.debug("RIGHT RELEASED")
mouse.Controller().release(mouse.Button.right)
self.right_pressed = 0
if self.buttons[3]:
log.debug("SCROLLUP PRESSED")
mouse.Controller().scroll(0, 2)
if self.buttons[4]:
log.debug("SCROLLDOWN PRESSED")
mouse.Controller().scroll(0, -2)
#log.debug("PointerEvent", buttonmask, x, y)

31
lib/oshelpers/windows.py Normal file
View File

@@ -0,0 +1,31 @@
import ctypes
import sys
from elevate import elevate
def is_admin():
try:
return ctypes.windll.shell32.IsUserAnAdmin()
except:
return False
def run_as_admin_old(argv=None):
shell32 = ctypes.windll.shell32
if argv is None and shell32.IsUserAnAdmin():
return True
if argv is None:
argv = sys.argv
if hasattr(sys, '_MEIPASS'):
# Support pyinstaller wrapped program.
arguments = argv[1:]
else:
arguments = argv
argument_line = u' '.join(arguments)
executable = sys.executable
ret = shell32.ShellExecuteW(None, u"runas", executable, argument_line, None, 1)
if int(ret) <= 32:
return False
return None
def run_as_admin():
elevate()

View File

@@ -19,17 +19,24 @@ from struct import *
from pyDes import *
from time import sleep
from pynput import mouse, keyboard
from PIL import Image, ImageChops, ImageDraw, ImagePalette
import socket
import select
import os
import sys
import random
import zlib
import numpy as np
from lib.encodings import *
from lib import mousectrl
from lib import kbdctrl
from lib.imagegrab import ImageGrab
from lib import log
from lib import bgr233_palette
# encodings support
import lib.encodings as encs
from lib.encodings.common import ENCODINGS
def hexdump(data):
str = ""
@@ -39,7 +46,7 @@ def hexdump(data):
return str
def quantizetopalette(silf, palette, dither=False):
"""Convert an RGB or L mode image to use a given P image's palette."""
"""Converts an RGB or L mode image to use a given P image's palette."""
silf.load()
@@ -60,50 +67,13 @@ def quantizetopalette(silf, palette, dither=False):
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 CONFIG:
_8bitdither = False
encoding_object = None
def __init__(self, socket, password):
self.RFB_VERSION = '003.008'
self.RFB_SECTYPES = [
@@ -115,72 +85,7 @@ class VncServer():
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]
self.cursor_support = False
def __del__(self):
log.debug("VncServer died")
@@ -348,94 +253,18 @@ class VncServer():
def protocol(self):
self.socket.settimeout(None) # set nonblocking socket
screen = ImageGrab.grab()
size = screen.size
width = size[0]
height = size[1]
del screen
mousecontroller = mousectrl.MouseController()
kbdcontroller = kbdctrl.KeyboardController()
self.primaryOrder = "rgb"
self.encoding = enc.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
self.encoding = ENCODINGS.raw
self.encoding_object = encs.common.encodings[self.encoding]()
while True:
#log.debug(".", end='', flush=True)
@@ -476,7 +305,7 @@ class VncServer():
self.primaryOrder = "rgb"
else:
self.primaryOrder = "bgr"
log.debug("Using order: ", self.primaryOrder)
log.debug("Using order:", self.primaryOrder)
continue
@@ -488,16 +317,25 @@ class VncServer():
data2 = sock.recv(4 * nencodings, socket.MSG_WAITALL)
#log.debug("len", len(data2))
self.client_encodings = unpack("!%si" % nencodings, data2)
#log.debug("data", repr(self.client_encodings), len(self.client_encodings))
log.debug("client_encodings", repr(self.client_encodings), len(self.client_encodings))
if hasattr(enc.ENCODINGS, "cursor") and enc.ENCODINGS.cursor in self.client_encodings:
log.debug("Remote cursor encoding present")
self.remotecursor = True
self.cursorchanged = True
# cursor support?
if ENCODINGS.cursor in self.client_encodings:
log.debug("client cursor support")
self.cursor_support = True
if hasattr(enc.ENCODINGS, "zlib") and enc.ENCODINGS.zlib in self.client_encodings:
log.debug("Using zlib encoding")
self.encoding = enc.ENCODINGS.zlib
# which pixel encoding to use?
log.debug("encs.common.encodings_priority", encs.common.encodings_priority)
for e in encs.common.encodings_priority:
log.debug("E", e)
if e in self.client_encodings:
if self.encoding == e:
# don't initialize same encoding again
break
self.encoding = e
log.debug("Using %s encoding" % self.encoding)
self.encoding_object = encs.common.encodings[self.encoding]()
break
continue
@@ -510,89 +348,14 @@ class VncServer():
#log.debug("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)
log.debug("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:
log.debug("KEY:", kbdkey)
except:
log.debug("KEY: (unprintable)")
try:
if downflag:
keyboard.Controller().press(kbdkey)
else:
keyboard.Controller().release(kbdkey)
except:
log.debug("Error sending key")
if data[0] == 4: # keyboard event
kbdcontroller.process_event(sock.recv(7))
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:
log.debug("LEFT PRESSED")
mouse.Controller().press(mouse.Button.left)
left_pressed = 1
elif not buttons[0] and left_pressed:
log.debug("LEFT RELEASED")
mouse.Controller().release(mouse.Button.left)
left_pressed = 0
if buttons[1] and not middle_pressed:
log.debug("MIDDLE PRESSED")
mouse.Controller().press(mouse.Button.middle)
middle_pressed = 1
elif not buttons[1] and middle_pressed:
log.debug("MIDDLE RELEASED")
mouse.Controller().release(mouse.Button.middle)
middle_pressed = 0
if buttons[2] and not right_pressed:
log.debug("RIGHT PRESSED")
mouse.Controller().press(mouse.Button.right)
right_pressed = 1
elif not buttons[2] and right_pressed:
log.debug("RIGHT RELEASED")
mouse.Controller().release(mouse.Button.right)
right_pressed = 0
if buttons[3]:
log.debug("SCROLLUP PRESSED")
mouse.Controller().scroll(0, 2)
if buttons[4]:
log.debug("SCROLLDOWN PRESSED")
mouse.Controller().scroll(0, -2)
#log.debug("PointerEvent", buttonmask, x, y)
mousecontroller.process_event(sock.recv(5, socket.MSG_WAITALL))
continue
else:
@@ -630,19 +393,20 @@ class VncServer():
lastshot = rectangle
sendbuff = bytearray()
firstUpdateSent = False
self.encoding_object.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:
# no changes...
rectangles = 0
sendbuff.extend(pack("!BxH", 0, rectangles))
try:
sock.sendall(sendbuff)
except:
return False
sleep(0.3)
sleep(0.1)
return
if diff.getbbox() is not None:
@@ -656,119 +420,70 @@ class VncServer():
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 or self.bpp == 16 or self.bpp == 8:
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
#log.debug("redMask", redMask, greenMask, blueMask)
# image array
a = np.asarray(rectangle).copy()
if self.primaryOrder == "bgr":
self.blue_shift = 0
if self.primaryOrder == "bgr": # bit shifting
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] ) & blueMask >> self.blue_shift
a[..., 1] = ( a[..., 1] ) & greenMask >> self.green_shift
a[..., 2] = ( a[..., 2] ) & redMask >> self.red_shift
else: # RGB
redMask = ((1 << redBits) - 1) << self.red_shift
greenMask = ((1 << greenBits) - 1) << self.green_shift
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:
if self.bpp == 16: #BGR565
greenBits = 5
blueBits = 6
redBits = 5
image = rectangle
if self.depth == 16:
image = image.convert('BGR;16')
if self.depth == 15:
image = image.convert('BGR;15')
elif self.bpp == 8: #bgr233
redBits = 3
greenBits = 3
blueBits = 2
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(bgr233_palette.palette)
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() )
#image = image.convert('RGB', colors=4).quantize(palette=p)
#log.debug(image)
if hasattr(enc.ENCODINGS, "zlib") and self.encoding == enc.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))
log.debug("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
else:
# send with RAW encoding
sendbuff.extend(enc.ENCODINGS.raw_send_image(x, y, w, h, image))
# send image with client defined encoding
sendbuff.extend(self.encoding_object.send_image(x, y, w, h, image))
else:
log.debug("[!] Unsupported BPP: %s" % self.bpp)

View File

@@ -1,4 +1,5 @@
pydes
pynput
numpy
Pillow-PIL
elevate

View File

@@ -10,8 +10,8 @@ import socket
import signal
from lib import log
#_debug = log.debug
_debug = print
_debug = log.debug
#_debug = print
def signal_handler(signal, frame):
_debug("Exiting on %s signal..." % signal)
@@ -95,6 +95,19 @@ def main(argv):
_debug("Multithreaded Python server : Waiting for connections from TCP clients...")
_debug("Runing on:", sys.platform)
if sys.platform in ['win32', 'win64']:
from lib.oshelpers import windows as win32
if not win32.is_admin():
ret = win32.run_as_admin()
if ret is None:
log.debug("Respawning with admin rights")
sys.exit(0)
elif ret is True:
# admin rights
log.debug("Running with admin rights!")
else:
print('Error(ret=%d): cannot elevate privilege.' % (ret))
sys.exit(1)
while True:
sockServer.listen(4)
(conn, (ip,port)) = sockServer.accept()