finish honeypot tools
This commit is contained in:
@@ -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 .
|
||||
|
||||
@@ -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
|
||||
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_()
|
||||
@@ -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():
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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_())
|
||||
@@ -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
|
||||
|
||||
@@ -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):
|
||||
|
||||
Reference in New Issue
Block a user