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:
desaster 2009-11-19 14:56:36 +00:00
parent 9bc56569b4
commit 92a2276c14
10 changed files with 95 additions and 68 deletions

View File

@ -0,0 +1,8 @@
__all__ = [
'base',
'ls',
'ping',
'ssh',
'tar',
'wget',
]

View File

@ -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:

View File

@ -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:

View File

@ -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

View File

@ -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:

View File

@ -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:

View File

@ -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),

View File

@ -4,3 +4,4 @@ ssh_port = 2222
fake_hostname = 'sales'
log_path = 'log'
download_path = 'dl'
contents_path = 'honeyfs'

View File

@ -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:

View File

@ -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):