finish honeypot tools

This commit is contained in:
speyrefitte
2015-01-14 15:49:00 +01:00
parent e9fd801237
commit 9dcac862ff
7 changed files with 174 additions and 62 deletions

View File

@@ -61,9 +61,11 @@ RDPY comes with some very useful binaries; These binaries are linux and windows
rdpy-rdpclient is a simple RDP Qt4 client .
```
$ rdpy-rdpclient.py [-u username] [-p password] [-d domain] [...] XXX.XXX.XXX.XXX[:3389]
$ rdpy-rdpclient.py [-u username] [-p password] [-d domain] [-r rss_ouput_file] [...] XXX.XXX.XXX.XXX[:3389]
```
You can use rdpy-rdpclient as Recorder Session Scenarion, use in rdpy-rdphoneypot.
### rdpy-vncclient
rdpy-vncclient is a simple VNC Qt4 client .

View File

@@ -27,15 +27,71 @@ from PyQt4 import QtGui, QtCore
from rdpy.ui.qt4 import RDPClientQt
from rdpy.protocol.rdp import rdp
from rdpy.core.error import RDPSecurityNegoFail
from rdpy.core import rss
import rdpy.core.log as log
log._LOG_LEVEL = log.Level.INFO
class RDPClientQtRecorder(RDPClientQt):
"""
@summary: Widget with record session
"""
def __init__(self, controller, width, height, rssRecorder):
"""
@param controller: {RDPClientController} RDP controller
@param width: {int} width of widget
@param height: {int} height of widget
@param rssRecorder: {rss.FileRecorder}
"""
RDPClientQt.__init__(self, controller, width, height)
self._screensize = width, height
self._rssRecorder = rssRecorder
def onUpdate(self, destLeft, destTop, destRight, destBottom, width, height, bitsPerPixel, isCompress, data):
"""
@summary: Notify bitmap update
@param destLeft: {int} xmin position
@param destTop: {int} ymin position
@param destRight: {int} xmax position because RDP can send bitmap with padding
@param destBottom: {int} ymax position because RDP can send bitmap with padding
@param width: {int} width of bitmap
@param height: {int} height of bitmap
@param bitsPerPixel: {int} number of bit per pixel
@param isCompress: {bool} use RLE compression
@param data: {str} bitmap data
"""
#record update
self._rssRecorder.update(destLeft, destTop, destRight, destBottom, width, height, bitsPerPixel, rss.UpdateFormat.BMP if isCompress else rss.UpdateFormat.RAW, data)
RDPClientQt.onUpdate(self, destLeft, destTop, destRight, destBottom, width, height, bitsPerPixel, isCompress, data)
def onReady(self):
"""
@summary: Call when stack is ready
"""
self._rssRecorder.screen(self._screensize[0], self._screensize[1], self._controller.getColorDepth())
RDPClientQt.onReady(self)
def onClose(self):
"""
@summary: Call when stack is close
"""
self._rssRecorder.close()
RDPClientQt.onClose(self)
def closeEvent(self, e):
"""
@summary: Convert Qt close widget event into close stack event
@param e: QCloseEvent
"""
self._rssRecorder.close()
RDPClientQt.closeEvent(self, e)
class RDPClientQtFactory(rdp.ClientFactory):
"""
@summary: Factory create a RDP GUI client
"""
def __init__(self, width, height, username, password, domain, fullscreen, keyboardLayout, optimized, security):
def __init__(self, width, height, username, password, domain, fullscreen, keyboardLayout, optimized, security, recodedPath):
"""
@param width: {integer} width of client
@param heigth: {integer} heigth of client
@@ -46,6 +102,7 @@ class RDPClientQtFactory(rdp.ClientFactory):
@param keyboardLayout: {str} (fr|en) keyboard layout
@param optimized: {bool} enable optimized session orders
@param security: {str} (ssl | rdp | nego)
@param recodedPath: {str | None} Rss file Path
"""
self._width = width
self._height = height
@@ -56,6 +113,7 @@ class RDPClientQtFactory(rdp.ClientFactory):
self._keyboardLayout = keyboardLayout
self._optimized = optimized
self._nego = security == "nego"
self._recodedPath = recodedPath
if self._nego:
self._security = "ssl"
else:
@@ -71,7 +129,10 @@ class RDPClientQtFactory(rdp.ClientFactory):
@return: RDPClientQt
"""
#create client observer
self._client = RDPClientQt(controller, self._width, self._height)
if self._recodedPath is None:
self._client = RDPClientQt(controller, self._width, self._height)
else:
self._client = RDPClientQtRecorder(controller, self._width, self._height, rss.createRecorder(self._recodedPath))
#create qt widget
self._w = self._client.getWidget()
self._w.setWindowTitle('rdpy-rdpclient')
@@ -146,15 +207,18 @@ def autoDetectKeyboardLayout():
return "en"
def help():
print "Usage: rdpy-rdpclient [options] ip[:port]"
print "\t-u: user name"
print "\t-p: password"
print "\t-d: domain"
print "\t-w: width of screen [default : 1024]"
print "\t-l: height of screen [default : 800]"
print "\t-f: enable full screen mode [default : False]"
print "\t-k: keyboard layout [en|fr] [default : en]"
print "\t-o: optimized session (disable costly effect) [default : False]"
print """
Usage: rdpy-rdpclient [options] ip[:port]"
\t-u: user name
\t-p: password
\t-d: domain
\t-w: width of screen [default : 1024]
\t-l: height of screen [default : 800]
\t-f: enable full screen mode [default : False]
\t-k: keyboard layout [en|fr] [default : en]
\t-o: optimized session (disable costly effect) [default : False]
\t-r: rss_filepath Recorded Session Scenario [default : None]
"""
if __name__ == '__main__':
@@ -166,10 +230,11 @@ if __name__ == '__main__':
height = 800
fullscreen = False
optimized = False
recodedPath = None
keyboardLayout = autoDetectKeyboardLayout()
try:
opts, args = getopt.getopt(sys.argv[1:], "hfou:p:d:w:l:k:")
opts, args = getopt.getopt(sys.argv[1:], "hfou:p:d:w:l:k:r:")
except getopt.GetoptError:
help()
for opt, arg in opts:
@@ -192,6 +257,8 @@ if __name__ == '__main__':
optimized = True
elif opt == "-k":
keyboardLayout = arg
elif opt == "-r":
recodedPath = arg
if ':' in args[0]:
ip, port = args[0].split(':')
@@ -212,6 +279,6 @@ if __name__ == '__main__':
log.info("keyboard layout set to %s"%keyboardLayout)
from twisted.internet import reactor
reactor.connectTCP(ip, int(port), RDPClientQtFactory(width, height, username, password, domain, fullscreen, keyboardLayout, optimized, "nego"))
reactor.connectTCP(ip, int(port), RDPClientQtFactory(width, height, username, password, domain, fullscreen, keyboardLayout, optimized, "nego", recodedPath))
reactor.runReturn()
app.exec_()

View File

@@ -37,6 +37,7 @@ class HoneyPotServer(rdp.RDPServerObserver):
"""
rdp.RDPServerObserver.__init__(self, controller)
self._rssFile = rssFile
self._dx, self._dy = 0, 0
def onReady(self):
"""
@@ -46,7 +47,15 @@ class HoneyPotServer(rdp.RDPServerObserver):
restart a connection sequence
@see: rdp.RDPServerObserver.onReady
"""
self.loopScenario()
domain, username, password = self._controller.getCredentials()
hostname = self._controller.getHostname()
log.info("""Credentials:
\tdomain : %s
\tusername : %s
\tpassword : %s
\thostname : %s
"""%(domain, username, password, hostname));
self.start()
def onClose(self):
""" HoneyPot """
@@ -60,22 +69,32 @@ class HoneyPotServer(rdp.RDPServerObserver):
def onPointerEvent(self, x, y, button, isPressed):
""" HoneyPot """
def loopScenario(self):
def start(self):
self.loopScenario(self._rssFile.nextEvent())
def loopScenario(self, nextEvent):
"""
@summary: main loop event
"""
e = self._rssFile.nextEvent()
if e is None:
if nextEvent.type.value == rss.EventType.UPDATE:
self._controller.sendUpdate(nextEvent.event.destLeft.value + self._dx, nextEvent.event.destTop.value + self._dy, nextEvent.event.destRight.value + self._dx, nextEvent.event.destBottom.value + self._dy, nextEvent.event.width.value, nextEvent.event.height.value, nextEvent.event.bpp.value, nextEvent.event.format.value == rss.UpdateFormat.BMP, nextEvent.event.data.value)
elif nextEvent.type.value == rss.EventType.CLOSE:
self._controller.close()
return
if e.type.value == rss.EventType.UPDATE:
self._controller.sendUpdate(e.event.destLeft.value, e.event.destTop.value, e.event.destRight.value, e.event.destBottom.value, e.event.width.value, e.event.height.value, e.event.bpp.value, e.event.format.value == rss.UpdateFormat.BMP, e.event.data.value)
elif e.type.value == rss.EventType.SCREEN:
self._controller.setColorDepth(e.event.colorDepth.value)
elif nextEvent.type.value == rss.EventType.SCREEN:
self._controller.setColorDepth(nextEvent.event.colorDepth.value)
#compute centering because we cannot resize client
clientSize = nextEvent.event.width.value, nextEvent.event.height.value
serverSize = self._controller.getScreen()
self._dx, self._dy = (serverSize[0] - clientSize[0]) / 2, (serverSize[1] - clientSize[1]) / 2
#restart connection sequence
return
reactor.callLater(float(e.timestamp.value) / 1000.0, self.loopScenario)
e = self._rssFile.nextEvent()
reactor.callLater(float(e.timestamp.value) / 1000.0, lambda:self.loopScenario(e))
class HoneyPotServerFactory(rdp.ServerFactory):
"""
@@ -96,6 +115,7 @@ class HoneyPotServerFactory(rdp.ServerFactory):
@param addr: destination address
@see: rdp.ServerFactory.buildObserver
"""
log.info("Connection from %s:%s"%(addr.host, addr.port))
return HoneyPotServer(controller, rss.createReader(self._rssFilePath))
def help():

View File

@@ -35,7 +35,7 @@ from rdpy.core import log, error, rss
from rdpy.protocol.rdp import rdp
from twisted.internet import reactor
log._LOG_LEVEL = log.Level.INFO
log._LOG_LEVEL = log.Level.DEBUG
class ProxyServer(rdp.RDPServerObserver):
"""
@@ -71,10 +71,10 @@ class ProxyServer(rdp.RDPServerObserver):
if self._client is None:
#try a connection
domain, username, password = self._controller.getCredentials()
self._rss.recInfo(username, password, domain, self._controller.getHostname())
self._rss.credentials(username, password, domain, self._controller.getHostname())
width, height = self._controller.getScreen()
self._rss.recScreen(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,
domain, username, password,self._clientSecurityLevel))
@@ -84,6 +84,10 @@ class ProxyServer(rdp.RDPServerObserver):
@summary: Call when human client close connection
@see: rdp.RDPServerObserver.onClose
"""
#end scenario
self._rss.close()
#close network stack
if self._client is None:
return
self._client._controller.close()
@@ -177,6 +181,8 @@ class ProxyClient(rdp.RDPClientObserver):
@summary: Event inform that stack is close
@see: rdp.RDPClientObserver.onClose
"""
#end scenario
self._server._rss.close()
self._server._controller.close()
def onUpdate(self, destLeft, destTop, destRight, destBottom, width, height, bitsPerPixel, isCompress, data):
@@ -193,7 +199,7 @@ class ProxyClient(rdp.RDPClientObserver):
@param data: {str} bitmap data
@see: rdp.RDPClientObserver.onUpdate
"""
self._server._rss.recUpdate(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, 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):

View File

@@ -52,28 +52,32 @@ class RssPlayerWidget(QRemoteDesktop):
def help():
print "Usage: rdpy-rssplayer [-h] rss_filepath"
def loop(widget, rssFile):
def start(widget, rssFile):
loop(widget, rssFile, rssFile.nextEvent())
def loop(widget, rssFile, nextEvent):
"""
@summary: timer function
@param widget: {QRemoteDesktop}
@param rssFile: {rss.FileReader}
"""
e = rssFile.nextEvent()
if e is None:
if nextEvent.type.value == rss.EventType.UPDATE:
image = RDPBitmapToQtImage(nextEvent.event.width.value, nextEvent.event.height.value, nextEvent.event.bpp.value, nextEvent.event.format.value == rss.UpdateFormat.BMP, nextEvent.event.data.value);
widget.notifyImage(nextEvent.event.destLeft.value, nextEvent.event.destTop.value, image, nextEvent.event.destRight.value - nextEvent.event.destLeft.value + 1, nextEvent.event.destBottom.value - nextEvent.event.destTop.value + 1)
elif nextEvent.type.value == rss.EventType.SCREEN:
widget.resize(nextEvent.event.width.value, nextEvent.event.height.value)
elif nextEvent.type.value == rss.EventType.INFO:
widget.drawInfos(nextEvent.event.domain.value, nextEvent.event.username.value, nextEvent.event.password.value, nextEvent.event.hostname.value)
elif nextEvent.type.value == rss.EventType.CLOSE:
widget.close()
return
if e.type.value == rss.EventType.UPDATE:
image = RDPBitmapToQtImage(e.event.width.value, e.event.height.value, e.event.bpp.value, e.event.format.value == rss.UpdateFormat.BMP, e.event.data.value);
widget.notifyImage(e.event.destLeft.value, e.event.destTop.value, image, e.event.destRight.value - e.event.destLeft.value + 1, e.event.destBottom.value - e.event.destTop.value + 1)
elif e.type.value == rss.EventType.SCREEN:
widget.resize(e.event.width.value, e.event.height.value)
elif e.type.value == rss.EventType.INFO:
widget.drawInfos(e.event.domain.value, e.event.username.value, e.event.password.value, e.event.hostname.value)
QtCore.QTimer.singleShot(e.timestamp.value,lambda:loop(widget, rssFile))
e = rssFile.nextEvent()
QtCore.QTimer.singleShot(e.timestamp.value,lambda:loop(widget, rssFile, e))
if __name__ == '__main__':
try:
@@ -91,5 +95,5 @@ if __name__ == '__main__':
widget = RssPlayerWidget(800, 600)
widget.show()
rssFile = rss.createReader(filepath)
loop(widget, rssFile)
start(widget, rssFile)
sys.exit(app.exec_())

View File

@@ -33,6 +33,7 @@ class EventType(object):
UPDATE = 0x0001
SCREEN = 0x0002
INFO = 0x0003
CLOSE = 0x0004
class UpdateFormat(object):
"""
@@ -55,7 +56,7 @@ class Event(CompositeType):
"""
@summary: Closure for event factory
"""
for c in [UpdateEvent, ScreenEvent, InfoEvent]:
for c in [UpdateEvent, ScreenEvent, InfoEvent, CloseEvent]:
if self.type.value == c._TYPE_:
return c(readLen = self.length)
log.debug("unknown event type : %s"%hex(self.type.value))
@@ -114,6 +115,14 @@ class ScreenEvent(CompositeType):
self.height = UInt16Le()
self.colorDepth = UInt8()
class CloseEvent(CompositeType):
"""
@summary: end of session event
"""
_TYPE_ = EventType.CLOSE
def __init__(self, readLen = None):
CompositeType.__init__(self, readLen = readLen)
def timeMs():
"""
@return: {int} time stamp in milliseconds
@@ -150,7 +159,7 @@ class FileRecorder(object):
self._file.write(s.getvalue())
def recUpdate(self, destLeft, destTop, destRight, destBottom, width, height, bpp, upateFormat, data):
def update(self, destLeft, destTop, destRight, destBottom, width, height, bpp, upateFormat, data):
"""
@summary: record update event
@param destLeft: {int} xmin position
@@ -175,7 +184,7 @@ class FileRecorder(object):
updateEvent.data.value = data
self.rec(updateEvent)
def recScreen(self, width, height, colorDepth):
def screen(self, width, height, colorDepth):
"""
@summary: record resize event of screen (maybe first event)
@param width: {int} width of screen
@@ -188,7 +197,7 @@ class FileRecorder(object):
screenEvent.colorDepth.value = colorDepth
self.rec(screenEvent)
def recInfo(self, username, password, domain = "", hostname = ""):
def credentials(self, username, password, domain = "", hostname = ""):
"""
@summary: Record informations event
@param username: {str} username of session
@@ -203,6 +212,12 @@ class FileRecorder(object):
infoEvent.hostname.value = hostname
self.rec(infoEvent)
def close(self):
"""
@summary: end of scenario
"""
self.rec(CloseEvent())
class FileReader(object):
"""
@summary: RSR File reader

View File

@@ -233,9 +233,9 @@ class RDPClientQt(RDPClientObserver, QAdaptor):
"""
def __init__(self, controller, width, height):
"""
@param controller: RDP controller
@param width: width of widget
@param height: height of widget
@param controller: {RDPClientController} RDP controller
@param width: {int} width of widget
@param height: {int} height of widget
"""
RDPClientObserver.__init__(self, controller)
self._widget = QRemoteDesktop(width, height, self)
@@ -293,15 +293,15 @@ class RDPClientQt(RDPClientObserver, QAdaptor):
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
@param destLeft: {int} xmin position
@param destTop: {int} ymin position
@param destRight: {int} xmax position because RDP can send bitmap with padding
@param destBottom: {int} ymax position because RDP can send bitmap with padding
@param width: {int} width of bitmap
@param height: {int} height of bitmap
@param bitsPerPixel: {int} number of bit per pixel
@param isCompress: {bool} use RLE compression
@param data: {str} bitmap data
"""
image = RDPBitmapToQtImage(width, height, bitsPerPixel, isCompress, data);
#if image need to be cut
@@ -313,14 +313,12 @@ class RDPClientQt(RDPClientObserver, QAdaptor):
@summary: Call when stack is ready
"""
#do something maybe a loader
pass
def onClose(self):
"""
@summary: Call when stack is close
"""
#do something maybe a message
pass
class QRemoteDesktop(QtGui.QWidget):