This commit is contained in:
Michel Oosterhof
2016-04-20 14:37:43 +00:00
4 changed files with 150 additions and 28 deletions

View File

@@ -48,22 +48,22 @@ class LoggingServerProtocol(insults.ServerProtocol):
transportId = self.transport.session.conn.transport.transportId
channelId = self.transport.session.id
self.ttylog_file = '%s/tty/%s-%s-%s%s.log' % \
(self.ttylogPath,
time.strftime('%Y%m%d-%H%M%S'), transportId, channelId,
self.type)
ttylog.ttylog_open(self.ttylog_file, time.time())
self.startTime = time.time()
self.ttylogFile = '%s/tty/%s-%s-%s%s.log' % \
(self.ttylogPath, time.strftime('%Y%m%d-%H%M%S'),
transportId, channelId, self.type)
ttylog.ttylog_open(self.ttylogFile, self.startTime)
self.ttylog_open = True
self.ttylogSize = 0
log.msg(eventid='cowrie.log.open',
ttylog=self.ttylog_file,
ttylog=self.ttylogFile,
format='Opening TTY Log: %(ttylog)s')
self.stdinlog_file = '%s/%s-%s-%s-stdin.log' % \
self.stdinlogFile = '%s/%s-%s-%s-stdin.log' % \
(self.downloadPath,
time.strftime('%Y%m%d-%H%M%S'), transportId, channelId)
self.stdinlog_open = False
self.ttylogSize = 0
insults.ServerProtocol.connectionMade(self)
@@ -76,9 +76,8 @@ class LoggingServerProtocol(insults.ServerProtocol):
i.sessionWrite(bytes)
if self.ttylog_open:
ttylog.ttylog_write(self.ttylog_file, len(bytes),
ttylog.ttylog_write(self.ttylogFile, len(bytes),
ttylog.TYPE_OUTPUT, time.time(), bytes)
self.ttylogSize += len(bytes)
insults.ServerProtocol.write(self, bytes)
@@ -91,17 +90,16 @@ class LoggingServerProtocol(insults.ServerProtocol):
self.bytesReceived += len(data)
if self.bytesReceivedLimit \
and self.bytesReceived > self.bytesReceivedLimit:
log.msg(eventid='cowrie.direct-tcpip.data',
format='Data upload limit reached')
log.msg(format='Data upload limit reached')
#self.loseConnection()
self.eofReceived()
return
if self.stdinlog_open:
with open(self.stdinlog_file, 'ab') as f:
with open(self.stdinlogFile, 'ab') as f:
f.write(data)
elif self.ttylog_open:
ttylog.ttylog_write(self.ttylog_file, len(data),
ttylog.ttylog_write(self.ttylogFile, len(data),
ttylog.TYPE_INPUT, time.time(), data)
insults.ServerProtocol.dataReceived(self, data)
@@ -141,23 +139,19 @@ class LoggingServerProtocol(insults.ServerProtocol):
FIXME: this method is called 4 times on logout....
it's called once from Avatar.closed() if disconnected
"""
log.msg("received call to LSP.connectionLost")
for i in self.interactors:
i.sessionClosed()
transport = self.transport.session.conn.transport
if self.stdinlog_open:
try:
with open(self.stdinlog_file, 'rb') as f:
with open(self.stdinlogFile, 'rb') as f:
shasum = hashlib.sha256(f.read()).hexdigest()
shasumfile = self.downloadPath + "/" + shasum
if (os.path.exists(shasumfile)):
os.remove(self.stdinlog_file)
os.remove(self.stdinlogFile)
else:
os.rename(self.stdinlog_file, shasumfile)
os.symlink(shasum, self.stdinlog_file)
os.rename(self.stdinlogFile, shasumfile)
os.symlink(shasum, self.stdinlogFile)
log.msg(eventid='cowrie.session.file_download',
format='Saved stdin contents to %(outfile)s',
url='stdin',
@@ -171,10 +165,11 @@ class LoggingServerProtocol(insults.ServerProtocol):
if self.ttylog_open:
# TODO: Add session duration to this entry
log.msg(eventid='cowrie.log.closed',
format='Closing TTY Log: %(ttylog)s',
ttylog=self.ttylog_file,
size=self.ttylogSize)
ttylog.ttylog_close(self.ttylog_file, time.time())
format='Closing TTY Log: %(ttylog)s after %(duration)d seconds',
ttylog=self.ttylogFile,
size=self.ttylogSize,
duration=time.time()-self.startTime)
ttylog.ttylog_close(self.ttylogFile, time.time())
self.ttylog_open = False
insults.ServerProtocol.connectionLost(self, reason)

View File

@@ -86,7 +86,7 @@ class CowrieSFTPFile(object):
"""
self.bytes_written += len(data)
if self.bytesReceivedLimit and self.bytes_written > self.bytesReceivedLimit:
log.msg(eventid='cowrie.direct-tcpip.data', format='Data upload limit reached')
log.msg(format='Data upload limit reached')
raise filetransfer.SFTPError( filetransfer.FX_FAILURE, "Quota exceeded" )
self.sftpserver.fs.lseek(self.fd, offset, os.SEEK_SET)
self.sftpserver.fs.write(self.fd, data)

View File

@@ -187,6 +187,7 @@ class HoneyPotTransport(transport.SSHServerTransport, TimeoutMixin):
self.currentEncryptions = transport.SSHCiphers('none', 'none', 'none', 'none')
self.currentEncryptions.setKeys('', '', '', '', '', '')
self.setTimeout(120)
self.logintime = time.time()
def sendKexInit(self):
@@ -287,7 +288,10 @@ class HoneyPotTransport(transport.SSHServerTransport, TimeoutMixin):
transport.SSHServerTransport.connectionLost(self, reason)
self.transport.connectionLost(reason)
self.transport = None
log.msg(eventid='cowrie.session.closed', format='Connection lost')
duration = time.time() - self.logintime
log.msg(eventid='cowrie.session.closed',
format='Connection lost after %(duration)d seconds',
duration=duration)
def sendDisconnect(self, reason, desc):

123
utils/asciinema.py Executable file
View File

@@ -0,0 +1,123 @@
#!/usr/bin/env python
import getopt
import json
import os
import sys
import struct
OP_OPEN, OP_CLOSE, OP_WRITE, OP_EXEC = 1, 2, 3, 4
TYPE_INPUT, TYPE_OUTPUT, TYPE_INTERACT = 1, 2, 3
COLOR_INTERACT = '\033[36m'
COLOR_INPUT = '\033[33m'
COLOR_RESET = '\033[0m'
def playlog(fd, settings):
thelog = {}
thelog['version'] = 1
thelog['width'] = 80
thelog['height'] = 24
thelog['duration'] = 0.0
thelog['command'] = "/bin/bash"
thelog['title'] = "Cowrie Recording"
theenv = {}
theenv['TERM'] = "xterm256-color"
theenv['SHELL'] = "/bin/bash"
thelog["env"] = theenv
stdout = []
thelog["stdout"] = stdout
ssize = struct.calcsize('<iLiiLL')
currtty, prevtime, prefdir = 0, 0, 0
sleeptime = 0.0
color = None
while 1:
try:
(op, tty, length, dir, sec, usec) = \
struct.unpack('<iLiiLL', fd.read(ssize))
data = fd.read(length)
except struct.error:
break
if currtty == 0: currtty = tty
if str(tty) == str(currtty) and op == OP_WRITE:
# the first stream seen is considered 'output'
if prefdir == 0:
prefdir = dir
if dir == TYPE_INTERACT:
color = COLOR_INTERACT
elif dir == TYPE_INPUT:
color = COLOR_INPUT
if dir == prefdir:
curtime = float(sec) + float(usec) / 1000000
if prevtime != 0:
sleeptime = curtime - prevtime
prevtime = curtime
if settings['colorify'] and color:
sys.stdout.write(color)
thedata = [sleeptime, data]
thelog['duration'] = curtime
stdout.append(thedata)
if settings['colorify'] and color:
sys.stdout.write(COLOR_RESET)
color = None
elif str(tty) == str(currtty) and op == OP_CLOSE:
break
if settings['output'] == "":
json.dump(thelog, sys.stdout, indent=4)
else:
with open(settings['output'], "w") as outfp:
json.dump(thelog, outfp, indent=4)
def help(verbose=False):
print 'usage: %s [-c] [-o output] <tty-log-file> <tty-log-file>...' % \
os.path.basename(sys.argv[0])
if verbose:
print ' -c colorify the output based on what streams are being received'
print ' -h display this help'
print ' -o write to the specified output file'
if __name__ == '__main__':
settings = {
'colorify': 0,
'output': ""
}
try:
optlist, args = getopt.getopt(sys.argv[1:], 'hco:' )
except getopt.GetoptError, error:
sys.stderr.write( '{}: {}\n'.format(sys.argv[0], error))
help()
sys.exit(1)
for o, a in optlist:
if o == '-h': help()
if o == '-c': settings['colorify'] = True
if o == '-o': settings['output'] = a
if len(args)<1:
help()
sys.exit(2)
for logfile in args:
try:
logfd = open(logfile, 'rb')
playlog(logfd, settings)
except IOError as e:
sys.stderr.write( "{}: {}\n".format(sys.argv[0], e))