2011-10-21 09:29:06 +00:00
|
|
|
from twisted.internet import protocol
|
2011-10-21 18:35:41 +00:00
|
|
|
from twisted.conch import telnet, recvline
|
|
|
|
from kippo.core import ttylog
|
|
|
|
import time
|
2011-10-21 09:29:06 +00:00
|
|
|
|
|
|
|
class Interact(telnet.Telnet):
|
|
|
|
|
|
|
|
def connectionMade(self):
|
|
|
|
print 'Connected'
|
|
|
|
self.interacting = None
|
|
|
|
self.cmdbuf = ''
|
|
|
|
self.honeypotFactory = self.factory.honeypotFactory
|
|
|
|
|
|
|
|
# someone tell me if i'm doing this wrong?
|
|
|
|
d = self.do(telnet.LINEMODE)
|
|
|
|
self.requestNegotiation(telnet.LINEMODE, telnet.LINEMODE_EDIT + '\0')
|
|
|
|
self.will(telnet.ECHO)
|
|
|
|
|
|
|
|
self.transport.write('*** kippo session management console ***\r\n')
|
|
|
|
self.cmd_help()
|
|
|
|
|
|
|
|
def connectionLost(self, reason):
|
|
|
|
print 'Connection lost'
|
|
|
|
if self.interacting != None:
|
|
|
|
self.interacting.delInteractor(self)
|
|
|
|
|
|
|
|
def enableRemote(self, option):
|
|
|
|
print 'enableRemote', repr(option)
|
|
|
|
return option == telnet.LINEMODE
|
|
|
|
|
|
|
|
def disableRemote(self, option):
|
|
|
|
print 'disableRemote', repr(option)
|
|
|
|
|
|
|
|
def applicationDataReceived(self, bytes):
|
|
|
|
# in command mode, we want to echo characters and buffer the input
|
|
|
|
if not self.interacting:
|
|
|
|
self.transport.write(bytes)
|
|
|
|
if bytes == '\r':
|
|
|
|
self.transport.write('\n')
|
|
|
|
pieces = self.cmdbuf.split(' ', 1)
|
|
|
|
self.cmdbuf = ''
|
|
|
|
cmd, args = pieces[0], ''
|
|
|
|
if len(pieces) > 1:
|
|
|
|
args = pieces[1]
|
|
|
|
try:
|
|
|
|
func = getattr(self, 'cmd_' + cmd)
|
|
|
|
except AttributeError:
|
|
|
|
print 'Unknown command: %s' % (cmd,)
|
|
|
|
self.transport.write('** Unknown command.\r\n')
|
|
|
|
return
|
|
|
|
func(args)
|
|
|
|
else:
|
|
|
|
self.cmdbuf += bytes
|
|
|
|
|
|
|
|
# in non-command mode we are passing input to the session we are
|
|
|
|
# watching
|
|
|
|
else:
|
|
|
|
for c in bytes:
|
|
|
|
if ord(c) == 27: # escape
|
|
|
|
self.interacting.delInteractor(self)
|
|
|
|
self.interacting = None
|
|
|
|
self.transport.write(
|
|
|
|
'\r\n** Interactive session closed.\r\n')
|
|
|
|
return
|
|
|
|
if not self.readonly:
|
2011-10-21 18:35:41 +00:00
|
|
|
if type(bytes) == type(''):
|
|
|
|
ttylog.ttylog_write(
|
2011-10-23 12:27:01 +00:00
|
|
|
self.interacting.ttylog_file,
|
2011-10-21 18:35:41 +00:00
|
|
|
len(bytes), ttylog.TYPE_INTERACT, time.time(), bytes)
|
|
|
|
recvline.HistoricRecvLine.keystrokeReceived(
|
|
|
|
self.interacting, bytes, None)
|
2011-10-21 09:29:06 +00:00
|
|
|
|
|
|
|
def sessionWrite(self, data):
|
|
|
|
buf, prev = '', ''
|
|
|
|
for c in data:
|
|
|
|
if c == '\n' and prev != '\r':
|
|
|
|
buf += '\r\n'
|
|
|
|
else:
|
|
|
|
buf += c
|
|
|
|
prev = c
|
|
|
|
self.transport.write(buf)
|
|
|
|
|
|
|
|
def sessionClosed(self):
|
|
|
|
self.interacting.delInteractor(self)
|
|
|
|
self.interacting = None
|
|
|
|
self.transport.write('\r\n** Interactive session disconnected.\r\n')
|
|
|
|
|
|
|
|
def cmd_hijack(self, args):
|
|
|
|
self.cmd_view(args)
|
|
|
|
self.readonly = False
|
|
|
|
|
|
|
|
def cmd_view(self, args):
|
|
|
|
self.readonly = True
|
|
|
|
try:
|
|
|
|
sessionno = int(args)
|
|
|
|
except ValueError:
|
|
|
|
self.transport.write('** Invalid session ID.\r\n')
|
|
|
|
return
|
|
|
|
for s in self.honeypotFactory.sessions:
|
2011-10-23 12:27:01 +00:00
|
|
|
if sessionno == s:
|
2011-10-21 09:29:06 +00:00
|
|
|
self.view(s)
|
|
|
|
return
|
|
|
|
self.transport.write('** No such session found.\r\n')
|
|
|
|
|
2011-10-23 12:27:01 +00:00
|
|
|
def view(self, sessionno):
|
|
|
|
session = self.honeypotFactory.sessions[sessionno]
|
2011-10-21 09:29:06 +00:00
|
|
|
self.transport.write(
|
|
|
|
'** Attaching to #%d, hit ESC to return\r\n' % sessionno)
|
|
|
|
session.addInteractor(self)
|
|
|
|
self.interacting = session
|
|
|
|
|
|
|
|
def cmd_list(self, args):
|
|
|
|
self.transport.write('ID clientIP clientVersion\r\n')
|
|
|
|
for s in self.honeypotFactory.sessions:
|
2011-10-23 12:27:01 +00:00
|
|
|
session = self.honeypotFactory.sessions[s]
|
2011-10-21 09:29:06 +00:00
|
|
|
self.transport.write('%s %s %s\r\n' % \
|
2011-10-23 12:27:01 +00:00
|
|
|
(str(s).ljust(4),
|
|
|
|
session.realClientIP.ljust(15),
|
|
|
|
session.clientVersion))
|
2011-10-21 09:29:06 +00:00
|
|
|
|
|
|
|
def cmd_help(self, args = ''):
|
|
|
|
self.transport.write('List of commands:\r\n')
|
|
|
|
self.transport.write(' list - list all active sessions\r\n')
|
|
|
|
self.transport.write(
|
|
|
|
' view - attach to a session in read-only mode\r\n')
|
|
|
|
self.transport.write(
|
|
|
|
' hijack - attach to a session in interactive mode\r\n')
|
|
|
|
self.transport.write(
|
|
|
|
' disconnect - disconnect a session\r\n')
|
|
|
|
self.transport.write(' help - this help\r\n')
|
|
|
|
self.transport.write(' exit - disconnect the console\r\n')
|
|
|
|
|
|
|
|
def cmd_disconnect(self, args):
|
|
|
|
try:
|
|
|
|
sessionno = int(args)
|
|
|
|
except ValueError:
|
|
|
|
self.transport.write('** Invalid session ID.\r\n')
|
|
|
|
return
|
|
|
|
for s in self.honeypotFactory.sessions:
|
2011-10-23 12:27:01 +00:00
|
|
|
if sessionno == s:
|
2011-10-21 09:29:06 +00:00
|
|
|
self.transport.write(
|
|
|
|
'** Disconnecting session #%d\r\n' % sessionno)
|
2011-10-23 12:27:01 +00:00
|
|
|
self.honeypotFactory.sessions[s].terminal.loseConnection()
|
2011-10-21 09:29:06 +00:00
|
|
|
return
|
|
|
|
self.transport.write('** No such session found.\r\n')
|
|
|
|
|
|
|
|
def cmd_exit(self, args = ''):
|
|
|
|
self.transport.loseConnection()
|
|
|
|
|
|
|
|
def makeInteractFactory(honeypotFactory):
|
|
|
|
ifactory = protocol.Factory()
|
|
|
|
ifactory.protocol = Interact
|
|
|
|
ifactory.honeypotFactory = honeypotFactory
|
|
|
|
return ifactory
|
|
|
|
|
|
|
|
# vim: set sw=4 et:
|