diff --git a/Makefile b/Makefile index bf33555..a8d6ca0 100644 --- a/Makefile +++ b/Makefile @@ -1,12 +1,14 @@ DESTDIR = target +PYCDIR = $(DESTDIR)/usr/lib/python3.1/site-packages CTFDIR = $(DESTDIR)/usr/lib/ctf WWWDIR = $(DESTDIR)/usr/lib/www FAKE = fakeroot -s fake -i fake INSTALL = $(FAKE) install -PYC = config.pyc points.pyc teams.pyc +PYC = __init__.pyc +PYC += config.pyc points.pyc teams.pyc PYC += register.pyc scoreboard.pyc puzzler.pyc PYC += flagd.pyc pointsd.pyc pointscli.pyc PYC += histogram.pyc @@ -19,9 +21,11 @@ target: $(PYC) $(INSTALL) -d $(DESTDIR)/var/lib/ctf/disabled touch $(DESTDIR)/var/lib/ctf/disabled/survey - $(INSTALL) -d $(CTFDIR) - $(INSTALL) $(PYC) $(CTFDIR) - $(INSTALL) ctfd.py $(CTFDIR) + $(INSTALL) -d $(PYCDIR)/ctf + $(INSTALL) $(PYC) $(PYCDIR)/ctf + + $(INSTALL) -d $(DESTDIR)/usr/sbin + $(INSTALL) ctfd.py $(DESTDIR)/usr/sbin $(INSTALL) -d $(WWWDIR) $(INSTALL) index.html intro.html ctf.css grunge.png $(WWWDIR) @@ -36,6 +40,7 @@ target: $(PYC) rm -rf $(WWWDIR)/puzzler $(INSTALL) -d $(WWWDIR)/puzzler + $(INSTALL) -d $(CTFDIR) ./mkpuzzles.py --htmldir=$(WWWDIR)/puzzler --keyfile=$(CTFDIR)/puzzler.keys ctf.tce: target @@ -45,5 +50,8 @@ clean: rm -rf target rm -f fake ctf.tce $(PYC) -%.pyc: %.py - python3 -c 'import $*' +ctf/%.pyc: ctf/%.py + python3 -c 'from ctf import $(notdir $*)' + +%.pyc: ctf/%.pyc + cp $< $@ diff --git a/ctf/__init__.py b/ctf/__init__.py new file mode 100755 index 0000000..467e41a --- /dev/null +++ b/ctf/__init__.py @@ -0,0 +1,33 @@ +#! /usr/bin/env python3 + +import asynchat +import asyncore +import socket + +class Flagger(asynchat.async_chat): + """Connection to flagd""" + + def __init__(self, addr, auth): + asynchat.async_chat.__init__(self) + self.create_socket(socket.AF_INET, socket.SOCK_STREAM) + self.connect((addr, 6668)) + self.push(auth + b'\n') + self.flag = None + + def handle_read(self): + msg = self.recv(4096) + raise ValueError("Flagger died: %r" % msg) + + def handle_error(self): + # If we lose the connection to flagd, nobody can score any + # points. Terminate everything. + asyncore.close_all() + asynchat.async_chat.handle_error(self) + + def set_flag(self, team): + if team: + eteam = team.encode('utf-8') + else: + eteam = b'' + self.push(eteam + b'\n') + self.flag = team diff --git a/config.py b/ctf/config.py similarity index 100% rename from config.py rename to ctf/config.py diff --git a/flagd.py b/ctf/flagd.py similarity index 95% rename from flagd.py rename to ctf/flagd.py index 9cdd5bb..24bceab 100755 --- a/flagd.py +++ b/ctf/flagd.py @@ -8,11 +8,11 @@ import time import hmac import optparse import os -import points -import pointscli -import teams -import config import traceback +from . import teams +from . import points +from . import pointscli +from . import config key = b'My First Shared Secret (tm)' def hexdigest(data): @@ -21,7 +21,7 @@ def hexdigest(data): flags_dir = config.get('global', 'flags_dir') class Submitter(asyncore.dispatcher): - def __init__(self, host='', port=6667): + def __init__(self, host='127.0.0.1', port=6667): asyncore.dispatcher.__init__(self) self.create_socket(socket.AF_INET, socket.SOCK_DGRAM) self.connect((host, port)) @@ -82,7 +82,7 @@ class Submitter(asyncore.dispatcher): class Listener(asyncore.dispatcher): - def __init__(self, connection_factory, host='localhost', port=6668): + def __init__(self, connection_factory, host='', port=6668): asyncore.dispatcher.__init__(self) self.create_socket(socket.AF_INET, socket.SOCK_STREAM) self.set_reuse_addr() diff --git a/game.py b/ctf/game.py similarity index 94% rename from game.py rename to ctf/game.py index 9dcd251..8346735 100755 --- a/game.py +++ b/ctf/game.py @@ -6,8 +6,9 @@ import asynchat import socket import traceback import time -import teams from errno import EPIPE +from . import teams +from . import Flagger # Heartbeat frequency (in seconds) @@ -38,35 +39,6 @@ class Listener(asyncore.dispatcher): return True -class Flagger(asynchat.async_chat): - """Connection to flagd""" - - def __init__(self, addr, auth): - asynchat.async_chat.__init__(self) - self.create_socket(socket.AF_INET, socket.SOCK_STREAM) - self.connect(addr) - self.push(auth + b'\n') - self.flag = None - - def handle_read(self): - msg = self.recv(4096) - raise ValueError("Flagger died: %r" % msg) - - def handle_error(self): - # If we lose the connection to flagd, nobody can score any - # points. Terminate everything. - asyncore.close_all() - asynchat.async_chat.handle_error(self) - - def set_flag(self, team): - if team: - eteam = team.encode('utf-8') - else: - eteam = b'' - self.push(eteam + b'\n') - self.flag = team - - class Manager: """Contest manager. diff --git a/histogram.py b/ctf/histogram.py similarity index 96% rename from histogram.py rename to ctf/histogram.py index 1afe1f0..542b534 100755 --- a/histogram.py +++ b/ctf/histogram.py @@ -1,11 +1,11 @@ #! /usr/bin/env python3 -import points import time import os import tempfile -import teams -import config +from . import points +from . import teams +from . import config pngout = config.datafile('histogram.png') diff --git a/points.py b/ctf/points.py similarity index 99% rename from points.py rename to ctf/points.py index 2f419c9..3879a02 100755 --- a/points.py +++ b/ctf/points.py @@ -4,9 +4,9 @@ import socket import hmac import struct import io -import teams -import config import os +from . import teams +from . import config ## ## Authentication diff --git a/pointscli.py b/ctf/pointscli.py similarity index 98% rename from pointscli.py rename to ctf/pointscli.py index d32b0a1..94133e9 100755 --- a/pointscli.py +++ b/ctf/pointscli.py @@ -2,9 +2,9 @@ import optparse import select -import points import socket import time +from . import points def makesock(host): s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) diff --git a/pointsd.py b/ctf/pointsd.py similarity index 94% rename from pointsd.py rename to ctf/pointsd.py index bbb0878..85328e7 100755 --- a/pointsd.py +++ b/ctf/pointsd.py @@ -3,10 +3,11 @@ import asyncore import socket import struct -import points import time +from . import points +from . import config -house = 'dirtbags' +house = config.get('global', 'house_team') class MyHandler(asyncore.dispatcher): def __init__(self, port=6667): diff --git a/puzzler.py b/ctf/puzzler.py similarity index 98% rename from puzzler.py rename to ctf/puzzler.py index 027ac8d..48e487e 100755 --- a/puzzler.py +++ b/ctf/puzzler.py @@ -7,9 +7,9 @@ import re import sys import http.cookies from urllib.parse import quote, unquote -import config -import pointscli -import teams +from . import config +from . import pointscli +from . import teams datafile = config.datafile('puzzler.dat') keysfile = config.get('puzzler', 'keys_file') diff --git a/register.py b/ctf/register.py similarity index 98% rename from register.py rename to ctf/register.py index c0efe98..422b798 100755 --- a/register.py +++ b/ctf/register.py @@ -2,10 +2,10 @@ import cgitb; cgitb.enable() import cgi -import teams import fcntl import string -import config +from . import teams +from . import config def main(): print('Content-type: text/html') diff --git a/scoreboard.py b/ctf/scoreboard.py similarity index 97% rename from scoreboard.py rename to ctf/scoreboard.py index 1b80eb6..43a1f96 100755 --- a/scoreboard.py +++ b/ctf/scoreboard.py @@ -2,10 +2,10 @@ import cgitb; cgitb.enable() import os -import config -import teams -import points import sys +from . import config +from . import teams +from . import points flags_dir = config.get('global', 'flags_dir') house_team = config.get('global', 'house_team') diff --git a/teams.py b/ctf/teams.py similarity index 98% rename from teams.py rename to ctf/teams.py index 4cba5ca..4f73799 100755 --- a/teams.py +++ b/ctf/teams.py @@ -2,9 +2,9 @@ import fcntl import time -import config import os from urllib.parse import quote, unquote +from . import config house = config.get('global', 'house_team') passwdfn = config.get('global', 'passwd') diff --git a/kevin/Makefile b/kevin/Makefile index 36b41f9..5ced261 100644 --- a/kevin/Makefile +++ b/kevin/Makefile @@ -8,8 +8,8 @@ kevin.tce: target target: kevin.py irc.pyc run log.run - $(INSTALL) -d target/usr/lib/ctf - $(INSTALL) kevin.py irc.py target/usr/lib/ctf + $(INSTALL) -d target/usr/lib/ctf/kevin + $(INSTALL) kevin.py irc.py target/usr/lib/ctf/kevin $(INSTALL) --owner=100 -d target/var/lib/ctf/kevin/tokens diff --git a/kevin/ctf b/kevin/ctf new file mode 120000 index 0000000..8d47818 --- /dev/null +++ b/kevin/ctf @@ -0,0 +1 @@ +../ctf \ No newline at end of file diff --git a/kevin/kevin.py b/kevin/kevin.py index be33038..1548858 100755 --- a/kevin/kevin.py +++ b/kevin/kevin.py @@ -7,38 +7,10 @@ import asynchat import socket import asyncore from urllib.parse import quote_plus as quote +from ctf import Flagger nobody = '\002[nobody]\002' -class Flagger(asynchat.async_chat): - """Connection to flagd""" - - def __init__(self, addr, auth): - asynchat.async_chat.__init__(self) - self.create_socket(socket.AF_INET, socket.SOCK_STREAM) - self.connect((addr, 6668)) - self.push(auth + b'\n') - self.flag = None - - def handle_read(self): - msg = self.recv(4096) - raise ValueError("Flagger died: %r" % msg) - - def handle_error(self): - # If we lose the connection to flagd, nobody can score any - # points. Terminate everything. - asyncore.close_all() - asynchat.async_chat.handle_error(self) - - def set_flag(self, team): - if team: - eteam = team.encode('utf-8') - else: - eteam = b'' - self.push(eteam + b'\n') - self.flag = team - - class Kevin(irc.Bot): def __init__(self, host, flagger, tokens, victims): irc.Bot.__init__(self, host, diff --git a/kevin/run b/kevin/run index 62c4a5c..b596d3c 100755 --- a/kevin/run +++ b/kevin/run @@ -2,4 +2,4 @@ [ -f /var/lib/ctf/disabled/kevin ] && exit 0 -exec envuidgid ctf /usr/lib/ctf/kevin.py --victims=/var/lib/ctf/kevin/victims.txt --tokens=/var/lib/ctf/kevin/tokens +exec envuidgid ctf /usr/lib/ctf/kevin/kevin.py --victims=/var/lib/ctf/kevin/victims.txt --tokens=/var/lib/ctf/kevin/tokens diff --git a/puzzler.cgi b/puzzler.cgi index 3fde24a..72e091c 100755 --- a/puzzler.cgi +++ b/puzzler.cgi @@ -1,7 +1,4 @@ #! /usr/bin/env python3 -import cgitb; cgitb.enable() -import sys -sys.path.insert(0, '/usr/lib/ctf') -import puzzler +from ctf import puzzler puzzler.main() diff --git a/pwnables/fingerd/Makefile b/pwnables/fingerd/Makefile new file mode 100644 index 0000000..74a0f1b --- /dev/null +++ b/pwnables/fingerd/Makefile @@ -0,0 +1 @@ +all: in.fingerd diff --git a/pwnables/fingerd/in.fingerd.c b/pwnables/fingerd/in.fingerd.c new file mode 100644 index 0000000..cb5d9e7 --- /dev/null +++ b/pwnables/fingerd/in.fingerd.c @@ -0,0 +1,38 @@ +#include + +int +main(int argc, char *argv) +{ + char user[256]; + char path[512]; + char *data; + FILE *f; + size_t count; + int i; + + if (NULL == gets(user)) { + return 0; + } + for (data = user; *data; data += 1) { + if ('\r' == *data) { + *data = 0; + } + } + if (0 == user[0]) { + printf("Nobody's home.\n"); + return 0; + } + + sprintf(path, "/home/%s/.plan", user); + f = fopen(path, "r"); + if (NULL == f) { + printf("No such user.\n"); + return 0; + } + + data = path; + while (count = fread(data, sizeof(*data), 1, f)) { + fwrite(data, count, 1, stdout); + } + return 0; +} diff --git a/pwnables/fingerd/run b/pwnables/fingerd/run new file mode 100755 index 0000000..4088271 --- /dev/null +++ b/pwnables/fingerd/run @@ -0,0 +1,3 @@ +#! /bin/sh + +exec tcpsvd 0 79 /usr/sbin/in.fingerd diff --git a/pwnables/tftpd/run b/pwnables/tftpd/run new file mode 100755 index 0000000..bcba031 --- /dev/null +++ b/pwnables/tftpd/run @@ -0,0 +1,3 @@ +#! /bin/sh + +exec udpsvd 0 69 tftpd /var/lib/tftp diff --git a/register.cgi b/register.cgi index e6db08f..526d6d4 100755 --- a/register.cgi +++ b/register.cgi @@ -1,6 +1,4 @@ #! /usr/bin/env python3 -import sys -sys.path.insert(0, '/usr/lib/ctf') -import register +from ctf import register register.main() diff --git a/run.ctfd b/run.ctfd index 6b74b93..b6a36c1 100755 --- a/run.ctfd +++ b/run.ctfd @@ -1,4 +1,4 @@ #! /bin/sh -exec envuidgid ctf /usr/lib/ctf/ctfd.py 2>&1 +exec envuidgid ctf /usr/sbin/ctfd.py 2>&1 diff --git a/scoreboard.cgi b/scoreboard.cgi index 4049b89..7c56d45 100755 --- a/scoreboard.cgi +++ b/scoreboard.cgi @@ -1,6 +1,4 @@ #! /usr/bin/env python3 -import sys -sys.path.insert(0, '/usr/lib/ctf') -import scoreboard +from ctf import scoreboard scoreboard.main()