diff --git a/ctf.css b/ctf.css index 4131ef8..d3c033a 100644 --- a/ctf.css +++ b/ctf.css @@ -80,4 +80,16 @@ p { .solved { text-decoration: line-through; -} \ No newline at end of file +} + +table.pollster { + margin-left: 5em; +} + +table.pollster td { + padding: 2px 1em 2px 5px; +} + +table.pollster thead { + font-weight: bold; +} diff --git a/pollster/pollster.py b/pollster/pollster.py index ca31dc9..e0bb62b 100755 --- a/pollster/pollster.py +++ b/pollster/pollster.py @@ -5,19 +5,14 @@ import re import sys import time import socket -import urllib.request +import traceback # TODO: -# special stops for http and tftp? -# get start time and end time of poll, sleep(60-exectime) -# what to do about exceptions -# no nested dicts # scoring interface # config interface -# html that uses the proper css -DEBUG = True -POLL_INTERVAL = 2 +DEBUG = False +POLL_INTERVAL = 60 IP_DIR = 'iptest/' REPORT_PATH = 'iptest/pollster.html' SOCK_TIMEOUT = 0.5 @@ -26,13 +21,14 @@ def socket_poll(ip, port, msg, prot, max_recv=1): ''' Connect via socket to the specified : using the specified , send the specified and return the response or None if something went wrong. specifies - how many times to read from the socket. ''' + how many times to read from the socket (default to once). ''' # create a socket try: sock = socket.socket(socket.AF_INET, prot) except Exception as e: - print('pollster: create socket failed') + print('pollster: create socket failed (%s)' % e) + traceback.print_exc() return None sock.settimeout(SOCK_TIMEOUT) @@ -41,10 +37,12 @@ def socket_poll(ip, port, msg, prot, max_recv=1): try: sock.connect((ip, port)) except socket.timeout as e: - print('pollster: attempt to connect to %s:%d timed out' % (ip, port)) + print('pollster: attempt to connect to %s:%d timed out (%s)' % (ip, port, e)) + traceback.print_exc() return None except Exception as e: - print('pollster: attempt to connect to %s:%d failed' % (ip, port)) + print('pollster: attempt to connect to %s:%d failed (%s)' % (ip, port, e)) + traceback.print_exc() return None # send something @@ -64,10 +62,13 @@ def socket_poll(ip, port, msg, prot, max_recv=1): resp += data.decode('utf-8') max_recv -= 1 sock.close() + except socket.timeout as e: - print('pollster: timed out waiting for a response from %s:%d' % (ip, port)) + print('pollster: timed out waiting for a response from %s:%d (%s)' % (ip, port, e)) + traceback.print_exc() except Exception as e: - print('pollster: receive from %s:%d failed' % (ip, port)) + print('pollster: receive from %s:%d failed (%s)' % (ip, port, e)) + traceback.print_exc() if len(resp) == 0: return None @@ -79,21 +80,21 @@ def socket_poll(ip, port, msg, prot, max_recv=1): # if (a) the service is not up, (b) it doesn't return a valid team name. def poll_fingerd(ip): - ''' Poll the fingerd service. ''' + ''' Poll the fingerd service. Returns None or a team name. ''' resp = socket_poll(ip, 79, b'flag\n', socket.SOCK_STREAM) if resp is None: return None return resp.strip('\r\n') def poll_noted(ip): - ''' Poll the noted service. ''' + ''' Poll the noted service. Returns None or a team name. ''' resp = socket_poll(ip, 4000, b'rflag\n', socket.SOCK_STREAM) if resp is None: return None return resp.strip('\r\n') def poll_catcgi(ip): - ''' Poll the cat.cgi web service. ''' + ''' Poll the cat.cgi web service. Returns None or a team name. ''' request = bytes('GET /cat.cgi/flag HTTP/1.1\r\nHost: %s\r\n\r\n' % ip, 'ascii') resp = socket_poll(ip, 80, request, socket.SOCK_STREAM, 3) if resp is None: @@ -115,7 +116,7 @@ def poll_catcgi(ip): return content[1].strip('\r\n') def poll_tftpd(ip): - ''' Poll the tftp service. ''' + ''' Poll the tftp service. Returns None or a team name. ''' resp = socket_poll(ip, 69, b'\x00\x01' + b'flag' + b'\x00' + b'octet' + b'\x00', socket.SOCK_DGRAM) if resp is None: return None @@ -137,15 +138,28 @@ POLLS = { ip_re = re.compile('(\d{1,3}\.){3}\d{1,3}') # loop forever -while(True): +while True: + + t_start = time.time() # gather the list of IPs to poll try: ips = os.listdir(IP_DIR) except Exception as e: - print('pollster: could not list dir %s' % IP_DIR) + print('pollster: could not list dir %s (%s)' % (IP_DIR, e)) + traceback.print_exc() + + try: + os.remove(REPORT_PATH) + except Exception as e: + pass + + out = open(REPORT_PATH, 'w') + out.write('\n\n') + out.write('Pollster Results\n') + out.write('\n') + out.write('\n

Polling Results

\n') - results = {} for ip in ips: # check file name format is ip @@ -153,49 +167,45 @@ while(True): continue # remove the file - #try: - # os.remove(os.path.join(IP_DIR, ip)) - #except Exception as e: - # print('pollster: could not remove %s' % os.path.join(IP_DIR, ip)) + try: + os.remove(os.path.join(IP_DIR, ip)) + except Exception as e: + print('pollster: could not remove %s' % os.path.join(IP_DIR, ip)) + traceback.print_exc() - results[ip] = {} + results = {} if DEBUG is True: print('ip: %s' % ip) + out.write('

%s

\n' % ip) + out.write('\n') + out.write('\n') + # perform polls for service,func in POLLS.items(): team = func(ip) if team is None: team = 'dirtbags' - results[ip][service] = team + if DEBUG is True: + print('\t%s - %s' % (service, team)) - if DEBUG is True: - for k,v in results[ip].items(): - print('\t%s - %s' % (k,v)) + out.write('\n' % (service, team)) - if DEBUG is True: - print('+-----------------------------------------+') - - # allocate points - - # generate html report - out = open(REPORT_PATH, 'w') - out.write('\n<head>Polling Results</head>\n') - out.write('\n

Polling Results

\n') - - for ip in results.keys(): - out.write('

%s

\n' % ip) - out.write('
Service NameFlag Holder
%s%s
\n') - out.write('\n') - for service,flag_holder in results[ip].items(): - out.write('\n' % (service, flag_holder)) out.write('
Service NameFlag Holder
%s%s
\n') + if DEBUG is True: + print('+-----------------------------------------+') + + t_end = time.time() + exec_time = int(t_end - t_start) + sleep_time = POLL_INTERVAL - exec_time + + out.write('

Next poll in: %ds

\n' % sleep_time) out.write('\n\n') out.close() - - # sleep until its time to poll again - time.sleep(POLL_INTERVAL) + + # sleep until its time to poll again + time.sleep(sleep_time)