Created
August 28, 2014 18:09
-
-
Save caseydunham/bcf07bbc8f8c5709f53f to your computer and use it in GitHub Desktop.
TimelessP's 2014-08-27 honeypot.py for detecting Lightaidra
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- coding: utf-8 -*- | |
# See @TimelessP on Twitter | |
# Originally pulled from http://pastebin.com/pXXi3g1z | |
# Also see http://pastebin.com/GhuezLhP | |
import SocketServer | |
import string | |
import datetime | |
import subprocess | |
import re | |
import threading | |
import time | |
import os | |
def _speak_thread(text_to_say): | |
pattern = re.compile('[^A-Za-z0-9 .!?]+', re.UNICODE | re.MULTILINE) | |
clean_text = text_to_say | |
pattern.sub(' ', clean_text) | |
inputcommand = ('if [ -x `which festival` ] ; then ' + | |
'echo "(SayText \\"%s\\")" |' % clean_text + | |
' festival -b --pipe ; fi') | |
p = subprocess.Popen(inputcommand, stdout=subprocess.PIPE, shell=True) | |
(output, err) = p.communicate() | |
return output | |
def speak(text_to_say): | |
t = threading.Thread(target=_speak_thread, args=(text_to_say,)) | |
t.daemon = True | |
t.start() | |
class RequestHandler(SocketServer.BaseRequestHandler): | |
def setup(self): | |
timestamp = "%s" % datetime.datetime.now() | |
speak('Sir, a new connection on the honeypot.') | |
print("%s Connection from %s:%s" % (timestamp, | |
self.client_address[0], self.client_address[1])) | |
self.server.connections[self.client_address] = {'instance': self, | |
'nickname': 'newbie'} | |
self.broadcast_others("Someone has entered the room.\r\n") | |
night_time = ' -d' if datetime.datetime.hour < 6 else '' | |
p = subprocess.Popen('fortune | cowsay %s' % night_time, | |
stdout=subprocess.PIPE, shell=True) | |
(fortune, err) = p.communicate() | |
self.request.send("%s\r\nYou are in a dark room.\r\n> " % fortune) | |
def handle(self): | |
self.input_buffer = '' | |
self.is_root = False | |
while True: | |
try: | |
data = self.request.recv(1024) | |
except Exception, err: | |
print("%s Receive error (%s) from %s:%s" % | |
(datetime.datetime.now(), | |
err, | |
self.client_address[0], self.client_address[1])) | |
self.broadcast_others("Someone has left the room.\r\n") | |
del self.server.connections[self.client_address] | |
self.finish() | |
speak("Sir, someone disconnected from the honeypot.") | |
break | |
timestamp = "%s" % datetime.datetime.now() | |
my_nickname = self.server. \ | |
connections[self.client_address]['nickname'] | |
if (data == ''): | |
print("%s Connection terminated from %s:%s" % (timestamp, | |
self.client_address[0], self.client_address[1])) | |
self.broadcast_others("Someone has left the room.\r\n") | |
del self.server.connections[self.client_address] | |
self.finish() | |
speak("Sir, someone disconnected from the honeypot.") | |
break | |
print(timestamp, self.client_address, my_nickname, 'data', data) | |
# Ctrl D in character mode is \xff\xec | |
if data == "\xff\xec": | |
data = "\x04" | |
# TODO: Implement full support for TELNET protocol: | |
if data.startswith("\xff"): | |
continue | |
# TODO: If any connection terminates just before we send a packet | |
# then we get an unhandled exception. Not so bad because | |
# only the thread dies. | |
self.input_buffer = self.input_buffer + data | |
if (not self.input_buffer.endswith("\n") and | |
not self.input_buffer.endswith("\r") and | |
not self.input_buffer.endswith("\x04") and | |
not self.input_buffer.endswith("\x00")): | |
continue | |
print(timestamp, self.client_address, my_nickname, | |
'line', self.input_buffer) | |
data = self.input_buffer.replace("\x00", "") | |
self.input_buffer = '' | |
# bots get snooped on, lol. | |
if self.is_root: | |
msg = "\r\n" + str(('bot_sent', self.client_address, | |
my_nickname, data)) + \ | |
"\r\n" | |
self.broadcast_others(msg) | |
if (data.strip() == 'exit' or data.strip() == '\x04'): | |
print("%s Disconnection from %s:%s" % (timestamp, | |
self.client_address[0], self.client_address[1])) | |
self.broadcast_others("Someone has left the room.\r\n") | |
del self.server.connections[self.client_address] | |
self.finish() | |
speak("Sir, someone disconnected from the honeypot.") | |
break | |
elif (data.strip() == 'shutdown'): | |
print("%s Shutdown issued from %s:%s" % (timestamp, | |
self.client_address[0], self.client_address[1])) | |
self.server.shutdown() | |
speak("Sir, someone has shut down the honeypot. Goodbye.") | |
time.sleep(5) | |
break | |
if data.strip() == 'help': | |
self.request.sendall(self.usage()) | |
elif data.strip() == 'who': | |
print(self.server.connections) | |
nicknames = [] | |
for client in self.server.connections.values(): | |
nicknames.append(client['nickname']) | |
self.request.sendall(str(nicknames) + "\r\n") | |
else: | |
if data.strip().find(' ') != -1: | |
command, arguments = string.split(data.strip(), ' ', 1) | |
else: | |
command = data.strip() | |
arguments = '' | |
if command == 'say': | |
msg = "\r\n" + str(('said', my_nickname, arguments)) + \ | |
"\r\n" | |
self.broadcast_others(msg) | |
elif command == 'speak': | |
speak(arguments) | |
msg = "\r\n" + str(('spake', my_nickname, arguments)) + \ | |
"\r\n" | |
self.broadcast_others(msg) | |
elif command == 'root': | |
# Right, we have a bot, everything it says gets broadcast. | |
self.is_root = True | |
elif command == 'quine': | |
this_file_path = os.path.realpath(__file__) | |
with open(this_file_path, 'r') as this_file_handle: | |
this_file_contents = this_file_handle.read() | |
self.request.sendall(this_file_contents) | |
elif command == 'nick': | |
if len(arguments) < 1 or len(arguments) > 20: | |
self.request.sendall(str(('error', 'nick', | |
'Too long or too short.')) + | |
"\r\n") | |
else: | |
speak('Sir, a human is using the honeypot.') | |
my_nickname = arguments | |
client = self.server.connections[self.client_address] | |
client['nickname'] = my_nickname | |
self.request.sendall("root@honeypot:~# " if self.is_root else "> ") | |
def broadcast_others(self, message): | |
for client in self.server.connections.values(): | |
if not client['instance'] == self: | |
client['instance'].request.sendall(message) | |
def usage(self): | |
return """Valid commands: | |
help - Shows this help. | |
who - Shows who is currently connected to the server. | |
nick <name> - Sets your nickname. | |
say <msg> - The message that follows the 'say' command will be sent to all. | |
speak <msg> - Audibly speaks the given message to the server owner (TTS) and | |
also works like the say command. | |
quine - Print the source code of this service. | |
exit - Disconnect from the server. | |
shutdown - Immediately shutdown the entire server. Yup, anyone can. Gone. | |
""" | |
if __name__ == "__main__": | |
SocketServer.ThreadingTCPServer.allow_reuse_address = True | |
# 5 is default anyway. | |
SocketServer.ThreadingTCPServer.request_queue_size = 5 | |
server_address = ('', 2323) | |
server = SocketServer.ThreadingTCPServer(server_address, | |
RequestHandler) | |
server.connections = {} | |
server.serve_forever() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment