import xchat import re import os __module_name__ = 'killspambot' __module_version__ = '0.1' __module_description__ = 'Uses the +c user mode to find if certain nicks are humans or spambots and kill the spambots' #In xchat, do /load killspambot.py once you are an oper oper_nick = 'pabs' query_bots = 1 msg_bots = 1 gline_bots = 1 close_query = 1 #These files are obtained directly from the virus. robotnicz_file = 'robotnicz.txt' robotgreetz_file = 'robotgreetz.txt' robotspamz_file = 'robotspamz.txt' #These just contain the networks where this should do it's magic networks_file = 'networks.txt' servers_file = 'servers.txt' #Log settings debug_xchat = 0 debug_file = 1 debug_bothunter = 1 #Messages used to test the bots & apologise to real users hi_message = 'hi' gline_message = 'Your computer is infected with a virus, please contact ircd@lists.indymedia.org when you have finished cleaning it.' apology_msg = 'Sorry, just testing to see if you are infected by a virus. Please contact ircd@lists.indymedia.org for more info.' #Some regexes for detecting urls & connection messages urlexe = re.compile( '.*(http\:\/\/.*\.exe)' ) connectmsg = re.compile( '\*\*\* Notice -- Client connecting: ([^ ]*) \(~([^@]*)@.*\) \[.*\] \{noident\} \[([^\]]*)\]' ) def log(msg,log=''): if log is '': log = 'spambot.log' if debug_bothunter: xchat.command('msg #bothunter %s' % msg ) else: log += '.log' if debug_xchat: xchat.prnt( msg ) if debug_file: f = open(log, 'ab') f.write(msg) f.write('\n') f.close() def spambot_cb(word, word_eol, userdata): if xchat.get_info('network') not in networks: return xchat.EAT_NONE channel = xchat.get_info('channel') if channel[0] == '#' or channel[0] == '&': xchat.prnt('You are not in a /query') return xchat.EAT_ALL user_host = xchat.get_info('topic') if user_host is None: if query_bots: xchat.command('query %s' % channel ) if msg_bots: xchat.command('msg %s %s' % (channel, hi_message) ) else: xchat.prnt('You need to talk to the bot first') return xchat.EAT_ALL (user, host) = user_host.split('@') gline( host, 'manual gline of %s!%s' % (channel, user_host) ) xchat.prnt('Spambot glined') return xchat.EAT_ALL def gline( host, logreason='' ): log( 'Glining a spambot. host: %s reason: %s)' % (host,logreason) ) if gline_bots: xchat.command('msg operserv gline 700h *@%s :%s' % (host, gline_message) ) def notice_cb(word, word_eol, userdata): "When clients connect to the server, check if their client matches & query them if so" if xchat.get_info('network') not in networks: return xchat.EAT_NONE if word[0][1:] not in servers: return xchat.EAT_NONE notice = word_eol[3][1:].strip() try: (nick, user, realname) = connectmsg.match(notice).groups() except: return xchat.EAT_NONE if nick.strip('_ ') in robotnicz and user.strip('_ ') in robotnicz: for name in realname.split(): if name.strip('_ ') not in robotnicz: log('unknown nick in realname: %s' % name) return xchat.EAT_NONE if query_bots: xchat.command('query %s' % nick ) if msg_bots: xchat.command('msg %s %s' % (nick, hi_message) ) def join_cb(word, word_eol, userdata): "When clients connect to the channel, check if their client matches & query them if so" (nick, user_host) = word[0][1:].split('!',1) if nick.strip('-_ ') not in robotnicz: return xchat.EAT_NONE (user, host) = user_host.split('@',1) user = user.strip('~') if user.strip('-_ ') not in robotnicz: return xchat.EAT_NONE channel = word[2][1:] if channel == '#turk': if query_bots: xchat.command('query %s' % nick ) if msg_bots: xchat.command('msg %s %s' % (nick, hi_message) ) def privmsg_cb(word, word_eol, userdata): "When people /msg us, check for one of several viral responses & if so harvest the url" if xchat.get_info('network') not in networks: return xchat.EAT_NONE if word[2][0] == '#' or word[2][0] == '&': #In a channel return xchat.EAT_NONE (nick, user_host) = word[0][1:].split('!',1) if nick.strip('_ ') not in robotnicz: return xchat.EAT_NONE (user, host) = user_host.split('@',1) user = user.strip('~') if user.strip('_ ') not in robotnicz: return xchat.EAT_NONE message = word_eol[3][1:].strip() if message in robotgreetz: xchat.prnt('Possible robot detected') elif message in robotspamz: xchat.prnt('Robot killed') gline( host, '%s spammed me: %s' % (word[0][1:], message) ) #~ if nick == xchat.get_info('channel') and close_query: #FIXME: Iterate through all contexts on the current server and #~ for c in xchat.get_list('channels'): #~ if c.type == 3: #~ c_user_host = c.context.get_info('topic') #~ (c_user, c_host) = user_host.split('@') #~ if user == c_user and host == c_host: #~ #c.context.command('close') else: try: url = urlexe.match(message).group(1) log('%s' % url, 'spamurllog') gline( host, '%s sent an exe url: %s' % (word[0][1:],url) ) return xchat.EAT_NONE except: xchat.command('msg %s %s' % (nick, apology_msg)) log('spammed a non-spambot, ooops: %s message: %s' % (word[0][1:], message)) return xchat.EAT_NONE def raw_cb(word, word_eol, userdata): xchat.prnt( 'raw_cb: %s' % word ) def loadlines(file): lines=[] f = open(file, 'rb') for line in f.readlines(): if line[-1] == "\n": lines.append(line.strip()) else: lines.append(line) f.close() return lines os.chdir('/home/pabs/.xchat2/spambotz/') robotnicz = loadlines(robotnicz_file) robotgreetz = loadlines(robotgreetz_file) robotspamz = loadlines(robotspamz_file) networks = loadlines(networks_file) servers = loadlines(servers_file) #xchat.hook_server('RAW LINE', raw_cb) xchat.hook_command('spambot', spambot_cb) xchat.hook_server('PRIVMSG', privmsg_cb) xchat.hook_server('NOTICE', notice_cb) xchat.hook_server('JOIN', join_cb) xchat.command('mode %s +c' % oper_nick ) xchat.command('join #bothunter' ) xchat.prnt('%s %s loaded' % (__module_name__, __module_version__))