#************************************************************************* #* Dionaea #* - catches bugs - #* #* #* #* Copyright (C) 2009 Paul Baecher & Markus Koetter #* #* This program is free software; you can redistribute it and/or #* modify it under the terms of the GNU General Public License #* as published by the Free Software Foundation; either version 2 #* of the License, or (at your option) any later version. #* #* This program is distributed in the hope that it will be useful, #* but WITHOUT ANY WARRANTY; without even the implied warranty of #* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #* GNU General Public License for more details. #* #* You should have received a copy of the GNU General Public License #* along with this program; if not, write to the Free Software #* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #* #* #* contact nepenthesdev@gmail.com #* #*******************************************************************************/ from dionaea import IHandlerLoader from dionaea.core import ihandler, incident, connection from struct import pack, unpack, calcsize from socket import inet_aton import logging logger = logging.getLogger('p0f') logger.setLevel(logging.DEBUG) class P0FHandlerLoader(IHandlerLoader): name = "p0f" @classmethod def start(cls, config=None): return p0fhandler(config=config) class p0fconnection(connection): def __init__(self, p0fpath, con): connection.__init__(self, 'tcp') self.con = con self.con.ref() self.connect(p0fpath, 0) def handle_established(self): if True: # p0f >= 2.0.8 data = pack("III4s4sHH", 0x0defaced, # p0f magic 1, # type 0xffffffff, # id inet_aton(self.con.remote.host),# remote host inet_aton(self.con.local.host), # local host self.con.remote.port, # remote port self.con.local.port) # local port else: # p0f < 2.0.8 data = pack("=II4s4sHH", 0x0defaced, # p0f magic 0xffffffff, # type inet_aton(self.con.remote.host),# remote host inet_aton(self.con.local.host), # local host self.con.remote.port, # remote port self.con.local.port) # local port self.send(data) def handle_io_in(self, data): fmt = "IIB20s40sB30s30sBBBhHi" if len(data) != calcsize(fmt): return 0 values = unpack(fmt, data) names=["magic","id","type","genre","detail","dist","link", "tos","fw","nat","real","score","mflags","uptime"] icd = incident(origin='dionaea.modules.python.p0f') for i in range(len(values)): s = values[i] if type(s) == bytes: if s.find(b'\x00'): s = s[:s.find(b'\x00')] try: s = s.decode("ascii") except UnicodeDecodeError: logger.warning("Unable to decode p0f information %s=%r", i, s, exc_info=True) icd.set(names[i], s) elif type(s) == int: icd.set(names[i], str(s)) icd.set('con',self.con) icd.report() self.close() return len(data) def handle_disconnect(self): self.con.unref() return 0 def handle_error(self, err): self.con.unref() class p0fhandler(ihandler): def __init__(self, config=None): logger.debug("p0fHandler") ihandler.__init__(self, 'dionaea.connection.*') self.p0fpath = config.get("path") def handle_incident(self, icd): if icd.origin == 'dionaea.connection.tcp.accept' or icd.origin == 'dionaea.connection.tls.accept' or icd.origin == 'dionaea.connection.tcp.reject': logger.debug("p0f action") # icd.dump() con = icd.get('con') p = p0fconnection(self.p0fpath, con) # p0f = p0fHandler('un:///tmp/p0f.sock')