forked from foospidy/HoneyPy
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathHoney.py
executable file
·207 lines (171 loc) · 8.47 KB
/
Honey.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
#!/usr/bin/env python
# HoneyPy Copyright (C) 2013-2017 foospidy
# GNU GENERAL PUBLIC LICENSE
# https://github.com/foospidy/HoneyPy/blob/master/LICENSE
import sys
import os
import subprocess
import socket
import ConfigParser
import argparse
import importlib
from twisted.internet import protocol
from twisted.internet import reactor
from twisted.internet import stdio
from twisted.python import log
from twisted.python.log import FileLogObserver
from twisted.python.logfile import DailyLogFile
from lib.honeypy_logtail import SingleDailyLogFile
from lib.honeypy_logtail import HoneyPyLogTail
from lib.honeypy_console import HoneyPyConsole
# prevent creation of compiled bytecode files
sys.dont_write_bytecode = True
# handle and process command line arguments
parser = argparse.ArgumentParser(description='Process command line arguments.')
parser.add_argument('-d', help='run in daemon mode (no console).', default=False, action="store_true")
parser.add_argument('-ipt', help='generate ipt-kit script in /tmp.', default=False, action="store_true")
args = parser.parse_args()
# get path for config files
script_dir = os.path.dirname(os.path.abspath(__file__))
honeypy_config_file = script_dir + '/etc/honeypy.cfg'
service_config_file = script_dir + '/etc/services.cfg'
# setup config parsers
honeypy_config = ConfigParser.ConfigParser()
service_config = ConfigParser.ConfigParser()
# read config files
honeypy_config.read(honeypy_config_file)
service_config.read(service_config_file)
# setup log file and formatting
if honeypy_config.has_option('honeypy', 'internal_log_dir'):
if os.path.isabs(honeypy_config.get('honeypy', 'internal_log_dir')):
log_path = honeypy_config.get('honeypy', 'internal_log_dir')
else:
log_path = os.path.join(script_dir, honeypy_config.get('honeypy', 'internal_log_dir'))
log_path = os.path.normpath(log_path)
else:
log_path = os.path.join(script_dir, 'log/')
log_file_name = 'honeypy.log'
ipt_file_name = '/tmp/honeypy-ipt.sh'
if not os.path.exists(log_path):
# if log directory does not exist, create it.
os.makedirs(log_path)
if honeypy_config.get('honeypy', 'limit_internal_logs').lower() == 'yes':
log_file = SingleDailyLogFile(log_file_name, log_path)
else:
log_file = DailyLogFile(log_file_name, log_path)
file_log_observer = FileLogObserver(log_file)
time_zone = subprocess.check_output(['date', '+%z'])
file_log_observer.timeFormat = "%Y-%m-%d %H:%M:%S,%f," + time_zone.rstrip()
# get version
version = file(script_dir + '/VERSION').read().strip()
# start logging
log.startLoggingWithObserver(file_log_observer.emit, False)
#check if other service profiles are to be included
if honeypy_config.has_option('honeypy', 'service_profiles'):
log.msg('Skipping etc/services.cfg')
service_config = ConfigParser.ConfigParser()
for service_profile in honeypy_config.get('honeypy', 'service_profiles').split(','):
profile_cfg_file = script_dir + '/etc/profiles/' + service_profile.strip()
log.msg("Reading services from %s" % profile_cfg_file)
profile_cfg = ConfigParser.ConfigParser()
profile_cfg.read(profile_cfg_file)
#add the services from this profile
for section in profile_cfg.sections():
if profile_cfg.get(section, 'enabled').lower() == 'yes':
#if enabled and don't already exist
if not service_config.has_section(section):
log.msg("Adding service : %s %s" % (section, profile_cfg.get(section, 'low_port')))
service_config.add_section(section)
#read the options and add then to the new service section
for option in profile_cfg.options(section):
service_config.set(section, option, profile_cfg.get(section, option))
else:
log.msg("Skipping duplicate service : %s %s" % (section, service_config.get(section, 'low_port')))
if args.ipt:
# generate ipt-kit script in /tmp and quit.
ipt_file = open(ipt_file_name, 'w')
ipt_file.write('# copy this file to your ipt-kit directory and execute.\n')
for service in service_config.sections():
if service_config.get(service, 'enabled') == 'Yes':
[low_protocol, low_port] = service_config.get(service, 'low_port').split(':')
[protocol, port] = service_config.get(service, 'port').split(':')
if int(low_port) < 1024:
ipt_file.write('./ipt_set_' + low_protocol + ' ' + low_port + ' ' + port + ' $1\n')
# set file permission, close, and quit
os.chmod(ipt_file_name, 0744)
ipt_file.close()
quit()
# tail log file when reactor runs
tailer = HoneyPyLogTail(os.path.join(log_path, log_file_name))
tailer.config = honeypy_config
tailer.config.set('honeypy', 'useragent', 'HoneyPy (' + version + ')')
# set persistent logger connections
for section in tailer.config.sections():
if tailer.config.has_option(section, 'persistent') and tailer.config.get(section, 'persistent').lower() == 'yes' and tailer.config.get(section, 'enabled').lower() == 'yes':
module_name = "loggers.%s.honeypy_%s" % (section, section)
logger_module = importlib.import_module(module_name)
tailer.persistent_conns[section] = logger_module.conn(tailer.config, section)
tailer.start()
log.msg(tailer.config.get('honeypy', 'useragent') + " Started")
for section in tailer.config.sections():
if section != 'honeypy' and tailer.config.get(section, 'enabled').lower() == 'yes':
log.msg("Enabled Logger : %s" % (section))
# services object array
services = []
services.append([])
services.append([])
# start enabled services
display_low_port_message = True
def get_ip_address():
# function to ensure we get external IP (rather than hostname) for udp connections.
# http://stackoverflow.com/questions/24196932/how-can-i-get-the-ip-address-of-eth0-in-python/24196955
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect(("8.8.8.8", 80))
ipaddress = s.getsockname()[0]
s.shutdown(socket.SHUT_RDWR)
s.close()
return ipaddress
for service in service_config.sections():
if service_config.get(service, 'enabled') == 'Yes':
[low_protocol, low_port] = service_config.get(service, 'low_port').split(':')
[protocol, port] = service_config.get(service, 'port').split(':')
plugin_module = 'plugins.' + service_config.get(service, 'plugin')
plugin = importlib.import_module(plugin_module)
service_object = None
if args.d is False:
if int(low_port) < 1024:
if display_low_port_message:
print 'Your service configuration suggests that you want to run on at least one low port!'
print 'To enable port redirection run the following ipt-kit (https://github.com/foospidy/ipt-kit) commands as root:'
print ''
display_low_port_message = False
try:
if protocol.lower() == 'tcp':
# run tcp service
service_object = reactor.listenTCP(int(port), plugin.pluginFactory(service))
else:
# run udp service
service_object = reactor.listenUDP(int(port), plugin.pluginMain(service, get_ip_address(), port))
if service_object:
# stop services from listening immediately if not starting in daemon mode.
if args.d is False:
service_object.stopListening()
# save service objects to array, to be used by HoneyPy Console
services[0].append(service)
services[1].append(service_object)
except Exception as e:
print str(e) + '\n'
if str(e).find('Permission denied') != -1:
print 'If you are attempting to use a low port (below 1024), do not.'
print 'Low ports require root privilege and you should not run HoneyPy as root.'
print 'Run the service on a high port and use IP Tables to redirect the low port'
print 'to a high port. This may help, https://github.com/foospidy/ipt-kit'
if str(e).find('Address already in use') != -1:
print 'A service (' + service + ') is configured to run on a port that is already'
print 'in use by another process. Kill the other process or use a different port.'
sys.exit()
# run HoneyPy Console if daemon mode not specified
if args.d is False:
stdio.StandardIO(HoneyPyConsole(honeypy_config, services))
# start reactor
reactor.run()