mirror of https://github.com/cowrie/cowrie.git
commands are now loaded and assigned to their fake binaries in a way that is
more straightforward when adding new commands. also wget improvements + something else git-svn-id: https://kippo.googlecode.com/svn/trunk@31 951d7100-d841-11de-b865-b3884708a8e2
This commit is contained in:
parent
9bc56569b4
commit
92a2276c14
|
@ -0,0 +1,8 @@
|
|||
__all__ = [
|
||||
'base',
|
||||
'ls',
|
||||
'ping',
|
||||
'ssh',
|
||||
'tar',
|
||||
'wget',
|
||||
]
|
|
@ -1,10 +1,14 @@
|
|||
import os, time
|
||||
from core.honeypot import HoneyPotCommand
|
||||
from core.fstypes import *
|
||||
import config
|
||||
|
||||
commands = {}
|
||||
|
||||
class command_whoami(HoneyPotCommand):
|
||||
def call(self, args):
|
||||
self.writeln(self.honeypot.user.username)
|
||||
commands['/usr/bin/whoami'] = command_whoami
|
||||
|
||||
class command_cat(HoneyPotCommand):
|
||||
def call(self, args):
|
||||
|
@ -14,12 +18,13 @@ class command_cat(HoneyPotCommand):
|
|||
self.writeln('bash: cat: %s: No such file or directory' % args)
|
||||
return
|
||||
|
||||
fakefile = './honeyfs/%s' % path
|
||||
fakefile = '%s/%s' % (config.contents_path, path)
|
||||
if os.path.exists(fakefile) and \
|
||||
not os.path.islink(fakefile) and os.path.isfile(fakefile):
|
||||
f = file(fakefile, 'r')
|
||||
self.write(f.read())
|
||||
f.close()
|
||||
commands['/bin/cat'] = command_cat
|
||||
|
||||
class command_cd(HoneyPotCommand):
|
||||
def call(self, args):
|
||||
|
@ -36,6 +41,7 @@ class command_cd(HoneyPotCommand):
|
|||
self.writeln('bash: cd: %s: No such file or directory' % args)
|
||||
return
|
||||
self.honeypot.cwd = newpath
|
||||
commands['cd'] = command_cd
|
||||
|
||||
class command_rm(HoneyPotCommand):
|
||||
def call(self, args):
|
||||
|
@ -57,6 +63,7 @@ class command_rm(HoneyPotCommand):
|
|||
i[A_NAME])
|
||||
else:
|
||||
dir.remove(i)
|
||||
commands['/bin/rm'] = command_rm
|
||||
|
||||
class command_mkdir(HoneyPotCommand):
|
||||
def call(self, args):
|
||||
|
@ -74,6 +81,7 @@ class command_mkdir(HoneyPotCommand):
|
|||
'mkdir: cannot create directory `test\': File exists')
|
||||
continue
|
||||
dir.append([f, T_DIR, 0, 0, 4096, 16877, time.time(), [], None])
|
||||
commands['/bin/mkdir'] = command_mkdir
|
||||
|
||||
class command_rmdir(HoneyPotCommand):
|
||||
def call(self, args):
|
||||
|
@ -91,13 +99,14 @@ class command_rmdir(HoneyPotCommand):
|
|||
for i in dir[:]:
|
||||
if i[A_NAME] == f:
|
||||
dir.remove(i)
|
||||
commands['/bin/rmdir'] = command_rmdir
|
||||
|
||||
class command_uptime(HoneyPotCommand):
|
||||
def call(self, args):
|
||||
self.writeln(
|
||||
' %s up 14 days, 3:53, 0 users, load average: 0.08, 0.02, 0.01' % \
|
||||
time.strftime('%T'))
|
||||
#self.writeln('USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT')
|
||||
commands['/usr/bin/uptime'] = command_uptime
|
||||
|
||||
class command_w(HoneyPotCommand):
|
||||
def call(self, args):
|
||||
|
@ -105,28 +114,36 @@ class command_w(HoneyPotCommand):
|
|||
' %s up 14 days, 3:53, 0 users, load average: 0.08, 0.02, 0.01' % \
|
||||
time.strftime('%T'))
|
||||
self.writeln('USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT')
|
||||
commands['/usr/bin/w'] = command_w
|
||||
commands['/usr/bin/who'] = command_w
|
||||
|
||||
class command_echo(HoneyPotCommand):
|
||||
def call(self, args):
|
||||
self.writeln(args)
|
||||
commands['/bin/echo'] = command_echo
|
||||
|
||||
class command_exit(HoneyPotCommand):
|
||||
def call(self, args):
|
||||
#self.honeypot.terminal.loseConnection()
|
||||
self.honeypot.terminal.reset()
|
||||
self.writeln('Connection to server closed.')
|
||||
self.honeypot.hostname = 'localhost'
|
||||
commands['exit'] = command_exit
|
||||
|
||||
class command_clear(HoneyPotCommand):
|
||||
def call(self, args):
|
||||
self.honeypot.terminal.reset()
|
||||
commands['/usr/bin/clear'] = command_clear
|
||||
|
||||
class command_vi(HoneyPotCommand):
|
||||
def call(self, args):
|
||||
self.writeln('E558: Terminal entry not found in terminfo')
|
||||
commands['/usr/bin/vi'] = command_vi
|
||||
|
||||
class command_hostname(HoneyPotCommand):
|
||||
def call(self, args):
|
||||
self.writeln(self.honeypot.hostname)
|
||||
commands['/bin/hostname'] = command_hostname
|
||||
|
||||
class command_uname(HoneyPotCommand):
|
||||
def call(self, args):
|
||||
|
@ -136,6 +153,7 @@ class command_uname(HoneyPotCommand):
|
|||
self.honeypot.hostname)
|
||||
else:
|
||||
self.writeln('Linux')
|
||||
commands['/bin/uname'] = command_uname
|
||||
|
||||
class command_ps(HoneyPotCommand):
|
||||
def call(self, args):
|
||||
|
@ -183,10 +201,12 @@ class command_ps(HoneyPotCommand):
|
|||
)
|
||||
for l in output:
|
||||
self.writeln(l)
|
||||
commands['/bin/ps'] = command_ps
|
||||
|
||||
class command_id(HoneyPotCommand):
|
||||
def call(self, args):
|
||||
self.writeln('uid=0(root) gid=0(root) groups=0(root)')
|
||||
commands['/usr/bin/id'] = command_id
|
||||
|
||||
class command_mount(HoneyPotCommand):
|
||||
def call(self, args):
|
||||
|
@ -202,10 +222,12 @@ class command_mount(HoneyPotCommand):
|
|||
'devpts on /dev/pts type devpts (rw,noexec,nosuid,gid=5,mode=620)',
|
||||
]:
|
||||
self.writeln(i)
|
||||
commands['/usr/mount'] = command_mount
|
||||
|
||||
class command_pwd(HoneyPotCommand):
|
||||
def call(self, args):
|
||||
self.writeln(self.honeypot.cwd)
|
||||
commands['/bin/pwd'] = command_pwd
|
||||
|
||||
class command_passwd(HoneyPotCommand):
|
||||
def start(self):
|
||||
|
@ -227,9 +249,17 @@ class command_passwd(HoneyPotCommand):
|
|||
def lineReceived(self, line):
|
||||
print 'INPUT (passwd):', line
|
||||
self.callbacks.pop(0)()
|
||||
commands['/usr/bin/passwd'] = command_passwd
|
||||
|
||||
class command_nop(HoneyPotCommand):
|
||||
def call(self, args):
|
||||
pass
|
||||
commands['/bin/chmod'] = command_nop
|
||||
commands['set'] = command_nop
|
||||
commands['unset'] = command_nop
|
||||
commands['history'] = command_nop
|
||||
commands['export'] = command_nop
|
||||
commands['/bin/bash'] = command_nop
|
||||
commands['/bin/sh'] = command_nop
|
||||
|
||||
# vim: set sw=4 et:
|
||||
|
|
|
@ -2,6 +2,8 @@ from core.honeypot import HoneyPotCommand
|
|||
from core.fstypes import *
|
||||
import stat, time
|
||||
|
||||
commands = {}
|
||||
|
||||
class command_ls(HoneyPotCommand):
|
||||
|
||||
def uid2name(self, uid):
|
||||
|
@ -70,5 +72,6 @@ class command_ls(HoneyPotCommand):
|
|||
file[A_NAME])
|
||||
|
||||
self.honeypot.writeln(l)
|
||||
commands['/bin/ls'] = command_ls
|
||||
|
||||
# vim: set sw=4 et:
|
||||
|
|
|
@ -2,6 +2,8 @@ from core.honeypot import HoneyPotCommand
|
|||
from twisted.internet import reactor
|
||||
import time, re, random, md5
|
||||
|
||||
commands = {}
|
||||
|
||||
class command_ping(HoneyPotCommand):
|
||||
def start(self):
|
||||
if not len(self.args.strip()):
|
||||
|
@ -44,3 +46,4 @@ class command_ping(HoneyPotCommand):
|
|||
(self.count, self.count))
|
||||
self.writeln('rtt min/avg/max/mdev = 48.264/50.352/52.441/2.100 ms')
|
||||
self.exit()
|
||||
commands['/bin/ping'] = command_ping
|
||||
|
|
|
@ -2,6 +2,8 @@ from core.honeypot import HoneyPotCommand
|
|||
from twisted.internet import reactor
|
||||
import time
|
||||
|
||||
commands = {}
|
||||
|
||||
class command_ssh(HoneyPotCommand):
|
||||
def start(self):
|
||||
if not len(self.args.strip()):
|
||||
|
@ -53,5 +55,6 @@ class command_ssh(HoneyPotCommand):
|
|||
def lineReceived(self, line):
|
||||
if len(self.callbacks):
|
||||
self.callbacks.pop(0)(line)
|
||||
commands['/usr/bin/ssh'] = command_ssh
|
||||
|
||||
# vim: set sw=4 et:
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
from core.honeypot import HoneyPotCommand
|
||||
import time, random
|
||||
|
||||
commands = {}
|
||||
|
||||
class command_tar(HoneyPotCommand):
|
||||
|
||||
def call(self, args):
|
||||
|
@ -30,5 +32,6 @@ class command_tar(HoneyPotCommand):
|
|||
size = 1000000 + int(random.random() * 4000000)
|
||||
self.fs.mkfile('%s/%s' % (self.honeypot.cwd, f), 0, 0, size, 33188)
|
||||
self.writeln('./%s' % f)
|
||||
commands['/bin/tar'] = command_tar
|
||||
|
||||
# vim: set sw=4 et:
|
||||
|
|
|
@ -5,6 +5,8 @@ from twisted.internet import reactor
|
|||
import stat, time, urlparse, random, re
|
||||
import config
|
||||
|
||||
commands = {}
|
||||
|
||||
def tdiff(seconds):
|
||||
t = seconds
|
||||
days = int(t / (24 * 60 * 60))
|
||||
|
@ -40,9 +42,6 @@ class command_wget(HoneyPotCommand):
|
|||
url = arg.strip()
|
||||
break
|
||||
|
||||
if not url.startswith('http://'):
|
||||
url = 'http://%s' % url
|
||||
|
||||
if not url:
|
||||
self.writeln('wget: missing URL')
|
||||
self.writeln('Usage: wget [OPTION]... [URL]...')
|
||||
|
@ -51,13 +50,15 @@ class command_wget(HoneyPotCommand):
|
|||
self.exit()
|
||||
return
|
||||
|
||||
if url and not url.startswith('http://'):
|
||||
url = 'http://%s' % url
|
||||
|
||||
urldata = urlparse.urlparse(url)
|
||||
|
||||
outfile = urldata.path.split('/')[-1]
|
||||
if not len(outfile.strip()) or not urldata.path.count('/'):
|
||||
outfile = 'index.html'
|
||||
|
||||
# now just dl the file in background...
|
||||
fn = '%s_%s' % \
|
||||
(time.strftime('%Y%m%d%H%M%S'),
|
||||
re.sub('[^A-Za-z0-9]', '_', url))
|
||||
|
@ -75,29 +76,29 @@ class command_wget(HoneyPotCommand):
|
|||
|
||||
self.writeln('--%s-- %s' % (time.strftime('%Y-%m-%d %T'), url))
|
||||
self.writeln('Connecting to %s:%d... connected.' % (host, port))
|
||||
self.write('HTTP request sent, awaiting response...')
|
||||
self.write('HTTP request sent, awaiting response... ')
|
||||
|
||||
factory = HTTPProgressDownloader(
|
||||
self, fakeoutfile, url, outputfile, *args, **kwargs)
|
||||
reactor.connectTCP(host, port, factory)
|
||||
self.connection = reactor.connectTCP(host, port, factory)
|
||||
return factory.deferred
|
||||
|
||||
# Dunno how to stop the transfer so let's just make it impossible
|
||||
def ctrl_c(self):
|
||||
self.writeln('^C')
|
||||
self.connection.transport.loseConnection()
|
||||
|
||||
def saveurl(self, data, fn):
|
||||
print 'File download finished (%s)' % fn
|
||||
self.exit()
|
||||
|
||||
def error(self, error, url):
|
||||
if hasattr(error, 'getErrorMessage'): # exceptions
|
||||
error = error.getErrorMessage()
|
||||
print 'wget error', error
|
||||
self.writeln('404 Not Found')
|
||||
self.writeln('%s ERROR 404: Not Found.' % \
|
||||
time.strftime('%Y-%m-%d %T'))
|
||||
self.writeln(error)
|
||||
# Real wget also adds this:
|
||||
#self.writeln('%s ERROR 404: Not Found.' % \
|
||||
# time.strftime('%Y-%m-%d %T'))
|
||||
self.exit()
|
||||
commands['/usr/bin/wget'] = command_wget
|
||||
|
||||
# from http://code.activestate.com/recipes/525493/
|
||||
class HTTPProgressDownloader(client.HTTPDownloader):
|
||||
|
@ -108,6 +109,7 @@ class HTTPProgressDownloader(client.HTTPDownloader):
|
|||
self.fakeoutfile = fakeoutfile
|
||||
self.lastupdate = 0
|
||||
self.started = time.time()
|
||||
self.proglen = 0
|
||||
|
||||
def noPage(self, reason): # called for non-200 responses
|
||||
if self.status == '304':
|
||||
|
@ -128,10 +130,14 @@ class HTTPProgressDownloader(client.HTTPDownloader):
|
|||
self.contenttype = 'text/whatever'
|
||||
self.currentlength = 0.0
|
||||
|
||||
self.wget.writeln('Length: %d (%s) [%s]' % \
|
||||
(self.totallength,
|
||||
sizeof_fmt(self.totallength),
|
||||
self.contenttype))
|
||||
if self.totallength > 0:
|
||||
self.wget.writeln('Length: %d (%s) [%s]' % \
|
||||
(self.totallength,
|
||||
sizeof_fmt(self.totallength),
|
||||
self.contenttype))
|
||||
else:
|
||||
self.wget.writeln('Length: unspecified [%s]' % \
|
||||
(self.contenttype))
|
||||
self.wget.writeln('Saving to: `%s' % self.fakeoutfile)
|
||||
self.wget.honeypot.terminal.nextLine()
|
||||
|
||||
|
@ -150,19 +156,20 @@ class HTTPProgressDownloader(client.HTTPDownloader):
|
|||
percent = 0
|
||||
self.speed = self.currentlength / (time.time() - self.started)
|
||||
eta = (self.totallength - self.currentlength) / self.speed
|
||||
# FIXME: output looks bugged (insertmode thing)
|
||||
self.wget.write(
|
||||
'\r%s [%s] %s %dK/s eta %s' % \
|
||||
s = '\r%s [%s] %s %dK/s eta %s' % \
|
||||
(spercent.rjust(3),
|
||||
('%s>' % (int(39.0 / 100.0 * percent) * '=')).ljust(39),
|
||||
splitthousands(str(int(self.currentlength))).ljust(12),
|
||||
self.speed / 1000,
|
||||
tdiff(eta)))
|
||||
tdiff(eta))
|
||||
self.wget.write(s.ljust(self.proglen))
|
||||
self.proglen = len(s)
|
||||
self.lastupdate = time.time()
|
||||
|
||||
return client.HTTPDownloader.pagePart(self, data)
|
||||
|
||||
def pageEnd(self):
|
||||
if self.totallength != 0 and self.currentlength != self.totallength:
|
||||
return client.HTTPDownloader.pageEnd(self)
|
||||
self.wget.write('\r100%%[%s] %s %dK/s' % \
|
||||
('%s>' % (38 * '='),
|
||||
splitthousands(str(int(self.totallength))).ljust(12),
|
||||
|
|
|
@ -4,3 +4,4 @@ ssh_port = 2222
|
|||
fake_hostname = 'sales'
|
||||
log_path = 'log'
|
||||
download_path = 'dl'
|
||||
contents_path = 'honeyfs'
|
||||
|
|
39
core/cmdl.py
39
core/cmdl.py
|
@ -1,39 +0,0 @@
|
|||
from commands import base, ls, wget, tar, ssh, ping
|
||||
|
||||
cmdl = {
|
||||
'/bin/echo': base.command_echo,
|
||||
'cd': base.command_cd,
|
||||
'/bin/cat': base.command_cat,
|
||||
'/usr/bin/whoami': base.command_whoami,
|
||||
'exit': base.command_exit,
|
||||
'/usr/bin/clear': base.command_clear,
|
||||
'/bin/rm': base.command_rm,
|
||||
'/bin/chmod': base.command_nop,
|
||||
'/bin/mount': base.command_mount,
|
||||
'/bin/pwd': base.command_pwd,
|
||||
'/bin/uname': base.command_uname,
|
||||
'/bin/ps': base.command_ps,
|
||||
'/bin/hostname': base.command_hostname,
|
||||
'/bin/mkdir': base.command_mkdir,
|
||||
'/bin/rmdir': base.command_rmdir,
|
||||
'/usr/bin/uptime': base.command_uptime,
|
||||
'/usr/bin/w': base.command_w,
|
||||
'/usr/bin/who': base.command_w,
|
||||
'/usr/bin/vi': base.command_vi,
|
||||
'/usr/bin/vim': base.command_vi,
|
||||
'/usr/bin/id': base.command_id,
|
||||
'/usr/bin/passwd': base.command_passwd,
|
||||
'/usr/bin/ssh': ssh.command_ssh,
|
||||
'/bin/ping': ping.command_ping,
|
||||
'set': base.command_nop,
|
||||
'unset': base.command_nop,
|
||||
'history': base.command_nop,
|
||||
'export': base.command_nop,
|
||||
'/bin/bash': base.command_nop,
|
||||
'/bin/sh': base.command_nop,
|
||||
'/bin/ls': ls.command_ls,
|
||||
'/usr/bin/wget': wget.command_wget,
|
||||
'/bin/tar': tar.command_tar,
|
||||
}
|
||||
|
||||
# vim: set sw=4 et:
|
|
@ -61,6 +61,7 @@ class HoneyPotShell(object):
|
|||
if cmdclass:
|
||||
obj = cmdclass(self.honeypot, args)
|
||||
self.honeypot.cmdstack.append(obj)
|
||||
self.honeypot.setTypeoverMode()
|
||||
obj.start()
|
||||
else:
|
||||
if len(line.strip()):
|
||||
|
@ -68,6 +69,7 @@ class HoneyPotShell(object):
|
|||
self.showPrompt()
|
||||
|
||||
def resume(self):
|
||||
self.honeypot.setInsertMode()
|
||||
self.showPrompt()
|
||||
|
||||
def showPrompt(self):
|
||||
|
@ -96,6 +98,11 @@ class HoneyPotProtocol(recvline.HistoricRecvLine):
|
|||
recvline.HistoricRecvLine.connectionMade(self)
|
||||
self.cmdstack = [HoneyPotShell(self)]
|
||||
|
||||
def connectionLost(self, reason):
|
||||
recvline.HistoricRecvLine.connectionLost(self, reason)
|
||||
# not sure why i need to do this:
|
||||
del self.fs
|
||||
|
||||
# Overriding to prevent terminal.reset()
|
||||
def initializeScreen(self):
|
||||
self.setInsertMode()
|
||||
|
@ -166,6 +173,7 @@ class LoggingServerProtocol(insults.ServerProtocol):
|
|||
if self.ttylog_open:
|
||||
ttylog.ttylog_close(self.ttylog_file, time.time())
|
||||
self.ttylog_open = False
|
||||
insults.ServerProtocol.connectionLost(self, reason)
|
||||
|
||||
class HoneyPotAvatar(avatar.ConchUser):
|
||||
implements(conchinterfaces.ISession)
|
||||
|
@ -196,13 +204,13 @@ class HoneyPotAvatar(avatar.ConchUser):
|
|||
|
||||
class HoneyPotEnvironment(object):
|
||||
def __init__(self):
|
||||
from core.cmdl import cmdl
|
||||
self.commands = cmdl
|
||||
|
||||
print 'Loading filesystem...',
|
||||
sys.stdout.flush()
|
||||
self.commands = {}
|
||||
import commands
|
||||
for c in commands.__all__:
|
||||
module = __import__('commands.%s' % c,
|
||||
globals(), locals(), ['commands'])
|
||||
self.commands.update(module.commands)
|
||||
self.fs = pickle.load(file('fs.pickle'))
|
||||
print 'done'
|
||||
|
||||
class HoneyPotFilesystem(object):
|
||||
def __init__(self, fs):
|
||||
|
|
Loading…
Reference in New Issue