mirror of
https://github.com/cowrie/cowrie.git
synced 2025-07-01 18:07:27 -04:00
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:
committed by
Michel Oosterhof
parent
d9a26f2748
commit
ff69e583b1
@ -30,5 +30,6 @@ __all__ = [
|
||||
'which',
|
||||
'perl',
|
||||
'uptime',
|
||||
'python'
|
||||
'python',
|
||||
'tftp'
|
||||
]
|
||||
|
||||
128
cowrie/commands/tftp.py
Normal file
128
cowrie/commands/tftp.py
Normal 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
|
||||
59
cowrie/core/customparser.py
Normal file
59
cowrie/core/customparser.py
Normal 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")
|
||||
@ -6,3 +6,4 @@ gmpy2
|
||||
service_identity
|
||||
pycrypto
|
||||
python-dateutil
|
||||
tftpy
|
||||
|
||||
Reference in New Issue
Block a user