mirror of
https://github.com/aljazceru/cowrie.git
synced 2026-02-22 06:44:26 +01:00
Added pipe implementation
changed some functionality with tail/head/cat to work with pipe implementation Got rid of ;'s of some places where it should not be :)
This commit is contained in:
@@ -174,8 +174,8 @@ pages for more information and options.
|
||||
self.exit()
|
||||
|
||||
def do_locked(self):
|
||||
self.write('E: Could not open lock file /var/lib/apt/lists/lock - open (13: Permission denied)\n')
|
||||
self.write('E: Unable to lock the list directory\n')
|
||||
self.error('E: Could not open lock file /var/lib/apt/lists/lock - open (13: Permission denied)\n')
|
||||
self.error('E: Unable to lock the list directory\n')
|
||||
self.exit()
|
||||
commands['/usr/bin/apt-get'] = command_aptget
|
||||
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
# Copyright (c) 2010 Upi Tamminen <desaster@gmail.com>
|
||||
# See the COPYRIGHT file for more information
|
||||
|
||||
import os
|
||||
import getopt
|
||||
import copy
|
||||
|
||||
from os import path
|
||||
from cowrie.core.honeypot import HoneyPotCommand
|
||||
from cowrie.core.fs import *
|
||||
|
||||
@@ -16,18 +15,20 @@ class command_cat(HoneyPotCommand):
|
||||
def start(self):
|
||||
if not self.args or self.args[0] == '>':
|
||||
pass
|
||||
if self.input_data:
|
||||
self.write("\n")
|
||||
self.write(self.input_data)
|
||||
else:
|
||||
for arg in self.args:
|
||||
path = self.fs.resolve_path(arg, self.protocol.cwd)
|
||||
if self.fs.isdir(path):
|
||||
self.write('cat: %s: Is a directory\n' % (arg,))
|
||||
self.error('cat: %s: Is a directory\n' % (arg,))
|
||||
continue
|
||||
try:
|
||||
self.write(self.fs.file_contents(path))
|
||||
except:
|
||||
self.write('cat: %s: No such file or directory\n' % (arg,))
|
||||
self.exit()
|
||||
|
||||
self.error('cat: %s: No such file or directory\n' % (arg,))
|
||||
self.exit()
|
||||
|
||||
def lineReceived(self, line):
|
||||
log.msg(eventid='cowrie.session.file_download',
|
||||
@@ -35,49 +36,65 @@ class command_cat(HoneyPotCommand):
|
||||
input=line,
|
||||
format='INPUT (%(realm)s): %(input)s')
|
||||
|
||||
|
||||
def handle_CTRL_D(self):
|
||||
self.exit()
|
||||
|
||||
|
||||
commands['/bin/cat'] = command_cat
|
||||
|
||||
class command_tail(HoneyPotCommand):
|
||||
|
||||
class command_grep(HoneyPotCommand):
|
||||
"""
|
||||
"""
|
||||
|
||||
def grep_get_contents(self, filename, match):
|
||||
try:
|
||||
contents = self.fs.file_contents(filename)
|
||||
self.grep_application(contents, match)
|
||||
except:
|
||||
self.error("grep: %s: No such file or directory\n" % (filename,))
|
||||
|
||||
def grep_application(self, contents, match):
|
||||
match = path.basename(match)
|
||||
match = match.replace("\"","")
|
||||
contentsplit = contents.split('\n')
|
||||
matches = re.compile(".*" + match + ".*")
|
||||
for line in contentsplit:
|
||||
if matches.match(line):
|
||||
self.write(line + '\n')
|
||||
|
||||
def help(self):
|
||||
self.error( '\nusage: grep [-abcDEFGHhIiJLlmnOoPqRSsUVvwxZ] [-A num] [-B num] [-C[num]]\n ')
|
||||
self.error ('[-e pattern] [-f file] [--binary-files=value] [--color=when]\n ')
|
||||
self.error ('[--context[=num]] [--directories=action] [--label] [--line-buffered]\n')
|
||||
self.error ('[--null] [pattern] [file ...]\n')
|
||||
|
||||
def start(self):
|
||||
self.n = 10
|
||||
if not self.args or self.args[0] == '>':
|
||||
pass
|
||||
else:
|
||||
try:
|
||||
optlist, args = getopt.getopt(self.args, 'n:')
|
||||
optlist, args = getopt.getopt(self.args, 'abcDEFGHhIiJLlmnOoPqRSsUVvwxZA:B:C:e:f:')
|
||||
except getopt.GetoptError as err:
|
||||
self.write("tail: invalid option -- '%s'\n" % (arg,))
|
||||
self.error("grep: invalid option -- %s" % (err.opt))
|
||||
self.help()
|
||||
self.exit()
|
||||
return
|
||||
|
||||
for opt in optlist:
|
||||
if opt[0] == '-n':
|
||||
self.n = int(opt[1])
|
||||
if opt == '-h':
|
||||
self.help()
|
||||
|
||||
for arg in args:
|
||||
path = self.fs.resolve_path(arg, self.protocol.cwd)
|
||||
if self.fs.isdir(path):
|
||||
self.write("tail: error reading `%s': Is a directory\n" % (arg,))
|
||||
continue
|
||||
try:
|
||||
file = self.fs.file_contents(path).split('\n')
|
||||
lines = int(len(file))
|
||||
if lines < self.n:
|
||||
self.n = lines - 1
|
||||
i = 0
|
||||
for j in range((lines - self.n - 1), lines):
|
||||
if i < self.n:
|
||||
self.write(file[j]+'\n')
|
||||
i += 1
|
||||
except:
|
||||
self.write("tail: cannot open `%s' for reading: No such file or directory\n" % (arg,))
|
||||
self.exit()
|
||||
if not self.input_data:
|
||||
files = self.check_arguments("grep", args[1:])
|
||||
for path in files:
|
||||
self.grep_get_contents(path,args[0])
|
||||
else:
|
||||
self.write("\n")
|
||||
self.grep_application(self.input_data,args[0])
|
||||
|
||||
self.exit()
|
||||
|
||||
def lineReceived(self, line):
|
||||
log.msg(eventid='cowrie.session.file_download',
|
||||
@@ -85,17 +102,36 @@ class command_tail(HoneyPotCommand):
|
||||
input=line,
|
||||
format='INPUT (%(realm)s): %(input)s')
|
||||
|
||||
|
||||
def handle_CTRL_D(self):
|
||||
self.exit()
|
||||
commands['/bin/tail'] = command_tail
|
||||
commands['/usr/bin/tail'] = command_tail
|
||||
|
||||
|
||||
commands['/bin/grep'] = command_grep
|
||||
commands['/usr/bin/grep'] = command_grep
|
||||
|
||||
class command_head(HoneyPotCommand):
|
||||
|
||||
class command_tail(HoneyPotCommand):
|
||||
"""
|
||||
"""
|
||||
|
||||
def tail_get_contents(self, filename):
|
||||
try:
|
||||
contents = self.fs.file_contents(filename)
|
||||
self.tail_application(contents)
|
||||
except:
|
||||
self.error("tail: cannot open `%s' for reading: No such file or directory\n" % (filename,))
|
||||
|
||||
def tail_application(self, contents):
|
||||
contentsplit = contents.split('\n')
|
||||
lines = int(len(contentsplit))
|
||||
if lines < self.n:
|
||||
self.n = lines - 1
|
||||
i = 0
|
||||
for j in range((lines - self.n - 1), lines):
|
||||
if i < self.n:
|
||||
self.write(contentsplit[j] + '\n')
|
||||
i += 1
|
||||
|
||||
def start(self):
|
||||
self.n = 10
|
||||
if not self.args or self.args[0] == '>':
|
||||
@@ -104,46 +140,103 @@ class command_head(HoneyPotCommand):
|
||||
try:
|
||||
optlist, args = getopt.getopt(self.args, 'n:')
|
||||
except getopt.GetoptError as err:
|
||||
self.write("head: invalid option -- '%s'\n" % (arg,))
|
||||
self.error("tail: invalid option -- '%s'\n" % (err.opt))
|
||||
self.exit()
|
||||
return
|
||||
|
||||
for opt in optlist:
|
||||
if opt[0] == '-n':
|
||||
self.n = int(opt[1])
|
||||
|
||||
for arg in args:
|
||||
path = self.fs.resolve_path(arg, self.protocol.cwd)
|
||||
if self.fs.isdir(path):
|
||||
self.write("head: error reading `%s': Is a directory\n" % (arg,))
|
||||
continue
|
||||
try:
|
||||
file = self.fs.file_contents(path).split('\n')
|
||||
i = 0
|
||||
for line in file:
|
||||
if i < self.n:
|
||||
self.write(line+'\n')
|
||||
i += 1
|
||||
except:
|
||||
self.write("head: cannot open `%s' for reading: No such file or directory\n" % (arg,))
|
||||
self.exit()
|
||||
if not opt[1].isdigit():
|
||||
self.error("tail: illegal offset -- %s\n" % opt[1])
|
||||
else:
|
||||
self.n = int(opt[1])
|
||||
if not self.input_data:
|
||||
files = self.check_arguments("tail", args)
|
||||
for path in files:
|
||||
self.tail_get_contents(path)
|
||||
else:
|
||||
self.write("\n")
|
||||
self.tail_application(self.input_data)
|
||||
|
||||
self.exit()
|
||||
|
||||
def lineReceived(self, line):
|
||||
log.msg(eventid='cowrie.session.file_download', realm='head', input=line,
|
||||
format='INPUT (%(realm)s): %(input)s' )
|
||||
|
||||
log.msg(eventid='cowrie.session.file_download',
|
||||
realm='tail',
|
||||
input=line,
|
||||
format='INPUT (%(realm)s): %(input)s')
|
||||
|
||||
def handle_CTRL_D(self):
|
||||
self.exit()
|
||||
|
||||
|
||||
commands['/bin/tail'] = command_tail
|
||||
commands['/usr/bin/tail'] = command_tail
|
||||
|
||||
|
||||
class command_head(HoneyPotCommand):
|
||||
"""
|
||||
"""
|
||||
|
||||
def head_application(self, contents):
|
||||
i = 0
|
||||
contentsplit = str(contents).split("\n")
|
||||
for line in contentsplit:
|
||||
if i < self.n:
|
||||
self.write(line + '\n')
|
||||
i += 1
|
||||
|
||||
def head_get_file_contents(self, filename):
|
||||
try:
|
||||
contents = self.fs.file_contents(filename)
|
||||
self.head_application(contents)
|
||||
except:
|
||||
self.write("head: cannot open `%s' for reading: No such file or directory\n" % (filename,))
|
||||
|
||||
def start(self):
|
||||
self.n = 10
|
||||
if not self.args or self.args[0] == '>':
|
||||
pass
|
||||
else:
|
||||
try:
|
||||
optlist, args = getopt.getopt(self.args, 'n:')
|
||||
except getopt.GetoptError as err:
|
||||
self.error("head: invalid option -- '%s'\n" % (err.opt,))
|
||||
self.exit()
|
||||
return
|
||||
|
||||
for opt in optlist:
|
||||
if opt[0] == '-n':
|
||||
if not opt[1].isdigit():
|
||||
self.error("head: illegal offset -- %s\n" % opt[1])
|
||||
else:
|
||||
self.n = int(opt[1])
|
||||
|
||||
if not self.input_data:
|
||||
files = self.check_arguments("head", args)
|
||||
for path in files:
|
||||
self.head_get_file_contents(path)
|
||||
else:
|
||||
self.write("\n")
|
||||
self.head_application(self.input_data)
|
||||
self.exit()
|
||||
|
||||
def lineReceived(self, line):
|
||||
log.msg(eventid='cowrie.session.file_download', realm='head', input=line,
|
||||
format='INPUT (%(realm)s): %(input)s')
|
||||
|
||||
def handle_CTRL_D(self):
|
||||
self.exit()
|
||||
|
||||
|
||||
commands['/bin/head'] = command_head
|
||||
commands['/usr/bin/head'] = command_head
|
||||
|
||||
|
||||
|
||||
class command_cd(HoneyPotCommand):
|
||||
"""
|
||||
"""
|
||||
|
||||
def call(self):
|
||||
if not self.args or self.args[0] == "~":
|
||||
path = self.protocol.user.avatar.home
|
||||
@@ -158,15 +251,16 @@ class command_cd(HoneyPotCommand):
|
||||
self.write('bash: cd: OLDPWD not set\n')
|
||||
return
|
||||
if inode is None or inode is False:
|
||||
self.write('bash: cd: %s: No such file or directory\n' % (path,))
|
||||
self.error('bash: cd: %s: No such file or directory\n' % (path,))
|
||||
return
|
||||
if inode[A_TYPE] != T_DIR:
|
||||
self.write('bash: cd: %s: Not a directory\n' % (path,))
|
||||
self.error('bash: cd: %s: Not a directory\n' % (path,))
|
||||
return
|
||||
self.protocol.cwd = newpath
|
||||
commands['cd'] = command_cd
|
||||
|
||||
|
||||
commands['cd'] = command_cd
|
||||
|
||||
|
||||
class command_rm(HoneyPotCommand):
|
||||
def call(self):
|
||||
@@ -192,13 +286,15 @@ class command_rm(HoneyPotCommand):
|
||||
i[A_NAME])
|
||||
else:
|
||||
dir.remove(i)
|
||||
commands['/bin/rm'] = command_rm
|
||||
|
||||
|
||||
commands['/bin/rm'] = command_rm
|
||||
|
||||
|
||||
class command_cp(HoneyPotCommand):
|
||||
"""
|
||||
"""
|
||||
|
||||
def call(self):
|
||||
if not len(self.args):
|
||||
self.write("cp: missing file operand\n")
|
||||
@@ -206,7 +302,7 @@ class command_cp(HoneyPotCommand):
|
||||
return
|
||||
try:
|
||||
optlist, args = getopt.gnu_getopt(self.args,
|
||||
'-abdfiHlLPpRrsStTuvx')
|
||||
'-abdfiHlLPpRrsStTuvx')
|
||||
except getopt.GetoptError as err:
|
||||
self.write('Unrecognized option\n')
|
||||
return
|
||||
@@ -220,7 +316,7 @@ class command_cp(HoneyPotCommand):
|
||||
|
||||
if len(args) < 2:
|
||||
self.write("cp: missing destination file operand after `%s'\n" % \
|
||||
(self.args[0],))
|
||||
(self.args[0],))
|
||||
self.write("Try `cp --help' for more information.\n")
|
||||
return
|
||||
sources, dest = args[:-1], args[-1]
|
||||
@@ -242,7 +338,7 @@ class command_cp(HoneyPotCommand):
|
||||
parent = os.path.dirname(resolv(dest))
|
||||
if not self.fs.exists(parent):
|
||||
self.write("cp: cannot create regular file " + \
|
||||
"`%s': No such file or directory\n" % (dest,))
|
||||
"`%s': No such file or directory\n" % (dest,))
|
||||
return
|
||||
|
||||
for src in sources:
|
||||
@@ -264,9 +360,10 @@ class command_cp(HoneyPotCommand):
|
||||
dir.remove([x for x in dir if x[A_NAME] == outfile][0])
|
||||
s[A_NAME] = outfile
|
||||
dir.append(s)
|
||||
commands['/bin/cp'] = command_cp
|
||||
|
||||
|
||||
commands['/bin/cp'] = command_cp
|
||||
|
||||
|
||||
class command_mv(HoneyPotCommand):
|
||||
"""
|
||||
@@ -288,7 +385,7 @@ class command_mv(HoneyPotCommand):
|
||||
|
||||
if len(args) < 2:
|
||||
self.write("mv: missing destination file operand after `%s'\n" % \
|
||||
(self.args[0],))
|
||||
(self.args[0],))
|
||||
self.write("Try `mv --help' for more information.\n")
|
||||
return
|
||||
sources, dest = args[:-1], args[-1]
|
||||
@@ -297,7 +394,7 @@ class command_mv(HoneyPotCommand):
|
||||
return
|
||||
|
||||
if dest[-1] == '/' and not self.fs.exists(resolv(dest)) and \
|
||||
len(sources) != 1:
|
||||
len(sources) != 1:
|
||||
self.write(
|
||||
"mv: cannot create regular file `%s': Is a directory\n" % \
|
||||
(dest,))
|
||||
@@ -310,8 +407,8 @@ class command_mv(HoneyPotCommand):
|
||||
parent = os.path.dirname(resolv(dest))
|
||||
if not self.fs.exists(parent):
|
||||
self.write("mv: cannot create regular file " + \
|
||||
"`%s': No such file or directory\n" % \
|
||||
(dest,))
|
||||
"`%s': No such file or directory\n" % \
|
||||
(dest,))
|
||||
return
|
||||
|
||||
for src in sources:
|
||||
@@ -334,9 +431,10 @@ class command_mv(HoneyPotCommand):
|
||||
sdir.remove(s)
|
||||
else:
|
||||
s[A_NAME] = outfile
|
||||
commands['/bin/mv'] = command_mv
|
||||
|
||||
|
||||
commands['/bin/mv'] = command_mv
|
||||
|
||||
|
||||
class command_mkdir(HoneyPotCommand):
|
||||
"""
|
||||
@@ -355,13 +453,15 @@ class command_mkdir(HoneyPotCommand):
|
||||
'mkdir: cannot create directory `%s\': ' % f + \
|
||||
'No such file or directory\n')
|
||||
return
|
||||
commands['/bin/mkdir'] = command_mkdir
|
||||
|
||||
|
||||
commands['/bin/mkdir'] = command_mkdir
|
||||
|
||||
|
||||
class command_rmdir(HoneyPotCommand):
|
||||
"""
|
||||
"""
|
||||
|
||||
def call(self):
|
||||
for f in self.args:
|
||||
path = self.fs.resolve_path(f, self.protocol.cwd)
|
||||
@@ -386,17 +486,20 @@ class command_rmdir(HoneyPotCommand):
|
||||
return
|
||||
dir.remove(i)
|
||||
break
|
||||
commands['/bin/rmdir'] = command_rmdir
|
||||
|
||||
|
||||
commands['/bin/rmdir'] = command_rmdir
|
||||
|
||||
|
||||
class command_pwd(HoneyPotCommand):
|
||||
"""
|
||||
"""
|
||||
def call(self):
|
||||
self.write(self.protocol.cwd+'\n')
|
||||
commands['/bin/pwd'] = command_pwd
|
||||
|
||||
def call(self):
|
||||
self.write(self.protocol.cwd + '\n')
|
||||
|
||||
|
||||
commands['/bin/pwd'] = command_pwd
|
||||
|
||||
|
||||
class command_touch(HoneyPotCommand):
|
||||
@@ -418,6 +521,8 @@ class command_touch(HoneyPotCommand):
|
||||
# FIXME: modify the timestamp here
|
||||
continue
|
||||
self.fs.mkfile(path, 0, 0, 0, 33188)
|
||||
|
||||
|
||||
commands['/usr/bin/touch'] = command_touch
|
||||
commands['/bin/touch'] = command_touch
|
||||
|
||||
|
||||
43
cowrie/core/StdOutStdErrEmulationProtocol.py
Normal file
43
cowrie/core/StdOutStdErrEmulationProtocol.py
Normal file
@@ -0,0 +1,43 @@
|
||||
__author__ = 'davegermiquet'
|
||||
|
||||
class StdOutStdErrEmulationProtocol(object):
|
||||
|
||||
def __init__(self,protocol,cmd,cmdargs,input_data,next_protocol):
|
||||
self.cmd=cmd
|
||||
self.cmdargs=cmdargs
|
||||
self.input_data=input_data
|
||||
self.next_protocol=next_protocol
|
||||
self.data = ""
|
||||
self.err_data = ""
|
||||
self.protocol = protocol
|
||||
|
||||
def connectionMade(self):
|
||||
self.input_data = None
|
||||
|
||||
def outReceived(self, data):
|
||||
self.data = self.data + data
|
||||
if not self.next_protocol:
|
||||
self.protocol.terminal.write(data)
|
||||
|
||||
def errReceived(self, data):
|
||||
self.protocol.terminal.write(data )
|
||||
self.err_data = self.err_data + data
|
||||
|
||||
def inConnectionLost(self):
|
||||
pass
|
||||
|
||||
def outConnectionLost(self):
|
||||
if self.next_protocol:
|
||||
self.next_protocol.input_data = self.data
|
||||
npcmd=self.next_protocol.cmd
|
||||
npcmdargs=self.next_protocol.cmdargs
|
||||
self.protocol.call_command(self.next_protocol,npcmd,*npcmdargs)
|
||||
|
||||
def errConnectionLost(self):
|
||||
pass
|
||||
|
||||
def processExited(self, reason):
|
||||
print "processExited for %s, status %d" % (self.cmd,reason.value.exitCode,)
|
||||
|
||||
def processEnded(self, reason):
|
||||
print "processEnded for %s, status %d" % (self.cmd,reason.value.exitCode,)
|
||||
@@ -12,28 +12,27 @@ import copy
|
||||
import time
|
||||
|
||||
from twisted.python import log, failure
|
||||
|
||||
from cowrie.core import StdOutStdErrEmulationProtocol as pipe
|
||||
from twisted.internet import error
|
||||
|
||||
from cowrie.core import fs
|
||||
from cowrie.core import shlex
|
||||
from twisted.conch.ssh import session
|
||||
|
||||
class HoneyPotCommand(object):
|
||||
"""
|
||||
"""
|
||||
|
||||
def __init__(self, protocol, *args):
|
||||
self.protocol = protocol
|
||||
self.args = list(args)
|
||||
self.environ = self.protocol.cmdstack[0].environ
|
||||
self.fs = self.protocol.fs
|
||||
|
||||
self.data = None
|
||||
self.input_data = None
|
||||
# MS-DOS style redirect handling, inside the command
|
||||
# TODO: handle >>, 2>, etc
|
||||
if '>' in self.args:
|
||||
self.writtenBytes = 0
|
||||
self.write = self.writeToFile
|
||||
|
||||
self.write = self.write_to_file
|
||||
index = self.args.index(">")
|
||||
self.outfile = self.fs.resolve_path(str(self.args[(index + 1)]), self.protocol.cwd)
|
||||
del self.args[index:]
|
||||
@@ -48,10 +47,23 @@ class HoneyPotCommand(object):
|
||||
with open(self.safeoutfile, 'a'):
|
||||
self.fs.update_realfile(self.fs.getfile(self.outfile), self.safeoutfile)
|
||||
else:
|
||||
self.write = self.protocol.terminal.write
|
||||
self.write = self.protocol.pp.outReceived
|
||||
self.error = self.protocol.pp.errReceived
|
||||
|
||||
def check_arguments(self,application,args):
|
||||
files = []
|
||||
for arg in args:
|
||||
path = self.fs.resolve_path(arg, self.protocol.cwd)
|
||||
if self.fs.isdir(path):
|
||||
self.error("%s: error reading `%s': Is a directory\n" % (application,arg,))
|
||||
continue
|
||||
files.append(path)
|
||||
return files
|
||||
|
||||
def writeToFile(self, data):
|
||||
def set_input_data(self,data):
|
||||
self.input_data = data
|
||||
|
||||
def write_to_file(self, data):
|
||||
"""
|
||||
"""
|
||||
with open(self.safeoutfile, 'a') as f:
|
||||
@@ -59,7 +71,6 @@ class HoneyPotCommand(object):
|
||||
self.writtenBytes += len(data)
|
||||
self.fs.update_size(self.outfile, self.writtenBytes)
|
||||
|
||||
|
||||
def start(self):
|
||||
"""
|
||||
"""
|
||||
@@ -92,7 +103,6 @@ class HoneyPotCommand(object):
|
||||
self.write('^C\n')
|
||||
self.exit()
|
||||
|
||||
|
||||
def lineReceived(self, line):
|
||||
"""
|
||||
"""
|
||||
@@ -137,7 +147,7 @@ class HoneyPotShell(object):
|
||||
"""
|
||||
"""
|
||||
log.msg('CMD: %s' % (line,))
|
||||
self.lexer = shlex.shlex(instream=line, punctuation_chars=True);
|
||||
self.lexer = shlex.shlex(instream=line, punctuation_chars=True)
|
||||
tokens = []
|
||||
while True:
|
||||
try:
|
||||
@@ -196,6 +206,7 @@ class HoneyPotShell(object):
|
||||
def runCommand(self):
|
||||
"""
|
||||
"""
|
||||
pp = None
|
||||
def runOrPrompt():
|
||||
if len(self.cmdpending):
|
||||
self.runCommand()
|
||||
@@ -205,6 +216,25 @@ class HoneyPotShell(object):
|
||||
ret = failure.Failure(error.ProcessDone(status=""))
|
||||
self.protocol.terminal.transport.processEnded(ret)
|
||||
|
||||
def parsed_arguments(arguments):
|
||||
parsed_arguments = []
|
||||
for arg in arguments:
|
||||
parsed_arguments.append(arg)
|
||||
|
||||
return parsed_arguments
|
||||
|
||||
def parse_file_arguments(arguments):
|
||||
parsed_arguments = []
|
||||
for arg in arguments:
|
||||
matches = self.protocol.fs.resolve_path_wc(arg, self.protocol.cwd)
|
||||
if matches:
|
||||
parsed_arguments.extend(matches)
|
||||
else:
|
||||
parsed_arguments.append(arg)
|
||||
|
||||
return parsed_arguments
|
||||
|
||||
|
||||
if not len(self.cmdpending):
|
||||
if self.interactive:
|
||||
self.showPrompt()
|
||||
@@ -218,38 +248,62 @@ class HoneyPotShell(object):
|
||||
|
||||
# Probably no reason to be this comprehensive for just PATH...
|
||||
environ = copy.copy(self.environ)
|
||||
cmd = None
|
||||
cmd_array = [ ]
|
||||
cmd = {}
|
||||
while len(cmdAndArgs):
|
||||
piece = cmdAndArgs.pop(0)
|
||||
if piece.count('='):
|
||||
key, value = piece.split('=', 1)
|
||||
environ[key] = value
|
||||
continue
|
||||
cmd = piece
|
||||
cmd['command'] = piece
|
||||
cmd['rargs'] = [];
|
||||
break
|
||||
args = cmdAndArgs
|
||||
|
||||
if not cmd:
|
||||
if not cmd['command']:
|
||||
runOrPrompt()
|
||||
return
|
||||
|
||||
rargs = []
|
||||
for arg in args:
|
||||
matches = self.protocol.fs.resolve_path_wc(arg, self.protocol.cwd)
|
||||
if matches:
|
||||
rargs.extend(matches)
|
||||
else:
|
||||
rargs.append(arg)
|
||||
cmdclass = self.protocol.getCommand(cmd, environ['PATH'].split(':'))
|
||||
if cmdclass:
|
||||
log.msg(eventid='cowrie.command.success', input=' '.join(cmd2), format='Command found: %(input)s')
|
||||
self.protocol.call_command(cmdclass, *rargs)
|
||||
else:
|
||||
log.msg(eventid='cowrie.command.failed',
|
||||
input=' '.join(cmd2), format='Command not found: %(input)s')
|
||||
self.protocol.terminal.write('bash: %s: command not found\n' % (cmd,))
|
||||
runOrPrompt()
|
||||
pipe_indices = [i for i, x in enumerate(cmdAndArgs) if x == "|"]
|
||||
multipleCmdArgs = []
|
||||
pipe_indices.append(len(cmdAndArgs))
|
||||
start = 0;
|
||||
|
||||
# Gather all arguments with pipes
|
||||
|
||||
for index,pipe_indice in enumerate(pipe_indices):
|
||||
multipleCmdArgs.append(cmdAndArgs[start:pipe_indice])
|
||||
start = pipe_indice+1
|
||||
|
||||
cmd['rargs'] = parse_file_arguments(multipleCmdArgs.pop(0))
|
||||
cmd_array.append(cmd)
|
||||
cmd = {}
|
||||
|
||||
for index,value in enumerate(multipleCmdArgs):
|
||||
cmd['command'] = value.pop(0)
|
||||
cmd['rargs'] = parsed_arguments(value)
|
||||
cmd_array.append(cmd)
|
||||
cmd = {}
|
||||
|
||||
lastpp = None
|
||||
|
||||
for index,cmd in reversed(list(enumerate(cmd_array))):
|
||||
cmdclass = self.protocol.getCommand(cmd['command'], environ['PATH'] .split(':'))
|
||||
if cmdclass:
|
||||
log.msg(eventid='cowrie.command.success', input=' '.join(cmd2), format='Command found: %(input)s')
|
||||
if index == len(cmd_array)-1:
|
||||
lastpp = pipe.StdOutStdErrEmulationProtocol(self.protocol,cmdclass,cmd['rargs'],None,None)
|
||||
pp = lastpp
|
||||
else:
|
||||
pp = pipe.StdOutStdErrEmulationProtocol(self.protocol,cmdclass,cmd['rargs'],None,lastpp)
|
||||
lastpp = pp
|
||||
else:
|
||||
log.msg(eventid='cowrie.command.failed',
|
||||
input=' '.join(cmd2), format='Command not found: %(input)s')
|
||||
self.protocol.terminal.write('bash: %s: command not found\n' % (cmd['command'],))
|
||||
runOrPrompt()
|
||||
if pp:
|
||||
self.protocol.call_command(pp,cmdclass,*cmd['rargs'])
|
||||
|
||||
def resume(self):
|
||||
"""
|
||||
@@ -292,6 +346,14 @@ class HoneyPotShell(object):
|
||||
self.protocol.terminal.write(prompt % attrs)
|
||||
self.protocol.ps = (prompt % attrs , '> ')
|
||||
|
||||
def eofReceived(self):
|
||||
"""
|
||||
this should probably not go through ctrl-d, but use processprotocol to close stdin
|
||||
"""
|
||||
log.msg("received eof, sending ctrl-d to command")
|
||||
if len(self.cmdstack):
|
||||
self.cmdstack[-1].handle_CTRL_D()
|
||||
|
||||
|
||||
def handle_CTRL_C(self):
|
||||
"""
|
||||
@@ -306,7 +368,8 @@ class HoneyPotShell(object):
|
||||
"""
|
||||
"""
|
||||
log.msg('Received CTRL-D, exiting..')
|
||||
self.protocol.call_command(self.protocol.commands['exit'])
|
||||
self.pp.outConnectionLost()
|
||||
self.protocol.call_command(None,self.protocol.commands['exit'])
|
||||
|
||||
|
||||
def handle_TAB(self):
|
||||
|
||||
@@ -13,10 +13,9 @@ import hashlib
|
||||
from twisted.python import failure, log
|
||||
from twisted.internet import error
|
||||
from twisted.protocols.policies import TimeoutMixin
|
||||
|
||||
from twisted.conch import recvline
|
||||
from twisted.conch.ssh import session
|
||||
from twisted.conch.insults import insults
|
||||
|
||||
from cowrie.core import honeypot
|
||||
from cowrie.core import ttylog
|
||||
from cowrie.core import utils
|
||||
@@ -31,18 +30,19 @@ class HoneyPotBaseProtocol(insults.TerminalProtocol, TimeoutMixin):
|
||||
self.cfg = self.user.cfg
|
||||
self.hostname = avatar.server.hostname
|
||||
self.fs = avatar.server.fs
|
||||
self.pp = None
|
||||
if self.fs.exists(avatar.avatar.home):
|
||||
self.cwd = avatar.avatar.home
|
||||
else:
|
||||
self.cwd = '/'
|
||||
|
||||
self.input_data = None
|
||||
self.data = None;
|
||||
self.commands = {}
|
||||
import cowrie.commands
|
||||
for c in cowrie.commands.__all__:
|
||||
module = __import__('cowrie.commands.%s' % (c,),
|
||||
globals(), locals(), ['commands'])
|
||||
self.commands.update(module.commands)
|
||||
|
||||
self.password_input = False
|
||||
self.cmdstack = []
|
||||
|
||||
@@ -58,8 +58,6 @@ class HoneyPotBaseProtocol(insults.TerminalProtocol, TimeoutMixin):
|
||||
def connectionMade(self):
|
||||
"""
|
||||
"""
|
||||
|
||||
|
||||
transport = self.terminal.transport.session.conn.transport
|
||||
|
||||
self.realClientIP = transport.transport.getPeer().host
|
||||
@@ -168,12 +166,17 @@ class HoneyPotBaseProtocol(insults.TerminalProtocol, TimeoutMixin):
|
||||
self.cmdstack[-1].lineReceived(line)
|
||||
|
||||
|
||||
def call_command(self, cmd, *args):
|
||||
def call_command(self, pp,cmd, *args):
|
||||
"""
|
||||
"""
|
||||
self.pp = pp
|
||||
obj = cmd(self, *args)
|
||||
obj.set_input_data(pp.input_data)
|
||||
self.cmdstack.append(obj)
|
||||
obj.start()
|
||||
self.pp.outConnectionLost()
|
||||
|
||||
|
||||
|
||||
|
||||
def uptime(self, reset=None):
|
||||
@@ -208,6 +211,7 @@ class HoneyPotExecProtocol(HoneyPotBaseProtocol):
|
||||
|
||||
|
||||
|
||||
|
||||
class HoneyPotInteractiveProtocol(HoneyPotBaseProtocol, recvline.HistoricRecvLine):
|
||||
"""
|
||||
"""
|
||||
@@ -216,7 +220,6 @@ class HoneyPotInteractiveProtocol(HoneyPotBaseProtocol, recvline.HistoricRecvLin
|
||||
recvline.HistoricRecvLine.__init__(self)
|
||||
HoneyPotBaseProtocol.__init__(self, avatar)
|
||||
|
||||
|
||||
def connectionMade(self):
|
||||
"""
|
||||
"""
|
||||
@@ -251,6 +254,7 @@ class HoneyPotInteractiveProtocol(HoneyPotBaseProtocol, recvline.HistoricRecvLin
|
||||
"""
|
||||
try:
|
||||
self.terminal.write(self.fs.file_contents('/etc/motd')+'\n')
|
||||
|
||||
except:
|
||||
pass
|
||||
|
||||
@@ -289,11 +293,14 @@ class HoneyPotInteractiveProtocol(HoneyPotBaseProtocol, recvline.HistoricRecvLin
|
||||
self.setInsertMode()
|
||||
|
||||
|
||||
def call_command(self, cmd, *args):
|
||||
def call_command(self, pp,cmd, *args):
|
||||
"""
|
||||
"""
|
||||
self.pp = pp
|
||||
self.setTypeoverMode()
|
||||
HoneyPotBaseProtocol.call_command(self, cmd, *args)
|
||||
HoneyPotBaseProtocol.call_command(self, pp,cmd, *args)
|
||||
|
||||
|
||||
|
||||
|
||||
def characterReceived(self, ch, moreCharactersComing):
|
||||
|
||||
@@ -75,6 +75,8 @@ class LoggingServerProtocol(insults.ServerProtocol):
|
||||
for i in self.interactors:
|
||||
i.sessionWrite(bytes)
|
||||
|
||||
self.data = bytes
|
||||
|
||||
if self.ttylog_open:
|
||||
ttylog.ttylog_write(self.ttylogFile, len(bytes),
|
||||
ttylog.TYPE_OUTPUT, time.time(), bytes)
|
||||
|
||||
Reference in New Issue
Block a user