Browse files

fixed issues with mod_wsgi when deploying with apache

  • Loading branch information...
1 parent 42790a6 commit c1c0ea4d7a9adda47f7f5a4b300404b941c49862 pjlantz committed Mar 16, 2011
View
7 src/client.py
@@ -23,13 +23,6 @@
from conf import configHandler
-if os.name == "nt":
- try:
- import pyreadline
- except ImportError:
- print "Error: Windows PyReadline support missing"
- sys.exit(1)
-
class CLI(cmd.Cmd):
"""
Handles command line input with support for
View
4 src/conf/configHandler.py
@@ -60,8 +60,6 @@ def __init__(self):
self.currentHash = ''
self.currentConfig = ConfigParser()
self.currentConfigFile = "conf/modules.conf"
- if os.name == "nt":
- self.currentConfigFile = self.currentConfigFile.replace("/", "\\")
self.currentConfig.read(self.currentConfigFile)
self.currentSection = ''
self.current = {}
@@ -72,8 +70,6 @@ def loadHaleConf(self):
"""
self.confFile = "conf/hale.conf"
- if os.name == "nt":
- self.confFile = self.confFile.replace("/", "\\")
self.haleConf = ConfigParser()
self.haleConf.read(self.confFile)
View
36 src/modules/ircModule.py
@@ -1,5 +1,5 @@
################################################################################
-# (c) 2010, The Honeynet Project
+# (c) 2011, The Honeynet Project
# Author: Patrik Lantz patrik@pjlantz.com
#
# This program is free software; you can redistribute it and/or modify
@@ -118,24 +118,32 @@ def dataReceived(self, data):
if data.find(self.factory.config['ping_grammar']) != -1: # ping
self.transport.write(self.factory.config['pong_grammar'] + ' ' + data.split()[1] + '\r\n') # send pong
if self.factory.firstPing:
- if self.factory.config['channel_pass'] != 'None': # joing with pass
- self.transport.write(self.factory.config['join_grammar'] + ' ' + self.factory.config['channel'] + ' ' +
- self.factory.config['channel_pass'] + '\r\n')
- else:
- self.transport.write(self.factory.config['join_grammar'] + ' ' + self.factory.config['channel'] + '\r\n') # join without pass
- self.factory.firstPing = False
+ if self.factory.config['channel_pass'] != 'None': # joing with pass
+ self.transport.write(self.factory.config['join_grammar'] + ' ' + self.factory.config['channel'] + ' ' + self.factory.config['channel_pass'] + '\r\n')
+ else:
+ self.transport.write(self.factory.config['join_grammar'] + ' ' + self.factory.config['channel'] + '\r\n') # join without pass
+ self.factory.firstPing = False
elif data.find(self.factory.config['topic_grammar']) != -1: # topic
self.factory.putLog(data)
elif data.find(self.factory.config['currenttopic_grammar']) != -1: # currenttopic
- firstline = data.split('\r\n')[0].split(self.factory.config['nick'])[1].strip()
- chan = firstline.split(' ')[0].strip()
- topic = firstline.split(' ')[1].strip()
- secondline = data.split('\r\n')[1].split(self.factory.config['channel'])[1].strip()
- setby = secondline.split(' ')[0].strip()
- logmsg = 'CURRENTTOPIC ' + chan + ' ' + topic + ' set by ' + setby
- self.factory.putLog(logmsg)
+ firstline = secondline = None
+ chan = topic = setby = ''
+
+ for line in data.split('\r\n'):
+ if not firstline:
+ firstline = line.split(self.factory.config['nick'])[1].strip()
+ chan = firstline.split(' ')[0].strip()
+ topic = firstline.split(' ')[1].strip()
+ self.factory.putLog("CURRENTTOPIC " + "Channel: " + chan + " Topic: " + topic.split(":")[1])
+ continue
+ if not secondline:
+ secondline = line.split(self.factory.config['channel'])[1].strip()
+ setby = secondline.split(' ')[0].strip()
+ self.factory.putLog("CURRENTTOPIC " + "Set by: " + setby)
+ break
+
elif data.find(self.factory.config['privmsg_grammar']) != -1: # privmsg
if not data.find(self.factory.config['version_grammar']) != -1:
View
2 src/modules/moduleManager.py
@@ -33,8 +33,6 @@
errors = {}
moduleDir = os.getcwd() + "/modules/"
-if os.name == "nt":
- moduleDir = moduleDir.replace("/", "\\")
def register(module):
"""
View
32 src/utils/logHandler.py
@@ -40,8 +40,6 @@ def __init__(self):
"""
geodata = os.getcwd() + "/utils/GeoIP.dat"
- if os.name == "nt":
- geodata = geodata.replace("/", "\\")
self.geo = GeoIP.open(geodata, GeoIP.GEOIP_STANDARD)
self.haleConf = configHandler.ConfigHandler().loadHaleConf()
@@ -63,17 +61,18 @@ def putToDB(self, data, botnethash, conf):
confStr = configHandler.ConfigHandler().getStrFromDict(conf, toDB=True)
coord = self.geo.record_by_name(conf['botnet'])
- b = Botnet(botnethashvalue=botnethash, botnettype=conf['module'], host=conf['botnet'], config=confStr, longitude=coord['longitude'], latitude=coord['latitude'])
- try:
- b.save()
- except IntegrityError:
- b = Botnet.objects.get(botnethashvalue=botnethash)
- b.longitude = coord['longitude']
- b.latitude = coord['latitude']
- b.save()
+
+ (b, created) = Botnet.objects.get_or_create(botnethashvalue = botnethash)
+ if not created:
+ b.botnettype = conf['module']
+ b.host = conf['botnet']
+ b.config = confStr
+ b.longitude = coord['longitude']
+ b.latitude = coord['latitude']
+ b.save()
botnetobject = Botnet.objects.get(botnethashvalue=botnethash)
- Log(botnet=botnetobject, logdata=data).save()
+ Log(botnet=b, logdata=data).save()
botnetobject.save()
def putToXMPP(self, data, config, botnethash):
@@ -131,6 +130,7 @@ def __init__(self):
self.prox = proxySelector.ProxySelector()
self.url_expre = re.compile('((http|https|ftp)://[~@a-zA-Z0-9_\-/\\\.\+:]+)')
+ self.haleConf = configHandler.ConfigHandler().loadHaleConf()
def handleData(self, data, botnethash, config):
"""
@@ -174,7 +174,10 @@ def doDownload(self, url, extfilename):
opener = urllib2.build_opener()
opener.addheaders = [('User-agent', '')]
- fp = opener.open(url)
+ try:
+ fp = opener.open(url)
+ except Exception:
+ return
urlinfo = fp.info()
if "text/html" in urlinfo['Content-Type']: # no executable
fp.close()
@@ -189,8 +192,6 @@ def doDownload(self, url, extfilename):
hash = md5.update(content)
fname = md5.hexdigest()
filename = extfilename
- if os.name == "nt":
- filename = filename.replace("/", "\\")
if not os.path.exists(filename):
fp = open(filename, 'a+')
fp.write(content)
@@ -202,7 +203,8 @@ def doDownload(self, url, extfilename):
return
os.remove(filename)
content = base64.b64encode(content)
- producerBot.ProducerBot().sendFile(content, fname)
+ if self.haleConf.get("xmpp", "use") == 'True':
+ producerBot.ProducerBot().sendFile(content, fname)
botnetobject = Botnet.objects.get(botnethashvalue=self.botnethash)
try:
File(botnet=botnetobject, hash=fname, content=content, filename=filename).save()
View
2 src/utils/moduleCoordinator.py
@@ -151,8 +151,6 @@ def __init__(self, haleConf):
self.url = logHandler.URLCheck()
self.relip = logHandler.CCRelatedIP()
geodata = os.getcwd() + "/utils/GeoIP.dat"
- if os.name == "nt":
- geodata = geodata.replace("/", "\\")
self.geo = GeoIP.open(geodata, GeoIP.GEOIP_STANDARD)
threading.Thread.__init__(self)
View
30 src/webdb/django.wsgi
@@ -0,0 +1,30 @@
+##############################################################################
+# (c) 2011, The Honeynet Project
+# Author: Patrik Lantz patrik@pjlantz.com
+#
+# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+################################################################################
+
+import sys
+import os
+
+sys.path.append(os.path.dirname(os.path.abspath(__file__)) + '/..')
+os.environ['DJANGO_SETTINGS_MODULE'] = 'webdb.settings'
+
+import django.core.handlers.wsgi
+
+application = django.core.handlers.wsgi.WSGIHandler()
+
View
7 src/webdb/hale/models.py
@@ -1,5 +1,5 @@
################################################################################
-# (c) 2010, The Honeynet Project
+# (c) 2011, The Honeynet Project
# Author: Patrik Lantz patrik@pjlantz.com
#
# This program is free software; you can redistribute it and/or modify
@@ -77,7 +77,7 @@ class Module(models.Model):
modulename = models.CharField(max_length=32, unique=True)
filename = models.CharField(max_length=32)
- module = models.FileField(upload_to='modules/')
+ module = models.FileField()
# configuration example for this module
confexample = models.TextField()
@@ -102,8 +102,7 @@ def getDay(self):
class File(models.Model):
"""
- Holds the file and analysis URL for the sandbox
- submitted to together with details about the file
+ Holds uploaded malware thefile
"""
def getYear(self):
View
8 src/webdb/hale/views.py
@@ -1,5 +1,5 @@
################################################################################
-# (c) 2010, The Honeynet Project
+# (c) 2011, The Honeynet Project
# Author: Patrik Lantz patrik@pjlantz.com
#
# This program is free software; you can redistribute it and/or modify
@@ -76,13 +76,11 @@ def download(request, filename):
Render response for module download
"""
- filePath = os.getcwd() + "/modules/" + filename
- if os.name == "nt":
- filePath = filePath.replace("/", "\\")
+ filePath = settings.MEDIA_ROOT + str(filename)
file = open(filePath)
ctype, encoding = mimetypes.guess_type(filePath)
response = HttpResponse(file, mimetype=ctype)
- response['Content-Disposition'] = 'attachment; filename='+filename
+ response['Content-Disposition'] = 'attachment; filename='+str(filename)
return response
@login_required
View
215 src/webdb/modules/httpModule.py
@@ -0,0 +1,215 @@
+################################################################################
+# (c) 2010, The Honeynet Project
+# Author: Patrik Lantz patrik@pjlantz.com
+#
+# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+################################################################################
+
+import base64, urllib
+import moduleManager
+from utils import *
+from twisted.internet import reactor, protocol
+from twisted.web.client import HTTPPageGetter
+
+@moduleManager.register("http")
+def setup_module(config, hash):
+ """
+ Function to register modules, simply
+ implement this to pass along the config
+ to the module object and return it back
+ """
+
+ return HTTP(config, hash)
+
+class HTTP(moduleInterface.Module):
+ """
+ Implementation of a http client to do http based
+ botnet monitoring by connecting to such botnets
+ and receiving commands and instructions
+ """
+
+ def __init__(self, conf, hash):
+ """
+ Constructor sets up configs and task to do
+ a looping call
+ """
+
+ self.hash = hash
+ self.config = conf
+ self.cont = True
+
+ def run(self):
+ """
+ Start execution
+ """
+
+ self.prox = proxySelector.ProxySelector()
+ self.factory = HTTPClientFactory(self, self.hash, self.config)
+ self.host = self.config['botnet']
+ self.port = int(self.config['port'])
+ self.proxyInfo = self.prox.getRandomProxy()
+ if self.proxyInfo != None:
+ self.proxyHost = self.proxyInfo['HOST']
+ self.proxyPort = self.proxyInfo['PORT']
+ self.proxyUser = self.proxyInfo['USER']
+ self.proxyPass = self.proxyInfo['PASS']
+ self.connect()
+
+ def connect(self):
+ """
+ Scheduled function to execute which connects
+ to botnet and receives instructions
+ """
+
+ if not self.cont:
+ return
+
+ if self.proxyInfo == None:
+ self.connector = reactor.connectTCP(self.host, self.port, self.factory)
+ else:
+ socksify = socks5.ProxyClientCreator(reactor, self.factory)
+ if len(self.proxyUser) == 0:
+ self.connector = socksify.connectSocks5Proxy(self.host, self.port, self.proxyHost, self.proxyPort, "HALE")
+ else:
+ self.connector = socksify.connectSocks5Proxy(self.host, self.port, self.proxyHost, self.proxyPort, "HALE", self.proxyUser, self.proxyPass)
+
+ def startLoop(self):
+ """
+ Called by the factory to do a new reconnect
+ """
+
+ self.connect()
+
+ def stop(self):
+ """
+ Stop execution
+ """
+
+ self.cont = False
+
+
+ def getConfig(self):
+ """
+ Return specific configuration used by this module
+ """
+
+ return self.config
+
+class HTTPProtocol(HTTPPageGetter):
+ """
+ Protocol class fetching web page
+ """
+
+ def handleResponsePart(self, data):
+ """
+ Sends response to the factory
+ """
+
+ self.factory.handleResponse(data.strip())
+
+class HTTPClientFactory(protocol.ClientFactory):
+ """
+ Clientfactory taking care of the http request
+ """
+
+ protocol = HTTPProtocol
+
+ def __init__(self, module, hash, config):
+ """
+ Constructor
+ """
+
+ self.hash = hash
+ self.config = config
+ self.cookies = {}
+ self.url = self.config['botnet']
+ self.host = self.config['botnet']
+ if self.config['useragent'] == "None":
+ self.agent = ""
+ else:
+ self.agent = self.config['useragent']
+ self.path = self.config['path']
+ self.method = self.config['method']
+ self.req = urllib.urlencode({self.config['id_grammar']: self.config['id'],
+ self.config['build_id_grammar']: self.config['build_id']})
+ if self.method == 'POST':
+ self.headers = {"Host": self.host, "Content-Type": "application/x-www-form-urlencoded"}
+ params = urllib.urlencode({self.config['id_grammar']: self.config['id'],
+ self.config['build_id_grammar']: self.config['build_id']})
+ if self.config['use_base64encoding'] == "True":
+ self.postdata = base64.b64encode(params)
+ else:
+ self.postdata = params
+ if self.method == 'GET':
+ self.headers = {"Host": self.host}
+ if self.config['use_base64encoding'] == "True":
+ idParameter = base64.b64encode(self.config['id'])
+ buildIdParamter = base64.b64encode(self.config['build_id'])
+ params = urllib.urlencode({self.config['id_grammar']: idParameter, self.config['build_id_grammar']: buildIdParamter})
+ else:
+ params = urllib.urlencode({self.config['id_grammar']: self.config['id'],
+ self.config['build_id_grammar']: self.config['build_id']})
+ self.path = self.path + "?" + params
+ self.wait = 0
+ self.module = module
+
+ def handleResponse(self, response):
+ """
+ Handles response by decoding it if specified to
+ do so in the config file. Logs data and extract
+ the new reconnect interval
+ """
+
+ if self.config['use_base64decoding'] == "True":
+ try:
+ response = base64.b64decode(response)
+ except TypeError:
+ # Could not decode data, maybe not base64 encoded, got response
+ return
+
+ moduleCoordinator.ModuleCoordinator().addEvent(moduleCoordinator.URL_EVENT, response, self.hash)
+ moduleCoordinator.ModuleCoordinator().addEvent(moduleCoordinator.LOG_EVENT, response, self.hash, self.config)
+ # extract wait grammar for new reconnect interval
+ try:
+ self.wait = int(response.split(self.config['wait_grammar'])[1].split(self.config['response_separator'])[1])
+ reactor.callLater(self.wait * 60, self.module.startLoop)
+ except IndexError:
+ # Could not split out wait grammar, maybe base64 decoding is necessary, got response:
+ return
+
+ def __call__(self):
+ """
+ Used by the socks5 module to return
+ the protocol handled by this factory
+ """
+
+ p = self.protocol()
+ p.factory = self
+ return p
+
+ def gotStatus(self, version, status, message):
+ pass
+
+ def gotHeaders(self, headers):
+ pass
+
+ def noPage(self, reason):
+ pass
+
+ def page(self, response):
+ pass
+
+
View
6 src/webdb/settings.py
@@ -45,12 +45,12 @@
# Absolute path to the directory that holds media.
# Example: "/home/media/media.lawrence.com/"
-MEDIA_ROOT = ''
+MEDIA_ROOT = '/home/pjlantz/Desktop/Hale/src/webdb/modules/'
# URL that handles the media served from MEDIA_ROOT. Make sure to use a
# trailing slash if there is a path component (optional in other cases).
# Examples: "http://media.lawrence.com", "http://example.com/media/"
-MEDIA_URL = ''
+MEDIA_URL = '/download/'
# URL prefix for admin media -- CSS, JavaScript and images. Make sure to use a
# trailing slash.
@@ -80,8 +80,6 @@
import os
templateDir = os.getcwd() + "/hale/templates/"
indexDir = os.getcwd() + "/hale/webdb/hale/site_index/"
-if os.name == "nt":
- templateDir = templateDir.replace("/", "\\")
TEMPLATE_DIRS = (templateDir)

0 comments on commit c1c0ea4

Please sign in to comment.