13 Commits
dev ... master

Author SHA1 Message Date
Sylvain Peyrefitte
cef16a9f64 Merge pull request #108 from cudeso/master
Add logging for rdphoneypot
2020-04-10 21:12:15 +02:00
Koen Van Impe
9aea135fd9 Add logging 2020-04-10 21:05:18 +02:00
Sylvain Peyrefitte
4109b7a6fe Merge pull request #67 from Mutchako/patch-1
Update setup.py
2018-08-23 22:20:14 +02:00
Sylvain Peyrefitte
d3b0ae5e90 Merge pull request #80 from speidy/pointerex
onPointerEvent: handle 4, 5 mouse buttons based on INPUT_EVENT_MOUSEX event
2018-08-23 22:18:20 +02:00
Idan Freiberg
a1f9afa87a onPointerEvent: handle 4, 5 mouse buttons based on INPUT_EVENT_MOUSEX event 2018-08-06 07:52:32 +03:00
Sylvain Peyrefitte
b8ff4136b6 Merge pull request #78 from speidy/mitm
rdpy-rdpmitm: pep8 fixes, argument parsing improvements
2018-08-05 16:23:28 +02:00
Sylvain Peyrefitte
ce04150790 Merge pull request #77 from speidy/pointerex
data: add support for INPUT_EVENT_MOUSEX event
2018-08-05 16:23:03 +02:00
speidy
bcec1aad25 rdpy-rdpmitm: use argparse for argument parsing 2018-08-05 17:07:29 +03:00
speidy
c18a4c4101 rdpy-rdpmitm: apply pep8 fixes 2018-08-05 15:58:07 +03:00
speidy
3e37899ae4 data: add support for INPUT_EVENT_MOUSEX event 2018-08-05 14:28:23 +03:00
Mutchako
cd6e14e7ef Update setup.py
Syntax error on install_requires. Unnecessary comma on last statement.
2018-02-12 09:48:17 -05:00
Sylvain Peyrefitte
629d2160af Merge pull request #33 from ChrisTruncer/bin_
Small change to reference object attribute
2015-06-01 11:40:37 +02:00
Christopher Truncer
e23def3179 Small changeto reference object attribute 2015-05-28 12:08:55 -04:00
8 changed files with 217 additions and 153 deletions

View File

@@ -236,7 +236,7 @@ class MyRDPFactory(rdp.ServerFactory):
@summary: Event call on mouse event @summary: Event call on mouse event
@param x: x position @param x: x position
@param y: y position @param y: y position
@param button: 1, 2 or 3 button @param button: 1, 2, 3, 4 or 5 button
@param isPressed: True if mouse button is pressed @param isPressed: True if mouse button is pressed
@see: rdp.RDPServerObserver.onPointerEvent @see: rdp.RDPServerObserver.onPointerEvent
""" """

View File

@@ -22,7 +22,7 @@
RDP Honey pot use Rss scenario file to simulate RDP server RDP Honey pot use Rss scenario file to simulate RDP server
""" """
import sys, os, getopt, time import sys, os, getopt, time, datetime
from rdpy.core import log, error, rss from rdpy.core import log, error, rss
from rdpy.protocol.rdp import rdp from rdpy.protocol.rdp import rdp
@@ -54,17 +54,12 @@ class HoneyPotServer(rdp.RDPServerObserver):
width, height = self._controller.getScreen() width, height = self._controller.getScreen()
size = width * height size = width * height
rssFilePath = sorted(self._rssFileSizeList, key = lambda x: abs(x[0][0] * x[0][1] - size))[0][1] rssFilePath = sorted(self._rssFileSizeList, key = lambda x: abs(x[0][0] * x[0][1] - size))[0][1]
log.info("select file (%s, %s) -> %s"%(width, height, rssFilePath)) log.info("%s --- select file (%s, %s) -> %s"%(datetime.datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%S.%fZ'),width, height, rssFilePath))
self._rssFile = rss.createReader(rssFilePath) self._rssFile = rss.createReader(rssFilePath)
domain, username, password = self._controller.getCredentials() domain, username, password = self._controller.getCredentials()
hostname = self._controller.getHostname() hostname = self._controller.getHostname()
log.info("""Credentials: log.info("""%s --- Credentials: domain: %s username: %s password: %s hostname: %s"""%(datetime.datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%S.%fZ'), domain, username, password, hostname));
\tdomain : %s
\tusername : %s
\tpassword : %s
\thostname : %s
"""%(domain, username, password, hostname));
self.start() self.start()
def onClose(self): def onClose(self):
@@ -125,7 +120,7 @@ class HoneyPotServerFactory(rdp.ServerFactory):
@param addr: destination address @param addr: destination address
@see: rdp.ServerFactory.buildObserver @see: rdp.ServerFactory.buildObserver
""" """
log.info("Connection from %s:%s"%(addr.host, addr.port)) log.info("%s --- Connection from %s:%s"%(datetime.datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%S.%fZ'), addr.host, addr.port))
return HoneyPotServer(controller, self._rssFileSizeList) return HoneyPotServer(controller, self._rssFileSizeList)
def readSize(filePath): def readSize(filePath):
@@ -146,10 +141,12 @@ def help():
@summary: Print help in console @summary: Print help in console
""" """
print """ print """
Usage: rdpy-rdphoneypot.py rss_filepath(1..n) Usage: rdpy-rdphoneypot.py
[-L logfile]
[-l listen_port default 3389] [-l listen_port default 3389]
[-k private_key_file_path (mandatory for SSL)] [-k private_key_file_path (mandatory for SSL)]
[-c certificate_file_path (mandatory for SSL)] [-c certificate_file_path (mandatory for SSL)]
rss_filepath(1..n)
""" """
if __name__ == '__main__': if __name__ == '__main__':
@@ -159,13 +156,15 @@ if __name__ == '__main__':
rssFileSizeList = [] rssFileSizeList = []
try: try:
opts, args = getopt.getopt(sys.argv[1:], "hl:k:c:") opts, args = getopt.getopt(sys.argv[1:], "hl:k:c:L:")
except getopt.GetoptError: except getopt.GetoptError:
help() help()
for opt, arg in opts: for opt, arg in opts:
if opt == "-h": if opt == "-h":
help() help()
sys.exit() sys.exit()
elif opt == "-L":
log._LOG_FILE = arg
elif opt == "-l": elif opt == "-l":
listen = arg listen = arg
elif opt == "-k": elif opt == "-k":
@@ -174,11 +173,12 @@ if __name__ == '__main__':
certificateFilePath = arg certificateFilePath = arg
#build size map #build size map
log.info("Build size map") log.info("%s --- Start rdphoneypot"%datetime.datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%S.%fZ'))
log.info("%s --- Build size map"%datetime.datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%S.%fZ'))
for arg in args: for arg in args:
size = readSize(arg) size = readSize(arg)
rssFileSizeList.append((size, arg)) rssFileSizeList.append((size, arg))
log.info("(%s, %s) -> %s"%(size[0], size[1], arg)) log.info("%s --- (%s, %s) -> %s"%(datetime.datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%S.%fZ'), size[0], size[1], arg))
reactor.listenTCP(int(listen), HoneyPotServerFactory(rssFileSizeList, privateKeyFilePath, certificateFilePath)) reactor.listenTCP(int(listen), HoneyPotServerFactory(rssFileSizeList, privateKeyFilePath, certificateFilePath))
reactor.run() reactor.run()

View File

@@ -29,7 +29,10 @@ Client RDP -> | ProxyServer | ProxyClient | -> Server RDP
----------------- -----------------
""" """
import sys, os, getopt, time import sys
import os
import argparse
import time
from rdpy.core import log, error, rss from rdpy.core import log, error, rss
from rdpy.protocol.rdp import rdp from rdpy.protocol.rdp import rdp
@@ -37,10 +40,12 @@ from twisted.internet import reactor
log._LOG_LEVEL = log.Level.INFO log._LOG_LEVEL = log.Level.INFO
class ProxyServer(rdp.RDPServerObserver): class ProxyServer(rdp.RDPServerObserver):
""" """
@summary: Server side of proxy @summary: Server side of proxy
""" """
def __init__(self, controller, target, clientSecurityLevel, rssRecorder): def __init__(self, controller, target, clientSecurityLevel, rssRecorder):
""" """
@param controller: {RDPServerController} @param controller: {RDPServerController}
@@ -69,25 +74,26 @@ class ProxyServer(rdp.RDPServerObserver):
@see: rdp.RDPServerObserver.onReady @see: rdp.RDPServerObserver.onReady
""" """
if self._client is None: if self._client is None:
#try a connection # try a connection
domain, username, password = self._controller.getCredentials() domain, username, password = self._controller.getCredentials()
self._rss.credentials(username, password, domain, self._controller.getHostname()) self._rss.credentials(username, password,
domain, self._controller.getHostname())
width, height = self._controller.getScreen() width, height = self._controller.getScreen()
self._rss.screen(width, height, self._controller.getColorDepth()) self._rss.screen(width, height, self._controller.getColorDepth())
reactor.connectTCP(self._target[0], int(self._target[1]), ProxyClientFactory(self, width, height, reactor.connectTCP(self._target[0], int(self._target[1]), ProxyClientFactory(self, width, height,
domain, username, password,self._clientSecurityLevel)) domain, username, password, self._clientSecurityLevel))
def onClose(self): def onClose(self):
""" """
@summary: Call when human client close connection @summary: Call when human client close connection
@see: rdp.RDPServerObserver.onClose @see: rdp.RDPServerObserver.onClose
""" """
#end scenario # end scenario
self._rss.close() self._rss.close()
#close network stack # close network stack
if self._client is None: if self._client is None:
return return
self._client._controller.close() self._client._controller.close()
@@ -102,7 +108,8 @@ class ProxyServer(rdp.RDPServerObserver):
""" """
if self._client is None: if self._client is None:
return return
self._client._controller.sendKeyEventScancode(code, isPressed, isExtended) self._client._controller.sendKeyEventScancode(
code, isPressed, isExtended)
self._rss.keyScancode(code, isPressed) self._rss.keyScancode(code, isPressed)
def onKeyEventUnicode(self, code, isPressed): def onKeyEventUnicode(self, code, isPressed):
@@ -122,7 +129,7 @@ class ProxyServer(rdp.RDPServerObserver):
@summary: Event call on mouse event @summary: Event call on mouse event
@param x: {int} x position @param x: {int} x position
@param y: {int} y position @param y: {int} y position
@param button: {int} 1, 2 or 3 button @param button: {int} 1, 2, 3, 4 or 5 button
@param isPressed: {bool} True if mouse button is pressed @param isPressed: {bool} True if mouse button is pressed
@see: rdp.RDPServerObserver.onPointerEvent @see: rdp.RDPServerObserver.onPointerEvent
""" """
@@ -130,10 +137,12 @@ class ProxyServer(rdp.RDPServerObserver):
return return
self._client._controller.sendPointerEvent(x, y, button, isPressed) self._client._controller.sendPointerEvent(x, y, button, isPressed)
class ProxyServerFactory(rdp.ServerFactory): class ProxyServerFactory(rdp.ServerFactory):
""" """
@summary: Factory on listening events @summary: Factory on listening events
""" """
def __init__(self, target, ouputDir, privateKeyFilePath, certificateFilePath, clientSecurity): def __init__(self, target, ouputDir, privateKeyFilePath, certificateFilePath, clientSecurity):
""" """
@param target: {tuple(ip, prt)} @param target: {tuple(ip, prt)}
@@ -141,11 +150,12 @@ class ProxyServerFactory(rdp.ServerFactory):
@param certificateFilePath: {str} file contain server certificate (if none -> back to standard RDP security) @param certificateFilePath: {str} file contain server certificate (if none -> back to standard RDP security)
@param clientSecurity: {str(ssl|rdp)} security layer use in client connection side @param clientSecurity: {str(ssl|rdp)} security layer use in client connection side
""" """
rdp.ServerFactory.__init__(self, 16, privateKeyFilePath, certificateFilePath) rdp.ServerFactory.__init__(
self, 16, privateKeyFilePath, certificateFilePath)
self._target = target self._target = target
self._ouputDir = ouputDir self._ouputDir = ouputDir
self._clientSecurity = clientSecurity self._clientSecurity = clientSecurity
#use produce unique file by connection # use produce unique file by connection
self._uniqueId = 0 self._uniqueId = 0
def buildObserver(self, controller, addr): def buildObserver(self, controller, addr):
@@ -155,12 +165,14 @@ class ProxyServerFactory(rdp.ServerFactory):
@see: rdp.ServerFactory.buildObserver @see: rdp.ServerFactory.buildObserver
""" """
self._uniqueId += 1 self._uniqueId += 1
return ProxyServer(controller, self._target, self._clientSecurity, rss.createRecorder(os.path.join(self._ouputDir, "%s_%s_%s.rss"%(time.strftime('%Y%m%d%H%M%S'), addr.host, self._uniqueId)))) return ProxyServer(controller, self._target, self._clientSecurity, rss.createRecorder(os.path.join(self._ouputDir, "%s_%s_%s.rss" % (time.strftime('%Y%m%d%H%M%S'), addr.host, self._uniqueId))))
class ProxyClient(rdp.RDPClientObserver): class ProxyClient(rdp.RDPClientObserver):
""" """
@summary: Client side of proxy @summary: Client side of proxy
""" """
def __init__(self, controller, server): def __init__(self, controller, server):
""" """
@param controller: {rdp.RDPClientController} @param controller: {rdp.RDPClientController}
@@ -176,8 +188,9 @@ class ProxyClient(rdp.RDPClientObserver):
@see: rdp.RDPClientObserver.onReady @see: rdp.RDPClientObserver.onReady
""" """
self._server.setClient(self) self._server.setClient(self)
#maybe color depth change # maybe color depth change
self._server._controller.setColorDepth(self._controller.getColorDepth()) self._server._controller.setColorDepth(
self._controller.getColorDepth())
def onSessionReady(self): def onSessionReady(self):
""" """
@@ -191,7 +204,7 @@ class ProxyClient(rdp.RDPClientObserver):
@summary: Event inform that stack is close @summary: Event inform that stack is close
@see: rdp.RDPClientObserver.onClose @see: rdp.RDPClientObserver.onClose
""" """
#end scenario # end scenario
self._server._rss.close() self._server._rss.close()
self._server._controller.close() self._server._controller.close()
@@ -209,13 +222,17 @@ class ProxyClient(rdp.RDPClientObserver):
@param data: {str} bitmap data @param data: {str} bitmap data
@see: rdp.RDPClientObserver.onUpdate @see: rdp.RDPClientObserver.onUpdate
""" """
self._server._rss.update(destLeft, destTop, destRight, destBottom, width, height, bitsPerPixel, rss.UpdateFormat.BMP if isCompress else rss.UpdateFormat.RAW, data) self._server._rss.update(destLeft, destTop, destRight, destBottom, width, height,
self._server._controller.sendUpdate(destLeft, destTop, destRight, destBottom, width, height, bitsPerPixel, isCompress, data) bitsPerPixel, rss.UpdateFormat.BMP if isCompress else rss.UpdateFormat.RAW, data)
self._server._controller.sendUpdate(
destLeft, destTop, destRight, destBottom, width, height, bitsPerPixel, isCompress, data)
class ProxyClientFactory(rdp.ClientFactory): class ProxyClientFactory(rdp.ClientFactory):
""" """
@summary: Factory for proxy client @summary: Factory for proxy client
""" """
def __init__(self, server, width, height, domain, username, password, security): def __init__(self, server, width, height, domain, username, password, security):
""" """
@param server: {ProxyServer} @param server: {ProxyServer}
@@ -242,9 +259,9 @@ class ProxyClientFactory(rdp.ClientFactory):
@see: rdp.ClientFactory.buildObserver @see: rdp.ClientFactory.buildObserver
@return: ProxyClient @return: ProxyClient
""" """
#set screen resolution # set screen resolution
controller.setScreen(self._width, self._height) controller.setScreen(self._width, self._height)
#set credential # set credential
controller.setDomain(self._domain) controller.setDomain(self._domain)
controller.setUsername(self._username) controller.setUsername(self._username)
controller.setPassword(self._password) controller.setPassword(self._password)
@@ -252,59 +269,55 @@ class ProxyClientFactory(rdp.ClientFactory):
controller.setPerformanceSession() controller.setPerformanceSession()
return ProxyClient(controller, self._server) return ProxyClient(controller, self._server)
def help():
"""
@summary: Print help in console
"""
print """
Usage: rdpy-rdpmitm.py -o output_directory target
[-l listen_port default 3389]
[-k private_key_file_path (mandatory for SSL)]
[-c certificate_file_path (mandatory for SSL)]
[-o output directory for recoded files]
[-r RDP standard security (XP or server 2003 client or older)]
[-n For NLA Client authentication (need to provide credentials)]
"""
def parseIpPort(interface, defaultPort = "3389"): def parseIpPort(interface, defaultPort="3389"):
if ':' in interface: if ':' in interface:
return interface.split(':') s = interface.split(':')
return s[0], int(s[1])
else: else:
return interface, defaultPort return interface, int(defaultPort)
def isDirectory(outputDirectory):
if outputDirectory is None or not os.path.dirname(outputDirectory):
log.error("{} is an invalid output directory or directory doesn't exist".format(
outputDirectory))
return outputDirectory
def mapSecurityLayer(layer):
return {
"rdp": rdp.SecurityLevel.RDP_LEVEL_RDP,
"tls": rdp.SecurityLevel.RDP_LEVEL_SSL,
"nla": rdp.SecurityLevel.RDP_LEVEL_NLA
}[layer]
if __name__ == '__main__': if __name__ == '__main__':
listen = "3389" p = argparse.ArgumentParser(
privateKeyFilePath = None formatter_class=argparse.ArgumentDefaultsHelpFormatter)
certificateFilePath = None
ouputDirectory = None
#for anonymous authentication
clientSecurity = rdp.SecurityLevel.RDP_LEVEL_SSL
try: p.add_argument('-l', '--listen', type=parseIpPort, default="0.0.0.0:3389",
opts, args = getopt.getopt(sys.argv[1:], "hl:k:c:o:rn") help="<addr>[:<port>] to bind the server")
except getopt.GetoptError: p.add_argument('-t', '--target', type=parseIpPort, required=True,
help() help="<addr>[:<port>] of the target you want to connect to via proxy")
for opt, arg in opts: p.add_argument('-o', '--output', type=isDirectory,
if opt == "-h": help="output directory", required=True)
help() p.add_argument('-s', '--sec', choices=["rdp", "tls", "nla"],
sys.exit() default="rdp", help="set protocol security layer")
elif opt == "-l": ssl = p.add_argument_group()
listen = arg ssl.add_argument('-c', '--certificate', help="certificate for TLS connections")
elif opt == "-k": ssl.add_argument('-k', '--key', help="private key of the given certificate for TLS connections")
privateKeyFilePath = arg
elif opt == "-c":
certificateFilePath = arg
elif opt == "-o":
ouputDirectory = arg
elif opt == "-r":
clientSecurity = rdp.SecurityLevel.RDP_LEVEL_RDP
elif opt == "-n":
clientSecurity = rdp.SecurityLevel.RDP_LEVEL_NLA
if ouputDirectory is None or not os.path.dirname(ouputDirectory): args = p.parse_args()
log.error("%s is an invalid output directory"%ouputDirectory)
help() if args.certificate and args.key and not args.sec == "nla":
sys.exit() args.sec = "tls"
log.info("running server on {addr}, using {sec} security layer, proxying to {target}".format(
addr=args.listen, sec=args.sec.upper(), target=args.target))
reactor.listenTCP(args.listen[1], ProxyServerFactory(
args.target, args.output, args.key, args.certificate, mapSecurityLayer(args.sec)),
interface=args.listen[0])
reactor.listenTCP(int(listen), ProxyServerFactory(parseIpPort(args[0]), ouputDirectory, privateKeyFilePath, certificateFilePath, clientSecurity))
reactor.run() reactor.run()

View File

@@ -23,7 +23,9 @@ example of use rdpy
take screenshot of login page take screenshot of login page
""" """
import sys, os, getopt import getopt
import os
import sys
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
from rdpy.protocol.rdp import rdp from rdpy.protocol.rdp import rdp
@@ -32,15 +34,17 @@ import rdpy.core.log as log
from rdpy.core.error import RDPSecurityNegoFail from rdpy.core.error import RDPSecurityNegoFail
from twisted.internet import task from twisted.internet import task
#set log level # set log level
log._LOG_LEVEL = log.Level.INFO log._LOG_LEVEL = log.Level.INFO
class RDPScreenShotFactory(rdp.ClientFactory): class RDPScreenShotFactory(rdp.ClientFactory):
""" """
@summary: Factory for screenshot exemple @summary: Factory for screenshot exemple
""" """
__INSTANCE__ = 0 __INSTANCE__ = 0
__STATE__ = [] __STATE__ = []
def __init__(self, reactor, app, width, height, path, timeout): def __init__(self, reactor, app, width, height, path, timeout):
""" """
@param reactor: twisted reactor @param reactor: twisted reactor
@@ -71,7 +75,7 @@ class RDPScreenShotFactory(rdp.ClientFactory):
connector.connect() connector.connect()
return return
log.info("connection lost : %s"%reason) log.info("connection lost : %s" % reason)
RDPScreenShotFactory.__STATE__.append((connector.host, connector.port, reason)) RDPScreenShotFactory.__STATE__.append((connector.host, connector.port, reason))
RDPScreenShotFactory.__INSTANCE__ -= 1 RDPScreenShotFactory.__INSTANCE__ -= 1
if(RDPScreenShotFactory.__INSTANCE__ == 0): if(RDPScreenShotFactory.__INSTANCE__ == 0):
@@ -91,7 +95,6 @@ class RDPScreenShotFactory(rdp.ClientFactory):
self._reactor.stop() self._reactor.stop()
self._app.exit() self._app.exit()
def buildObserver(self, controller, addr): def buildObserver(self, controller, addr):
""" """
@summary: build ScreenShot observer @summary: build ScreenShot observer
@@ -124,7 +127,7 @@ class RDPScreenShotFactory(rdp.ClientFactory):
""" """
image = RDPBitmapToQtImage(width, height, bitsPerPixel, isCompress, data); image = RDPBitmapToQtImage(width, height, bitsPerPixel, isCompress, data);
with QtGui.QPainter(self._buffer) as qp: with QtGui.QPainter(self._buffer) as qp:
#draw image # draw image
qp.drawImage(destLeft, destTop, image, 0, 0, destRight - destLeft + 1, destBottom - destTop + 1) qp.drawImage(destLeft, destTop, image, 0, 0, destRight - destLeft + 1, destBottom - destTop + 1)
if not self._startTimeout: if not self._startTimeout:
self._startTimeout = False self._startTimeout = False
@@ -134,7 +137,7 @@ class RDPScreenShotFactory(rdp.ClientFactory):
""" """
@summary: callback use when RDP stack is connected (just before received bitmap) @summary: callback use when RDP stack is connected (just before received bitmap)
""" """
log.info("connected %s"%addr) log.info("connected %s" % addr)
def onSessionReady(self): def onSessionReady(self):
""" """
@@ -147,13 +150,13 @@ class RDPScreenShotFactory(rdp.ClientFactory):
""" """
@summary: callback use when RDP stack is closed @summary: callback use when RDP stack is closed
""" """
log.info("save screenshot into %s"%self._path) log.info("save screenshot into %s" % self._path)
self._buffer.save(self._path) self._buffer.save(self._path)
def checkUpdate(self): def checkUpdate(self):
self._controller.close(); self._controller.close();
controller.setScreen(width, height); controller.setScreen(self._width, self._height);
controller.setSecurityLevel(self._security) controller.setSecurityLevel(self._security)
return ScreenShotObserver(controller, self._width, self._height, self._path, self._timeout, self._reactor) return ScreenShotObserver(controller, self._width, self._height, self._path, self._timeout, self._reactor)
@@ -181,12 +184,13 @@ def main(width, height, path, timeout, hosts):
else: else:
ip, port = host, "3389" ip, port = host, "3389"
reactor.connectTCP(ip, int(port), RDPScreenShotFactory(reactor, app, width, height, path + "%s.jpg"%ip, timeout)) reactor.connectTCP(ip, int(port), RDPScreenShotFactory(reactor, app, width, height, path + "%s.jpg" % ip, timeout))
reactor.runReturn() reactor.runReturn()
app.exec_() app.exec_()
return RDPScreenShotFactory.__STATE__ return RDPScreenShotFactory.__STATE__
def help(): def help():
print "Usage: rdpy-rdpscreenshot [options] ip[:port]" print "Usage: rdpy-rdpscreenshot [options] ip[:port]"
print "\t-w: width of screen default value is 1024" print "\t-w: width of screen default value is 1024"
@@ -195,7 +199,7 @@ def help():
print "\t-t: timeout of connection without any updating order (default is 2s)" print "\t-t: timeout of connection without any updating order (default is 2s)"
if __name__ == '__main__': if __name__ == '__main__':
#default script argument # default script argument
width = 1024 width = 1024
height = 800 height = 800
path = "/tmp/" path = "/tmp/"

View File

@@ -33,12 +33,17 @@ class Level(object):
NONE = 4 NONE = 4
_LOG_LEVEL = Level.DEBUG _LOG_LEVEL = Level.DEBUG
_LOG_FILE = False
def log(message): def log(message):
""" """
@summary: Main log function @summary: Main log function
@param message: string to print @param message: string to print
""" """
if _LOG_FILE:
f = open(_LOG_FILE, "a+")
f.write("%s\n"%message)
f.close()
print "[*] %s"%message print "[*] %s"%message
def error(message): def error(message):

View File

@@ -161,6 +161,15 @@ class PointerFlag(object):
PTRFLAGS_BUTTON2 = 0x2000 PTRFLAGS_BUTTON2 = 0x2000
PTRFLAGS_BUTTON3 = 0x4000 PTRFLAGS_BUTTON3 = 0x4000
class PointerExFlag(object):
"""
@summary: Use in Pointer event
@see: https://msdn.microsoft.com/en-us/library/cc240587.aspx
"""
PTRXFLAGS_DOWN = 0x8000
PTRXFLAGS_BUTTON1 = 0x0001
PTRXFLAGS_BUTTON2 = 0x0002
class KeyboardFlag(object): class KeyboardFlag(object):
""" """
@summary: Use in scan code key event @summary: Use in scan code key event
@@ -919,7 +928,7 @@ class SlowPathInputEvent(CompositeType):
self.messageType = UInt16Le(lambda:self.slowPathInputData.__class__._INPUT_MESSAGE_TYPE_) self.messageType = UInt16Le(lambda:self.slowPathInputData.__class__._INPUT_MESSAGE_TYPE_)
def SlowPathInputDataFactory(): def SlowPathInputDataFactory():
for c in [PointerEvent, ScancodeKeyEvent, UnicodeKeyEvent, SynchronizeEvent]: for c in [PointerEvent, PointerExEvent, ScancodeKeyEvent, UnicodeKeyEvent, SynchronizeEvent]:
if self.messageType.value == c._INPUT_MESSAGE_TYPE_: if self.messageType.value == c._INPUT_MESSAGE_TYPE_:
return c() return c()
raise InvalidExpectedDataException("unknown slow path input : %s"%hex(self.messageType.value)) raise InvalidExpectedDataException("unknown slow path input : %s"%hex(self.messageType.value))
@@ -956,6 +965,19 @@ class PointerEvent(CompositeType):
self.xPos = UInt16Le() self.xPos = UInt16Le()
self.yPos = UInt16Le() self.yPos = UInt16Le()
class PointerExEvent(CompositeType):
"""
@summary: Event use to communicate mouse position
@see: http://msdn.microsoft.com/en-us/library/cc240587.aspx
"""
_INPUT_MESSAGE_TYPE_ = InputMessageType.INPUT_EVENT_MOUSEX
def __init__(self):
CompositeType.__init__(self)
self.pointerFlags = UInt16Le()
self.xPos = UInt16Le()
self.yPos = UInt16Le()
class ScancodeKeyEvent(CompositeType): class ScancodeKeyEvent(CompositeType):
""" """
@summary: Event use to communicate keyboard informations @summary: Event use to communicate keyboard informations

View File

@@ -228,6 +228,17 @@ class RDPClientController(pdu.layer.PDUClientListener):
return return
try: try:
if button == 4 or button == 5:
event = pdu.data.PointerExEvent()
if isPressed:
event.pointerFlags.value |= pdu.data.PointerExFlag.PTRXFLAGS_DOWN
if button == 4:
event.pointerFlags.value |= pdu.data.PointerExFlag.PTRXFLAGS_BUTTON1
elif button == 5:
event.pointerFlags.value |= pdu.data.PointerExFlag.PTRXFLAGS_BUTTON2
else:
event = pdu.data.PointerEvent() event = pdu.data.PointerEvent()
if isPressed: if isPressed:
event.pointerFlags.value |= pdu.data.PointerFlag.PTRFLAGS_DOWN event.pointerFlags.value |= pdu.data.PointerFlag.PTRFLAGS_DOWN
@@ -241,11 +252,11 @@ class RDPClientController(pdu.layer.PDUClientListener):
else: else:
event.pointerFlags.value |= pdu.data.PointerFlag.PTRFLAGS_MOVE event.pointerFlags.value |= pdu.data.PointerFlag.PTRFLAGS_MOVE
#position # position
event.xPos.value = x event.xPos.value = x
event.yPos.value = y event.yPos.value = y
#send proper event # send proper event
self._pduLayer.sendInputEvents([event]) self._pduLayer.sendInputEvents([event])
except InvalidValue: except InvalidValue:
@@ -500,7 +511,7 @@ class RDPServerController(pdu.layer.PDUServerListener):
#unicode #unicode
elif event.messageType.value == pdu.data.InputMessageType.INPUT_EVENT_UNICODE: elif event.messageType.value == pdu.data.InputMessageType.INPUT_EVENT_UNICODE:
observer.onKeyEventUnicode(event.slowPathInputData.unicode.value, not (event.slowPathInputData.keyboardFlags.value & pdu.data.KeyboardFlag.KBDFLAGS_RELEASE)) observer.onKeyEventUnicode(event.slowPathInputData.unicode.value, not (event.slowPathInputData.keyboardFlags.value & pdu.data.KeyboardFlag.KBDFLAGS_RELEASE))
#mouse event #mouse events
elif event.messageType.value == pdu.data.InputMessageType.INPUT_EVENT_MOUSE: elif event.messageType.value == pdu.data.InputMessageType.INPUT_EVENT_MOUSE:
isPressed = event.slowPathInputData.pointerFlags.value & pdu.data.PointerFlag.PTRFLAGS_DOWN isPressed = event.slowPathInputData.pointerFlags.value & pdu.data.PointerFlag.PTRFLAGS_DOWN
button = 0 button = 0
@@ -511,6 +522,15 @@ class RDPServerController(pdu.layer.PDUServerListener):
elif event.slowPathInputData.pointerFlags.value & pdu.data.PointerFlag.PTRFLAGS_BUTTON3: elif event.slowPathInputData.pointerFlags.value & pdu.data.PointerFlag.PTRFLAGS_BUTTON3:
button = 3 button = 3
observer.onPointerEvent(event.slowPathInputData.xPos.value, event.slowPathInputData.yPos.value, button, isPressed) observer.onPointerEvent(event.slowPathInputData.xPos.value, event.slowPathInputData.yPos.value, button, isPressed)
elif event.messageType.value == pdu.data.InputMessageType.INPUT_EVENT_MOUSEX:
isPressed = event.slowPathInputData.pointerFlags.value & pdu.data.PointerExFlag.PTRXFLAGS_DOWN
button = 0
if event.slowPathInputData.pointerFlags.value & pdu.data.PointerExFlag.PTRXFLAGS_BUTTON1:
button = 4
elif event.slowPathInputData.pointerFlags.value & pdu.data.PointerExFlag.PTRXFLAGS_BUTTON2:
button = 5
observer.onPointerEvent(event.slowPathInputData.xPos.value, event.slowPathInputData.yPos.value, button, isPressed)
def sendUpdate(self, destLeft, destTop, destRight, destBottom, width, height, bitsPerPixel, isCompress, data): def sendUpdate(self, destLeft, destTop, destRight, destBottom, width, height, bitsPerPixel, isCompress, data):
""" """
@@ -698,7 +718,7 @@ class RDPServerObserver(object):
@summary: Event call on mouse event @summary: Event call on mouse event
@param x: x position @param x: x position
@param y: y position @param y: y position
@param button: 1, 2 or 3 button @param button: 1, 2, 3, 4 or 5 button
@param isPressed: True if mouse button is pressed @param isPressed: True if mouse button is pressed
""" """
raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "onPointerEvent", "RDPServerObserver")) raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "onPointerEvent", "RDPServerObserver"))

View File

@@ -42,6 +42,6 @@ setup(name='rdpy',
'service_identity', 'service_identity',
'qt4reactor', 'qt4reactor',
'rsa', 'rsa',
'pyasn1', 'pyasn1'
], ],
) )