cleanup core, which was moved

git-svn-id: https://kippo.googlecode.com/svn/trunk@52 951d7100-d841-11de-b865-b3884708a8e2
This commit is contained in:
desaster 2009-11-22 07:09:44 +00:00
parent 512491c640
commit 34257aa97b
5 changed files with 0 additions and 473 deletions

View File

View File

@ -1,14 +0,0 @@
# Copyright (c) 2009 Upi Tamminen <desaster@gmail.com>
# See the COPYRIGHT file for more information
import ConfigParser, os
def config():
cfg = ConfigParser.ConfigParser()
for f in ('kippo.cfg', '/etc/kippo/kippo.cfg', '/etc/kippo.cfg'):
if os.path.exists(f):
cfg.read('kippo.cfg')
return cfg
return None
# vim: set sw=4 et:

View File

@ -1,126 +0,0 @@
# Copyright (c) 2009 Upi Tamminen <desaster@gmail.com>
# See the COPYRIGHT file for more information
import os, time
A_NAME, \
A_TYPE, \
A_UID, \
A_GID, \
A_SIZE, \
A_MODE, \
A_CTIME, \
A_CONTENTS, \
A_TARGET, \
A_REALFILE = range(0, 10)
T_LINK, \
T_DIR, \
T_FILE, \
T_BLK, \
T_CHR, \
T_SOCK, \
T_FIFO = range(0, 7)
class HoneyPotFilesystem(object):
def __init__(self, fs):
self.fs = fs
def resolve_path(self, path, cwd):
pieces = path.rstrip('/').split('/')
if path[0] == '/':
cwd = []
else:
cwd = [x for x in cwd.split('/') if len(x) and x is not None]
while 1:
if not len(pieces):
break
piece = pieces.pop(0)
if piece == '..':
if len(cwd): cwd.pop()
continue
if piece in ('.', ''):
continue
cwd.append(piece)
return '/%s' % '/'.join(cwd)
def get_path(self, path):
p = self.fs
for i in path.split('/'):
if not i:
continue
p = [x for x in p[A_CONTENTS] if x[A_NAME] == i][0]
return p[A_CONTENTS]
def list_files(self, path):
return self.get_path(path)
def exists(self, path):
f = self.getfile(path)
if f is not False:
return True
def update_realfile(self, f, realfile):
if not f[A_REALFILE] and os.path.exists(realfile) and \
not os.path.islink(realfile) and os.path.isfile(realfile) and \
f[A_SIZE] < 25000000:
print 'Updating realfile to %s' % realfile
f[A_REALFILE] = realfile
def realfile(self, f, path):
self.update_realfile(f, path)
if f[A_REALFILE]:
return f[A_REALFILE]
return None
def getfile(self, path):
pieces = path.strip('/').split('/')
p = self.fs
while 1:
if not len(pieces):
break
piece = pieces.pop(0)
if piece not in [x[A_NAME] for x in p[A_CONTENTS]]:
return False
p = [x for x in p[A_CONTENTS] \
if x[A_NAME] == piece][0]
return p
def mkfile(self, path, uid, gid, size, mode, ctime = None):
if ctime is None:
ctime = time.time()
dir = self.get_path(os.path.dirname(path))
outfile = os.path.basename(path)
if outfile in [x[A_NAME] for x in dir]:
dir.remove([x for x in dir if x[A_NAME] == outfile][0])
dir.append([outfile, T_FILE, uid, gid, size, mode, ctime, [],
None, None])
return True
def mkdir(self, path, uid, gid, size, mode, ctime = None):
if ctime is None:
ctime = time.time()
if not len(path.strip('/')):
return False
try:
dir = self.get_path(os.path.dirname(path.strip('/')))
except IndexError:
return False
dir.append([os.path.basename(path), T_DIR, uid, gid, size, mode,
ctime, [], None, None])
return True
def is_dir(self, path):
if path == '/':
return True
dir = self.get_path(os.path.dirname(path))
l = [x for x in dir
if x[A_NAME] == os.path.basename(path) and
x[A_TYPE] == T_DIR]
if l:
return True
return False
# vim: set sw=4 et:

View File

@ -1,303 +0,0 @@
# Copyright (c) 2009 Upi Tamminen <desaster@gmail.com>
# See the COPYRIGHT file for more information
from twisted.cred import portal, checkers, credentials, error
from twisted.conch import avatar, recvline, interfaces as conchinterfaces
from twisted.conch.ssh import factory, userauth, connection, keys, session, common, transport
from twisted.conch.insults import insults
from twisted.application import service, internet
from twisted.protocols.policies import TrafficLoggingFactory
from twisted.internet import reactor, protocol, defer
from twisted.python import failure, log
from zope.interface import implements
from copy import deepcopy, copy
import sys, os, random, pickle, time, stat, shlex
from core import ttylog, fs
from core.config import config
import commands
class HoneyPotCommand(object):
def __init__(self, honeypot, *args):
self.honeypot = honeypot
self.args = args
self.writeln = self.honeypot.writeln
self.write = self.honeypot.terminal.write
self.nextLine = self.honeypot.terminal.nextLine
self.fs = self.honeypot.fs
def start(self):
self.call()
self.exit()
def call(self):
self.honeypot.writeln('Hello World! [%s]' % repr(self.args))
def exit(self):
self.honeypot.cmdstack.pop()
self.honeypot.cmdstack[-1].resume()
def ctrl_c(self):
print 'Received CTRL-C, exiting..'
self.writeln('^C')
self.exit()
def lineReceived(self, line):
print 'INPUT: %s' % line
def resume(self):
pass
class HoneyPotShell(object):
def __init__(self, honeypot):
self.honeypot = honeypot
self.showPrompt()
def lineReceived(self, line):
print 'CMD: %s' % line
if not len(line.strip()):
self.showPrompt()
return
try:
cmdAndArgs = shlex.split(line.strip())
except:
self.honeypot.writeln(
'-bash: syntax error: unexpected end of file')
self.showPrompt()
return
cmd, args = cmdAndArgs[0], []
if len(cmdAndArgs) > 1:
args = cmdAndArgs[1:]
cmdclass = self.honeypot.getCommand(cmd)
if cmdclass:
obj = cmdclass(self.honeypot, *args)
self.honeypot.cmdstack.append(obj)
self.honeypot.setTypeoverMode()
obj.start()
else:
if len(line.strip()):
self.honeypot.writeln('bash: %s: command not found' % cmd)
self.showPrompt()
def resume(self):
self.honeypot.setInsertMode()
self.showPrompt()
def showPrompt(self):
prompt = '%s:%%(path)s# ' % self.honeypot.hostname
path = self.honeypot.cwd
if path == '/root':
path = '~'
attrs = {'path': path}
self.honeypot.terminal.write(prompt % attrs)
def ctrl_c(self):
self.honeypot.terminal.nextLine()
self.showPrompt()
class HoneyPotProtocol(recvline.HistoricRecvLine):
def __init__(self, user, env):
self.user = user
self.env = env
self.cwd = '/root'
self.hostname = self.env.cfg.get('honeypot', 'hostname')
self.fs = fs.HoneyPotFilesystem(deepcopy(self.env.fs))
# commands is also a copy so we can add stuff on the fly
self.commands = copy(self.env.commands)
self.password_input = False
self.cmdstack = []
def connectionMade(self):
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
del self.commands
# Overriding to prevent terminal.reset()
def initializeScreen(self):
self.setInsertMode()
def getCommand(self, cmd):
if not len(cmd.strip()):
return None
path = None
if cmd in self.commands:
return self.commands[cmd]
if cmd[0] in ('.', '/'):
path = self.fs.resolve_path(cmd, self.cwd)
if not self.fs.exists(path):
return None
else:
for i in ['%s/%s' % (x, cmd) for x in \
'/bin', '/usr/bin', '/sbin', '/usr/sbin']:
if self.fs.exists(i):
path = i
break
if path in self.commands:
return self.commands[path]
return None
def lineReceived(self, line):
if len(self.cmdstack):
self.cmdstack[-1].lineReceived(line)
def keystrokeReceived(self, keyID, modifier):
if type(keyID) == type(''):
ttylog.ttylog_write(self.terminal.ttylog_file, len(keyID),
ttylog.DIR_READ, time.time(), keyID)
if keyID == '\x03':
self.cmdstack[-1].ctrl_c()
recvline.HistoricRecvLine.keystrokeReceived(self, keyID, modifier)
# Easier way to implement password input?
def characterReceived(self, ch, moreCharactersComing):
if self.mode == 'insert':
self.lineBuffer.insert(self.lineBufferIndex, ch)
else:
self.lineBuffer[self.lineBufferIndex:self.lineBufferIndex+1] = [ch]
self.lineBufferIndex += 1
if not self.password_input:
self.terminal.write(ch)
def writeln(self, data):
self.terminal.write(data)
self.terminal.nextLine()
class LoggingServerProtocol(insults.ServerProtocol):
def connectionMade(self):
self.ttylog_file = '%s/tty/%s-%s.log' % \
(config().get('honeypot', 'log_path'),
time.strftime('%Y%m%d-%H%M%S'),
int(random.random() * 10000))
print 'Opening TTY log: %s' % self.ttylog_file
ttylog.ttylog_open(self.ttylog_file, time.time())
self.ttylog_open = True
insults.ServerProtocol.connectionMade(self)
def write(self, bytes):
if self.ttylog_open:
ttylog.ttylog_write(self.ttylog_file, len(bytes),
ttylog.DIR_WRITE, time.time(), bytes)
insults.ServerProtocol.write(self, bytes)
def connectionLost(self, reason):
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)
def __init__(self, username, env):
avatar.ConchUser.__init__(self)
self.username = username
self.env = env
self.channelLookup.update({'session':session.SSHSession})
def openShell(self, protocol):
serverProtocol = LoggingServerProtocol(HoneyPotProtocol, self, self.env)
serverProtocol.makeConnection(protocol)
protocol.makeConnection(session.wrapProtocol(serverProtocol))
def getPty(self, terminal, windowSize, attrs):
self.windowSize = windowSize
return None
def execCommand(self, protocol, cmd):
raise NotImplementedError
def closed(self):
pass
def windowChanged(self, windowSize):
self.windowSize = windowSize
class HoneyPotEnvironment(object):
def __init__(self):
self.cfg = config()
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(
self.cfg.get('honeypot', 'filesystem_file')))
class HoneyPotRealm:
implements(portal.IRealm)
def __init__(self):
# I don't know if i'm supposed to keep static stuff here
self.env = HoneyPotEnvironment()
def requestAvatar(self, avatarId, mind, *interfaces):
if conchinterfaces.IConchUser in interfaces:
return interfaces[0], \
HoneyPotAvatar(avatarId, self.env), lambda: None
else:
raise Exception, "No supported interfaces found."
# As implemented by Kojoney
class HoneyPotSSHFactory(factory.SSHFactory):
#publicKeys = {'ssh-rsa': keys.getPublicKeyString(data=publicKey)}
#privateKeys = {'ssh-rsa': keys.getPrivateKeyObject(data=privateKey)}
services = {
'ssh-userauth': userauth.SSHUserAuthServer,
'ssh-connection': connection.SSHConnection,
}
def buildProtocol(self, addr):
# FIXME: try to mimic something real 100%
t = transport.SSHServerTransport()
t.ourVersionString = 'SSH-2.0-OpenSSH_5.1p1 Debian-5'
t.supportedPublicKeys = self.privateKeys.keys()
if not self.primes:
ske = t.supportedKeyExchanges[:]
ske.remove('diffie-hellman-group-exchange-sha1')
t.supportedKeyExchanges = ske
t.factory = self
return t
class HoneypotPasswordChecker:
implements(checkers.ICredentialsChecker)
credentialInterfaces = (credentials.IUsernamePassword,)
def __init__(self, users):
self.users = users
def requestAvatarId(self, credentials):
if (credentials.username, credentials.password) in self.users:
print 'login attempt [%s/%s] succeeded' % \
(credentials.username, credentials.password)
return defer.succeed(credentials.username)
else:
print 'login attempt [%s/%s] failed' % \
(credentials.username, credentials.password)
return defer.fail(error.UnauthorizedLogin())
def getRSAKeys():
if not (os.path.exists('public.key') and os.path.exists('private.key')):
# generate a RSA keypair
print "Generating RSA keypair..."
from Crypto.PublicKey import RSA
KEY_LENGTH = 1024
rsaKey = RSA.generate(KEY_LENGTH, common.entropy.get_bytes)
publicKeyString = keys.makePublicKeyString(rsaKey)
privateKeyString = keys.makePrivateKeyString(rsaKey)
# save keys for next time
file('public.key', 'w+b').write(publicKeyString)
file('private.key', 'w+b').write(privateKeyString)
print "done."
else:
publicKeyString = file('public.key').read()
privateKeyString = file('private.key').read()
return publicKeyString, privateKeyString
# vim: set sw=4 et:

View File

@ -1,30 +0,0 @@
# Copyright (c) 2009 Upi Tamminen <desaster@gmail.com>
# See the COPYRIGHT file for more information
# Should be compatible with user mode linux
import struct, sys
OP_OPEN, OP_CLOSE, OP_WRITE, OP_EXEC = 1, 2, 3, 4
DIR_READ, DIR_WRITE = 1, 2
def ttylog_write(logfile, len, direction, stamp, data = None):
f = file(logfile, 'a')
sec, usec = int(stamp), int(1000000 * (stamp - int(stamp)))
f.write(struct.pack('iLiiLL', 3, 0, len, direction, sec, usec))
f.write(data)
f.close()
def ttylog_open(logfile, stamp):
f = file(logfile, 'a')
sec, usec = int(stamp), int(1000000 * (stamp - int(stamp)))
f.write(struct.pack('iLiiLL', 1, 0, 0, 0, sec, usec))
f.close()
def ttylog_close(logfile, stamp):
f = file(logfile, 'a')
sec, usec = int(stamp), int(1000000 * (stamp - int(stamp)))
f.write(struct.pack('iLiiLL', 2, 0, 0, 0, sec, usec))
f.close()
# vim: set sw=4 et: