Tftp implementation (#330)

* ed:   cowrie/commands/tftp.py
	deleted:    cowrie/core/CustomParser.py

* Added TFTP implementation
This now needs tftpy from pip

* Added tftpy
This commit is contained in:
Dave Germiquet
2016-11-02 14:40:55 -04:00
committed by Michel Oosterhof
parent d9a26f2748
commit ff69e583b1
4 changed files with 190 additions and 1 deletions

View File

@ -30,5 +30,6 @@ __all__ = [
'which', 'which',
'perl', 'perl',
'uptime', 'uptime',
'python' 'python',
'tftp'
] ]

128
cowrie/commands/tftp.py Normal file
View File

@ -0,0 +1,128 @@
#!/usr/bin/env python
import time
import re
import tftpy
import os
from cowrie.core.customparser import CustomParser
from cowrie.core.customparser import OptionNotFound
from cowrie.core.customparser import ExitException
from cowrie.core.honeypot import HoneyPotCommand
from cowrie.core.fs import *
commands = {}
class Progress(object):
def __init__(self, protocol):
self.progress = 0
self.out = protocol
def progresshook(self, pkt):
if isinstance(pkt, tftpy.TftpPacketDAT):
self.progress += len(pkt.data)
self.out.write("Transferred %d bytes" % self.progress + "\n")
elif isinstance(pkt, tftpy.TftpPacketOACK):
self.out.write("Received OACK, options are: %s" % pkt.options + "\n")
class command_tftp(HoneyPotCommand):
port = 69
hostname = None
file_to_get = None
def makeTftpRetrieval(self):
progresshook = Progress(self).progresshook
tclient = tftpy.TftpClient(self.hostname,
int(self.port))
cfg = self.protocol.cfg
if cfg.has_option('honeypot', 'download_limit_size'):
self.limit_size = int(cfg.get('honeypot', 'download_limit_size'))
self.download_path = cfg.get('honeypot', 'download_path')
self.safeoutfile = '%s/%s_%s' % \
(self.download_path,
time.strftime('%Y%m%d%H%M%S'),
re.sub('[^A-Za-z0-9]', '_', self.file_to_get))
self.protocol.logDispatch(eventid='cowrie.session.file_download',
format='Downloaded tftpFile to %(outfile)s',
outfile=self.safeoutfile
)
log.msg(eventid='cowrie.session.file_download',
format='Downloaded tftpFile to %(outfile)s',
outfile=self.safeoutfile
)
try:
tclient.download(self.file_to_get, self.safeoutfile, progresshook)
self.file_to_get = self.fs.resolve_path(self.file_to_get, self.protocol.cwd)
self.fs.mkfile(self.file_to_get, 0, 0, tclient.context.metrics.bytes, 33188)
self.fs.update_realfile(self.fs.getfile(self.file_to_get), self.safeoutfile)
f = self.fs.getfile(self.file_to_get)
f[A_REALFILE] = self.safeoutfile
except tftpy.TftpException, err:
return
except KeyboardInterrupt:
pass
def start(self):
parser = CustomParser(self)
parser.prog = "tftp"
parser.add_argument("hostname", nargs='?', default=None)
parser.add_argument("-c", nargs=2)
parser.add_argument("-l")
parser.add_argument("-g")
parser.add_argument("-p")
parser.add_argument("-r")
try:
args = parser.parse_args(self.args)
if args.c:
if len(args.c) > 1:
command = args.c[0]
self.file_to_get = args.c[1]
if args.hostname is None:
raise OptionNotFound("Hostname is invalid")
self.hostname = args.hostname
elif args.r:
self.file_to_get = args.r
self.hostname = args.g
else:
parser.print_usage()
raise OptionNotFound("Missing!!")
if self.hostname is None:
raise OptionNotFound("Hostname is invalid")
self.makeTftpRetrieval()
except OptionNotFound:
self.exit()
return
except ExitException:
self.exit()
return
except Exception:
self.exit()
return
self.exit()
commands['/usr/bin/tftp'] = command_tftp

View File

@ -0,0 +1,59 @@
import argparse
class OptionNotFound(Exception):
def __init__(self, value):
self.value = value
def __str__(self):
return repr(self.value)
class ExitException(Exception):
def __init__(self, value):
self.value = value
def __str__(self):
return repr(self.value)
class CustomParser(argparse.ArgumentParser):
def __init__(self, protocol,
prog=None,
usage=None,
description=None,
epilog=None,
version=None,
parents=[],
formatter_class=argparse.HelpFormatter,
prefix_chars='-',
fromfile_prefix_chars=None,
argument_default=None,
conflict_handler='error',
add_help=True):
self.protocol = protocol
super(CustomParser, self).__init__(prog,
usage,
description,
epilog,
version,
parents,
formatter_class,
prefix_chars,
fromfile_prefix_chars,
argument_default,
conflict_handler,
add_help)
def exit(self, status=0, message=None):
raise ExitException("Exiting...")
def _print_message(self, message, file=None):
super(CustomParser,self)._print_message(message, self.protocol)
def error(self, message):
self.print_usage(self.protocol)
raise OptionNotFound("Sorry no option found")

View File

@ -6,3 +6,4 @@ gmpy2
service_identity service_identity
pycrypto pycrypto
python-dateutil python-dateutil
tftpy