Skip to content

Instantly share code, notes, and snippets.

@caseydunham
Created August 28, 2014 18:09
Show Gist options
  • Save caseydunham/bcf07bbc8f8c5709f53f to your computer and use it in GitHub Desktop.
Save caseydunham/bcf07bbc8f8c5709f53f to your computer and use it in GitHub Desktop.
TimelessP's 2014-08-27 honeypot.py for detecting Lightaidra
# -*- 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