#!/usr/bin/env python # -*- coding: utf-8 -*- """ HTN Credit Juggler ================== A tool for the HackTheNet_ browser game to juggle with credits, causing magic things to happen. Original Perl script created by Gizmor. Improved, refurbished and eventually ported to Python by Y0Gi. Tested with HTN version 2.5 Beta. :Copyright: 2005 Gizmor, Y0Gi :Date: 12-Dec-2005 :License: GNU General Public License :Version: 0.4 .. _HackTheNet: http://www.hackthenet.org/ """ from optparse import OptionParser import re import sys import threading import urllib import urllib2 # Configuration USER_AGENT = ('Mozilla/5.0 (X11; U; Linux i686; de-DE; rv:1.7.12)' ' Gecko/20051010 Firefox/1.0.7') URL_BASE = 'http://htn25.unkreativ.org/_htn.php' TIMEOUT = 4.0 def repay_credit(url_repay, cid): urllib2.urlopen(url_repay + cid).close() print "Credit '%s' repayed." % cid def main(): print 'HTN Credit Juggler 0.4 by Gizmor and Y0Gi\n' # Create option parser and define options. parser = OptionParser( usage='%prog [options] <session ID>', version='HTN Credit Juggler 0.4', description='HTN Credit Juggler juggles with credits,' 'causing magic things to happen.') parser.add_option('-c', '--credit-count', type='int', dest='credit_count', default=3, help='number of credits (1-3) to raise (default: 3)', metavar='NUM') parser.add_option('-p', '--passes', type='int', dest='pass_count', default=50, help='number of passes (default: 50)', metavar='NUM') # Process options and arguments. options, args = parser.parse_args() if len(args) != 1: parser.print_help() parser.exit() session_id = args[0] # Set URLs. url_bank = '%s/bank/start?sid=%s' % (URL_BASE, session_id) url_raise = '%s/bank/raisecredit?sid=%s&secret=' % (URL_BASE, session_id) url_repay = '%s/bank/repaycredit?sid=%s&id=' % (URL_BASE, session_id) # Precompile regular expression patterns. re_raise_secret = re.compile('raisecredit\?.*?secret=([0-9a-f]+?)"') re_max_credit_amount = re.compile('\(max. ([\d\.]+) Credits pro Kredit\)') re_credit_id = re.compile('repaycredit\?.*?id=([0-9a-f]+?)"') # Customize the URL opener. opener = urllib2.build_opener() opener.addheaders = [('User-Agent', USER_AGENT), ('Referer', URL_BASE)] urllib2.install_opener(opener) # Main loop for pass_num in range(1, options.pass_count + 1): try: print '--- Pass #%d ---' % pass_num # Raise credits. for i in range(options.credit_count): # Retrieve HTML form. try: data = urllib2.urlopen(url_bank).read() except urllib2.URLError, e: print 'Could not retrieve HTML form:', e continue # Extract challenge code and maximum # credit amount from document. try: challenge = re_raise_secret.search(data).group(1) except AttributeError: print 'Could not extract challenge code.' continue try: credit_amount = re_max_credit_amount.search(data) \ .group(1).replace('.', '') except AttributeError: print 'Could not extract maximum credit amount.' continue # Actually raise a credit. try: req = urllib2.Request( url_raise + challenge, urllib.urlencode({'credits': credit_amount})) urllib2.urlopen(req).close() print 'Credit in the amount of %sc raised.' \ % credit_amount except urllib2.URLError, e: print 'Could not raise credit:', e # Fetch IDs of raised credits. try: data = urllib2.urlopen(url_bank).read() except urllib2.URLError, e: sys.exit('Could not fetch credits list: ' + str(e)) credit_ids = re_credit_id.findall(data) print 'Currently raised credits: ', ', '.join(credit_ids) # Repay credits. threads = [] for cid in credit_ids: threads.append(threading.Thread( target=repay_credit, args=(url_repay, cid))) threads[-1].start() for t in threads: t.join(TIMEOUT) except KeyboardInterrupt: sys.exit('Aborting ...' ' you might need to kill the process manually.') if __name__ == '__main__': main()