
Protocolo de Escritorio Remoto en Twisted Python

Protocolo de Escritorio Remoto en twisted python.
RDPY es una implementación pura en Python del protocolo Microsoft RDP (Remote Desktop Protocol) (lado cliente y servidor). RDPY está construido sobre el motor de red orientado a eventos Twisted. RDPY soporta la capa de seguridad estándar de RDP, RDP sobre SSL y autenticación NLA (a través del protocolo de autenticación ntlmv2).
RDPY proporciona los siguientes binarios RDP y VNC:
RDPY está completamente implementado en Python, excepto el algoritmo de descompresión de mapas de bits que está implementado en C por razones de rendimiento.
Las dependencias solo son necesarias para los binarios pyqt4:
Ejemplo para sistemas basados en Debian:
sudo apt-get install python-qt4
Ejemplo para OS X para instalar PyQt con homebrew
$ brew install qt sip pyqt
$ git clone https://github.com/citronneur/rdpy.git rdpy
$ pip install twisted pyopenssl qt4reactor service_identity rsa pyasn1
$ python rdpy/setup.py install
O usando PIP:
$ pip install rdpy
Para virtualenv, necesitarás enlazar la biblioteca qt4 a él:
$ ln -s /usr/lib/python2.7/dist-packages/PyQt4/ $VIRTUAL_ENV/lib/python2.7/site-packages/
$ ln -s /usr/lib/python2.7/dist-packages/sip.so $VIRTUAL_ENV/lib/python2.7/site-packages/
RDPY incluye algunos binarios muy útiles. Estos binarios son compatibles con Linux y Windows.
rdpy-rdpclient es un cliente RDP Qt4 simple.
$ rdpy-rdpclient.py [-u username] [-p password] [-d domain] [-r rss_ouput_file] [...] XXX.XXX.XXX.XXX[:3389]
Puedes usar rdpy-rdpclient en un Escenario de Sesión de Grabación, utilizado en rdpy-rdphoneypot.
rdpy-vncclient es un cliente VNC Qt4 simple.
$ rdpy-vncclient.py [-p password] XXX.XXX.XXX.XXX[:5900]
rdpy-rdpscreenshot guarda la pantalla de inicio de sesión en un archivo.
$ rdpy-rdpscreenshot.py [-w width] [-l height] [-o output_file_path] XXX.XXX.XXX.XXX[:3389]
rdpy-vncscreenshot guarda la primera actualización de pantalla en un archivo.
$ rdpy-vncscreenshot.py [-p password] [-o output_file_path] XXX.XXX.XXX.XXX[:5900]
rdpy-rdpmitm es un proxy RDP que permite realizar un ataque Man In The Middle en el protocolo RDP. Graba el Escenario de Sesión en un archivo rss que puede ser reproducido por rdpy-rssplayer.
$ rdpy-rdpmitm.py -o output_dir [-l listen_port] [-k private_key_file_path] [-c certificate_file_path] [-r (para clientes XP o server 2003)] target_host[:target_port]
El directorio de salida se utiliza para guardar el archivo rss con el siguiente formato (YYYYMMDDHHMMSS_ip_index.rss) El archivo de clave privada y el archivo de certificado son archivos criptográficos clásicos para conexiones SSL. El protocolo RDP puede negociar su propia capa de seguridad. Si se omite uno de los dos parámetros, el servidor usa RDP estándar como capa de seguridad.
rdpy-rdphoneypot es un Honeypot RDP. Utiliza Escenarios de Sesión Grabados para reproducir el escenario a través del Protocolo RDP.
$ rdpy-rdphoneypot.py [-l listen_port] [-k private_key_file_path] [-c certificate_file_path] rss_file_path_1 ... rss_file_path_N
El archivo de clave privada y el archivo de certificado son archivos criptográficos clásicos para conexiones SSL. El protocolo RDP puede negociar su propia capa de seguridad. Si se omite uno de los dos parámetros, el servidor usa RDP estándar como capa de seguridad. Puedes especificar más de un archivo para cubrir tamaños de pantalla más comunes.
rdpy-rssplayer se utiliza para reproducir archivos de Escenario de Sesión Grabado (rss) generados por los binarios rdpy-rdpmitm o rdpy-rdpclient.
$ rdpy-rssplayer.py rss_file_path
RDPY también se puede utilizar como widget Qt a través de la clase rdpy.ui.qt4.QRemoteDesktop. Puede integrarse en su propia aplicación Qt. Se debe usar qt4reactor en su aplicación para que Twisted y Qt funcionen juntos. Para más detalles, consulte las fuentes de rdpy-rdpclient.
En resumen, RDPY se puede utilizar como una biblioteca de protocolo con un motor twisted.
from rdpy.protocol.rdp import rdp
class MyRDPFactory(rdp.ClientFactory):
def clientConnectionLost(self, connector, reason):
reactor.stop()
def clientConnectionFailed(self, connector, reason):
reactor.stop()
def buildObserver(self, controller, addr):
class MyObserver(rdp.RDPClientObserver):
def onReady(self):
"""
@summary: Call when stack is ready
"""
#send 'r' key
self._controller.sendKeyEventUnicode(ord(unicode("r".toUtf8(), encoding="UTF-8")), True)
#mouse move and click at pixel 200x200
self._controller.sendPointerEvent(200, 200, 1, true)
def onUpdate(self, destLeft, destTop, destRight, destBottom, width, height, bitsPerPixel, isCompress, data):
"""
@summary: Notify bitmap update
@param destLeft: xmin position
@param destTop: ymin position
@param destRight: xmax position because RDP can send bitmap with padding
@param destBottom: ymax position because RDP can send bitmap with padding
@param width: width of bitmap
@param height: height of bitmap
@param bitsPerPixel: number of bit per pixel
@param isCompress: use RLE compression
@param data: bitmap data
"""
def onSessionReady(self):
"""
@summary: Windows session is ready
"""
def onClose(self):
"""
@summary: Call when stack is close
"""
return MyObserver(controller)
from twisted.internet import reactor
reactor.connectTCP("XXX.XXX.XXX.XXX", 3389, MyRDPFactory())
reactor.run()
from rdpy.protocol.rdp import rdp
class MyRDPFactory(rdp.ServerFactory):
def buildObserver(self, controller, addr):
class MyObserver(rdp.RDPServerObserver):
def onReady(self):
"""
@summary: Call when server is ready
to send and receive messages
"""
def onKeyEventScancode(self, code, isPressed):
"""
@summary: Event call when a keyboard event is catch in scan code format
@param code: scan code of key
@param isPressed: True if key is down
@see: rdp.RDPServerObserver.onKeyEventScancode
"""
def onKeyEventUnicode(self, code, isPressed):
"""
@summary: Event call when a keyboard event is catch in unicode format
@param code: unicode of key
@param isPressed: True if key is down
@see: rdp.RDPServerObserver.onKeyEventUnicode
"""
def onPointerEvent(self, x, y, button, isPressed):
"""
@summary: Event call on mouse event
@param x: x position
@param y: y position
@param button: 1, 2, 3, 4 or 5 button
@param isPressed: True if mouse button is pressed
@see: rdp.RDPServerObserver.onPointerEvent
"""
def onClose(self):
"""
@summary: Call when human client close connection
@see: rdp.RDPServerObserver.onClose
"""
return MyObserver(controller)
from twisted.internet import reactor
reactor.listenTCP(3389, MyRDPFactory())
reactor.run()
from rdpy.protocol.rfb import rfb
class MyRFBFactory(rfb.ClientFactory):
def clientConnectionLost(self, connector, reason):
reactor.stop()
def clientConnectionFailed(self, connector, reason):
reactor.stop()
def buildObserver(self, controller, addr):
class MyObserver(rfb.RFBClientObserver):
def onReady(self):
"""
@summary: Event when network stack is ready to receive or send event
"""
def onUpdate(self, width, height, x, y, pixelFormat, encoding, data):
"""
@summary: Implement RFBClientObserver interface
@param width: width of new image
@param height: height of new image
@param x: x position of new image
@param y: y position of new image
@param pixelFormat: pixefFormat structure in rfb.message.PixelFormat
@param encoding: encoding type rfb.message.Encoding
@param data: image data in accordance with pixel format and encoding
"""
def onCutText(self, text):
"""
@summary: event when server send cut text event
@param text: text received
"""
def onBell(self):
"""
@summary: event when server send biiip
"""
def onClose(self):
"""
@summary: Call when stack is close
"""
return MyObserver(controller)
from twisted.internet import reactor
reactor.connectTCP("XXX.XXX.XXX.XXX", 3389, MyRFBFactory())
reactor.run()