random/irc/blackhole.py

209 lines
6.1 KiB
Python

#!/usr/bin/env python
# Blackhole IRC Bot - Developed by acidvegas in Python - (https://acid.vegas/random)
'''
WARNING: This script it entirely unfinished and should not be used for anything other than testing!
This is an advanced master/honeypot(s) bot system designed to combat advanced flooding techniques on IRC
'''
import random, ssl, socket, time, threading
# Config
nickserv_password = None
operator_password = None
user_modes = None #BdZ
class HoneyPot(threading.Thread):
def __init__(self):
self.nickname = random.choice(BlackHole.db['honeypot_nicks'])
self.sock = None
threading.Thread.__init__(self)
def connect(self):
try:
self.sock = ssl.wrap_socket(socket.socket(socket.AF_INET, socket.SOCK_STREAM))
self.sock.connect(('localhost', 6697))
self.raw(f'USER {username} 0 * :{realname}')
self.raw('NICK ' + self.nickname)
except socket.error:
self.event_disconnect()
else:
self.listen()
def event_disconnect(self):
self.sock.close()
time.sleep(15)
self.connect()
def handle_events(self, data):
args = data.split()
if data.startswith('ERROR :Closing Link:'):
raise Exception('Connection has closed.')
elif args[0] == 'PING':
self.raw('PONG ' + args[1][1:])
elif args[1] == '001':
for chan in channels:
self.raw('JOIN ' + chan)
time.sleep(1)
elif args[1] == '433':
self.nickname = random.choice(BlackHole.db['honeypot_nicks'])
self.raw('NICK ' + self.nickname)
elif args[1] == 'INVITE':
nick = args[0].split('!')[0][1:]
self.sendmsg('blackhole', '!' + nick)
elif args[1] == 'KICK' and len(args) >= 4:
chan = args[2]
kicked = args[3]
if chan in channels and kicked == self.nickname:
time.sleep(1)
self.raw('JOIN ' + chan)
elif args[1] == 'NOTICE':
nick = args[0].split('!')[0][1:]
self.sendmsg('blackhole', '!' + nick)
elif args[1] == 'PRIVMSG' and len(args) >= 3:
nick = args[0].split('!')[0][1:]
chan = args[2]
if chan == self.nickname or '\001' in data:
self.sendmsg('blackhole', '!' + nick)
def listen(self):
while True:
try:
data = self.sock.recv(1024).decode('utf-8')
for line in (line for line in data.split('\r\n') if line):
if len(line.split()) >= 2:
self.handle_events(line)
except (UnicodeDecodeError,UnicodeEncodeError):
pass
except:
break
self.event_disconnect()
def raw(self, msg):
self.sock.send(bytes(msg + '\r\n', 'utf-8'))
def sendmsg(self, target, msg):
self.raw(f'PRIVMSG {target} :{msg}')
class IRC(object):
def __init__(self):
self.db = {'ident':list(),'nick':list(),:'protect':list()}
self.sock = None
def run(self):
with open('blackhole.pkl','rb') as db_file:
self.db = pickle.load(db_file)
self.connect()
def connect(self):
try:
self.sock = ssl.wrap_socket(socket.socket(socket.AF_INET, socket.SOCK_STREAM))
self.sock.connect(('localhost', 6697))
self.raw(f'USER BL 0 * :ENTER THE VOID')
self.raw('NICK blackhole')
except socket.error:
self.event_disconnect()
else:
self.listen()
def evemt_connect(self):
self.mode(nickname, '+' + user_modes)
self.identify(nickname, nickserv_password)
self.oper(username, operator_password)
def event_disconnect(self):
self.sock.close()
time.sleep(15)
self.connect()
def event_private(self, ident, nick, msg):
if ident == admin:
args = msg.split()
cmd = args[0][1:]
if msg[:1] == '.':
if cmd in self.db.keys():
if len(args) == 1:
for item in self.db[cmd]:
self.sendmsg(nick, '\x0310' + item)
elif len(args) == 2:
option = args[1][1:]
change = args[1][:1]
if change == '+':
if option not in self.db[cmd]:
self.db[cmd].append(option)
self.sendmsg(nick, '\x033added')
elif change == '-':
if option in self.db[cmd]:
self.db[cmd].remove(option)
self.sendmsg(nick, '\x035removed')
elif ident not in self.db['protected_hosts']:
self.raw('KILL {nick} \x038,4 E N T E R T H E V O I D \x0f')
def handle_events(self, data):
args = data.split()
if data.startswith('ERROR :Closing Link:'):
raise Exception('Connection has closed.')
elif args[0] == 'PING':
self.raw('PONG ' + args[1][1:])
elif args[1] == '001':
self.event_connect()
elif args[1] == 'INVITE' or args[1] == 'NOTICE':
nick = args[0].split('!')[0][1:]
host = args[0].split('@')[1]
self.raw('KILL {nick} \x038,4 E N T E R T H E V O I D \x0f')
elif args[1] == 'KICK' and len(args) >= 4:
nick = args[0].split('!')[0][1:].lower()
host = args[0].split('@')[1]
chan = args[2]
kicked = args[3].lower()
if kicked == 'blackhole':
time.sleep(1)
self.raw('JOIN ' + chan)
else:
for item in self.db['nick']:
if kicked == item:
self.raw(f'KICK {chan} {nick} \x038,4 E N T E R T H E V O I D \x0f')
self.mode(chan, '+b *!*@' + host)
break
elif args[1] == 'PRIVMSG' and len(args) == 4:
ident = args[0].split('!')[1].lower()
host = args[0].split('@')[1]
nick = args[0].split('!')[0][1:].lower()
chan = args[2]
msg = ' '.join(args[3:])[1:].lower()
if '\001' in msg:
self.raw('KILL {nick} \x038,4 E N T E R T H E V O I D \x0f')
elif chan == 'blackhole':
if ident in self.db['ident'] and msg.startswith('!'):
self.raw('KILL {msg[1:]} \x038,4 E N T E R T H E V O I D \x0f')
elif ident == admin:
self.event_private(ident, nick, msg)
else:
self.raw('KILL {nick} \x038,4 E N T E R T H E V O I D \x0f')
elif host not in self.db['protect']:
for item in self.db['nick']:
if item in msg:
self.raw('KICK {chan} {nick} \x038,4 E N T E R T H E V O I D \x0f')
break
def listen(self):
while True:
try:
data = self.sock.recv(1024).decode('utf-8')
for line in (line for line in data.split('\r\n') if line):
if len(line.split()) >= 2:
self.handle_events(line)
except (UnicodeDecodeError,UnicodeEncodeError):
pass
except:
break
self.event_disconnect()
def raw(self, msg):
self.sock.send(bytes(msg + '\r\n', 'utf-8'))
# Main
BlackHole = IRC()
BlackHole.run()