Merge branch 'master' of /var/projects/gctf

This commit is contained in:
Paul S. Ferrell 2009-10-07 10:51:02 -06:00
commit aa3e660ae6
41 changed files with 371 additions and 20 deletions

View File

@ -11,8 +11,7 @@ PYC = __init__.pyc
PYC += config.pyc points.pyc teams.pyc PYC += config.pyc points.pyc teams.pyc
PYC += register.pyc scoreboard.pyc puzzler.pyc PYC += register.pyc scoreboard.pyc puzzler.pyc
PYC += flagd.pyc pointsd.pyc pointscli.pyc PYC += flagd.pyc pointsd.pyc pointscli.pyc
PYC += histogram.pyc PYC += histogram.pyc irc.pyc
#PYC += roshambo.pyc game.pyc
all: ctf.tce all: ctf.tce

View File

@ -64,6 +64,10 @@ th, td {
vertical-align: top; vertical-align: top;
} }
.scoreboard {
background: #222;
}
.scoreboard td { .scoreboard td {
height: 400px; height: 400px;
} }

View File

@ -7,6 +7,8 @@ import sys
import traceback import traceback
import time import time
channel_prefixes = '+#&'
class IRCHandler(asynchat.async_chat): class IRCHandler(asynchat.async_chat):
"""IRC Server connection. """IRC Server connection.
@ -256,7 +258,7 @@ class User(Recipient):
return 'User(%s, %s, %s)' % (self.name(), self.user, self.host) return 'User(%s, %s, %s)' % (self.name(), self.user, self.host)
def recipient(interface, name): def recipient(interface, name):
if name[0] in ['&', '#', '+']: if name[0] in channel_prefixes:
return Channel(interface, name) return Channel(interface, name)
else: else:
return User(interface, name, None, None) return User(interface, name, None, None)
@ -327,9 +329,8 @@ class SmartIRCHandler(IRCHandler):
# PRIVMSG ['neale!~user@127.0.0.1', 'PRIVMSG', '#hydra'] firebot, foo # PRIVMSG ['neale!~user@127.0.0.1', 'PRIVMSG', '#hydra'] firebot, foo
# PRIVMSG ['neale!~user@127.0.0.1', 'PRIVMSG', 'firebot'] firebot, foo # PRIVMSG ['neale!~user@127.0.0.1', 'PRIVMSG', 'firebot'] firebot, foo
try: try:
if args[2][0] in '#&':
forum = self.recipient(args[2]) forum = self.recipient(args[2])
else: if not forum.is_channel():
forum = sender forum = sender
addl = (text,) addl = (text,)
except IndexError: except IndexError:

View File

@ -90,7 +90,7 @@ def incdict(dict, key, amt=1):
dict[key] = dict.get(key, 0) + amt dict[key] = dict.get(key, 0) + amt
class Storage: class Storage:
def __init__(self, fn=None): def __init__(self, fn=None, fix=False):
if not fn: if not fn:
fn = config.datafile('scores.dat') fn = config.datafile('scores.dat')
self.teams = set() self.teams = set()
@ -100,6 +100,8 @@ class Storage:
self.f = io.BytesIO() self.f = io.BytesIO()
# Read stored scores # Read stored scores
truncate = False
lastgood = 0
try: try:
f = open(fn, 'rb') f = open(fn, 'rb')
while True: while True:
@ -113,7 +115,13 @@ class Storage:
team = b[catlen:].decode('utf-8') team = b[catlen:].decode('utf-8')
req = (when, cat, team, score) req = (when, cat, team, score)
self.add(req, False) self.add(req, False)
lastgood = f.tell()
f.close() f.close()
except struct.error:
if fix:
truncate = True
else:
raise
except IOError: except IOError:
pass pass
@ -122,6 +130,10 @@ class Storage:
except IOError: except IOError:
self.f = None self.f = None
if truncate:
self.f.seek(lastgood)
self.f.truncate()
def __len__(self): def __len__(self):
return len(self.log) return len(self.log)

View File

@ -14,7 +14,7 @@ class MyHandler(asyncore.dispatcher):
asyncore.dispatcher.__init__(self) asyncore.dispatcher.__init__(self)
self.create_socket(socket.AF_INET, socket.SOCK_DGRAM) self.create_socket(socket.AF_INET, socket.SOCK_DGRAM)
self.bind(('', port)) self.bind(('', port))
self.store = points.Storage() self.store = points.Storage(fix=True)
self.acked = set() self.acked = set()
self.outq = [] self.outq = []

18
ctfd.py
View File

@ -1,13 +1,13 @@
#! /usr/bin/env python3 #! /usr/bin/env python3
import asyncore import asyncore
import pointsd
import game
import flagd
import histogram
import config
import os import os
import sys import sys
import optparse
from ctf import pointsd
from ctf import flagd
from ctf import histogram
from ctf import config
do_reap = False do_reap = False
@ -27,6 +27,14 @@ def sigchld(signum, frame):
do_reap = True do_reap = True
def main(): def main():
p = optparse.OptionParser()
p.add_option('-p', '--genpass', dest='cat', default=None,
help='Generate a flagger password for the given category')
opts, args = p.parse_args()
if opts.cat:
print('%s:::%s' % (opts.cat, flagd.hexdigest(opts.cat.encode('utf-8'))))
return
pointsrv = pointsd.start() pointsrv = pointsd.start()
flagsrv = flagd.start() flagsrv = flagd.start()

View File

@ -7,11 +7,10 @@ kevin.tce: target
$(FAKE) sh -c 'cd target && tar -czf - --exclude=placeholder --exclude=*~ .' > $@ $(FAKE) sh -c 'cd target && tar -czf - --exclude=placeholder --exclude=*~ .' > $@
target: kevin.py irc.pyc run log.run target: kevin.py run log.run
$(INSTALL) -d target/usr/lib/ctf/kevin $(INSTALL) -D kevin.py target/usr/bin/kevin.py
$(INSTALL) kevin.py irc.py target/usr/lib/ctf/kevin
$(INSTALL) --owner=100 -d target/var/lib/ctf/kevin/tokens $(INSTALL) --owner=100 -d target/var/lib/kevin/tokens
$(INSTALL) -d target/var/service/kevin $(INSTALL) -d target/var/service/kevin
$(INSTALL) run target/var/service/kevin/run $(INSTALL) run target/var/service/kevin/run

View File

@ -60,8 +60,8 @@ class Kevin(irc.Bot):
def cmd_PRIVMSG(self, sender, forum, addl): def cmd_PRIVMSG(self, sender, forum, addl):
text = addl[0] text = addl[0]
if text.startswith('!'): if text.startswith('!'):
parts = text[1:].lower().split(' ', 1) parts = text[1:].split(' ', 1)
cmd = parts[0] cmd = parts[0].lower()
if len(parts) > 1: if len(parts) > 1:
args = parts[1] args = parts[1]
else: else:

View File

@ -2,4 +2,4 @@
[ -f /var/lib/ctf/disabled/kevin ] && exit 0 [ -f /var/lib/ctf/disabled/kevin ] && exit 0
exec envuidgid ctf /usr/lib/ctf/kevin/kevin.py --victims=/var/lib/ctf/kevin/victims.txt --tokens=/var/lib/ctf/kevin/tokens exec envuidgid ctf /usr/bin/kevin.py --victims=/var/lib/kevin/victims.txt --tokens=/var/lib/kevin/tokens

BIN
puzzles/posters/10/img.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 184 KiB

View File

@ -0,0 +1 @@
<img src = "img.png" alt = "" width = "638" height = "825" />

1
puzzles/posters/10/key Normal file
View File

@ -0,0 +1 @@
You're well on your way :)

View File

@ -0,0 +1 @@
<strong>Puzzle:</strong> &nbsp;Braille

1
puzzles/posters/125/key Normal file
View File

@ -0,0 +1 @@
‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽

BIN
puzzles/posters/15/img.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 362 KiB

View File

@ -0,0 +1 @@
<img src = "img.png" alt = "" width = "517" height = "731" />

1
puzzles/posters/15/key Normal file
View File

@ -0,0 +1 @@
-462766

BIN
puzzles/posters/5/img.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

View File

@ -0,0 +1 @@
<img src = "img.png" alt = "" width = "558" height = "782" />

1
puzzles/posters/5/key Normal file
View File

@ -0,0 +1 @@
3acd767f2717b84076cdcd18e882f01d

View File

@ -0,0 +1,7 @@
Little-known fact<br />
Is that the<br />
Best answer is<br />
Right here.<br />
And if you know what the key is, you'll know where to go next.<br />
Really, it's that simple.<br />
You need to speak the key at the front desk.<br />

1
puzzles/posters/50/key Normal file
View File

@ -0,0 +1 @@
LIBRARY

View File

@ -0,0 +1 @@
&#9873; _ _ _ _ &#9698; _ _ _ _ &#9829; _ _ _ _ &#9733; _ _ _ _ &#9685; _ _ _ _

1
puzzles/posters/75/key Normal file
View File

@ -0,0 +1 @@
⚑ ◢ ◕ ★ ♥ ◢ ♥ ⚑ ◕ ★ ♥ ◕ ★ ♥ ⚑ ★ ⚑ ◢ ♥ ◢ ◕ ◕ ◢ ★ ⚑

View File

@ -0,0 +1,3 @@
<pre>
04 aa 12 7f 99 03 ed c1 22 __ dc be e1 45 94
</pre>

1
puzzles/sequence/450/key Normal file
View File

@ -0,0 +1 @@
05

29
pwnables/Makefile Normal file
View File

@ -0,0 +1,29 @@
CGI = cat.cgi
TARGET = $(CURDIR)/target
FAKE = fakeroot -s $(CURDIR)/fake -i $(CURDIR)/fake
INSTALL = $(FAKE) install
all: 99-pwnables.tce
99-pwnables.tce: target
$(FAKE) sh -c 'cd target && tar -czf - --exclude=placeholder --exclude=*~ .' > $@
target:
$(INSTALL) -d $(TARGET)
(cd skel; tar cf - .) | (cd $(TARGET); tar xf -)
$(MAKE) -C daemons TARGET=$(TARGET) install
$(INSTALL) -d $(TARGET)/usr/lib/www
$(INSTALL) $(CGI) $(TARGET)/usr/lib/www
$(INSTALL) -D flag $(TARGET)/var/lib/tftp/flag
$(INSTALL) -D flag $(TARGET)/var/lib/notes/flag
$(INSTALL) -D flag $(TARGET)/home/flag/.plan
clean:
rm -rf target

6
pwnables/cat.cgi Executable file
View File

@ -0,0 +1,6 @@
#! /bin/sh
echo 'Content-type: text/plain'
echo
cat .$PATH_INFO

21
pwnables/daemons/Makefile Normal file
View File

@ -0,0 +1,21 @@
SBIN = in.fingerd in.noted
BIN = notecli
TARGET ?= $(CURDIR)/target
FAKE = fakeroot -s $(CURDIR)/fake -i $(CURDIR)/fake
INSTALL = $(FAKE) install
all: $(SBIN) $(BIN)
install: all
$(INSTALL) -d $(TARGET)/usr/sbin
$(INSTALL) -s $(SBIN) $(TARGET)/usr/sbin
$(INSTALL) -d $(TARGET)/usr/bin
$(INSTALL) -s $(BIN) $(TARGET)/usr/bin
$(INSTALL) -d $(TARGET)/var/service/fingerd
$(INSTALL) run.fingerd $(TARGET)/var/service/fingerd/run
$(INSTALL) -d $(TARGET)/var/service/noted
$(INSTALL) run.noted $(TARGET)/var/service/noted/run

View File

@ -0,0 +1,44 @@
#include <syslog.h>
#include <stdio.h>
int
main(int argc, char *argv)
{
char user[256];
char path[512];
char *data;
FILE *f;
size_t count;
int i;
char *peer = getenv("REMOTEADDR");
openlog("in.fingerd", LOG_PID, LOG_USER);
if (NULL == gets(user)) {
return 0;
}
for (data = user; *data; data += 1) {
if ('\r' == *data) {
*data = 0;
}
}
if (peer) {
syslog(LOG_INFO, "%s requests %s", peer, user);
}
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;
}

View File

@ -0,0 +1,55 @@
#include <stdio.h>
#include <syslog.h>
void
readntrim(char *s)
{
gets(s);
for (; *s; s++) {
switch (*s) {
case '\n':
case '\r':
*s = 0;
}
}
}
int
main(int argc, char *argv)
{
int cmd;
char line[4096];
char note[512];
FILE *f = NULL;
char *peer = getenv("REMOTEADDR");
openlog("in.noted", LOG_PID, LOG_USER);
switch (getc(stdin)) {
case EOF:
return 0;
case 'r':
readntrim(note);
if (peer) {
syslog(LOG_INFO, "%s read %s", peer, note);
}
f = fopen(note, "r");
while (fgets(line, sizeof(line), f)) {
fputs(line, stdout);
}
fclose(f);
break;
case 'w':
readntrim(note);
if (peer) {
syslog(LOG_INFO, "%s write %s", peer, note);
}
f = fopen(note, "w");
while (gets(line)) {
fputs(line, f);
}
fclose(f);
break;
}
return 0;
}

View File

@ -0,0 +1,90 @@
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <string.h>
int
open_connection(char *host, int port)
{
struct sockaddr_in addr;
struct hostent *h;
int fd;
if (! inet_aton(host, &(addr.sin_addr))) {
if (!(h = gethostbyname(host))) {
return -1;
} else {
memcpy(&(addr.sin_addr), h->h_addr, h->h_length);
}
}
fd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
if (fd == -1) {
return -1;
}
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
if (connect(fd, (struct sockaddr *)&addr, sizeof(addr))) {
close(fd);
return -1;
}
return fd;
}
void
clean(char *s)
{
for (; *s; s++) {
switch (*s) {
case '/':
case '.':
*s = '_';
}
}
}
int
main(int argc, char *argv[])
{
int fd;
char s[4096];
ssize_t len;
if (4 != argc) {
printf("Usage: %s HOST NOTE COMMAND\n", argv[0]);
printf("\n");
printf(" COMMAND must be 'r' (read) or 'w' (write).\n");
printf(" For w, input is taken from stdin.\n");
return 1;
}
fd = open_connection(argv[1], 4000);
clean(argv[2]);
switch (argv[3][0]) {
case 'r':
write(fd, "r", 1);
write(fd, argv[2], strlen(argv[2]));
write(fd, "\n", 1);
do {
len = read(fd, s, sizeof(s));
write(1, s, len);
} while (len);
break;
case 'w':
write(fd, "w", 1);
write(fd, argv[2], strlen(argv[2]));
write(fd, "\n", 1);
do {
len = read(0, s, sizeof(s));
write(fd, s, len);
} while (len);
break;
default:
printf("I don't understand that command.\n");
break;
}
return 0;
}

3
pwnables/daemons/run.fingerd Executable file
View File

@ -0,0 +1,3 @@
#! /bin/sh
exec tcpsvd 0 79 /usr/sbin/in.fingerd

4
pwnables/daemons/run.noted Executable file
View File

@ -0,0 +1,4 @@
#! /bin/sh
cd /var/lib/notes
exec tcpsvd 0 4000 /usr/sbin/in.noted

25
pwnables/init Executable file
View File

@ -0,0 +1,25 @@
#! /bin/sh
## This is the init for the desktop services box.
. /sbin/db-funcs.sh
dbmsg
dbmsg "-----------------------------------------------------------------------"
dbmsg "Bringing up pwnables personality"
dbmsg "-----------------------------------------------------------------------"
dbmsg
# /usr and /home live in RAM
mount -t tmpfs usr /usr
mount -t tmpfs home /home
# Unpackage everything. Globs are sorted in busybox.
cd /
for i in /opt/tce/*.tce; do
dbmsg "Unpacking $i..."
tar xzf $i
done
# Pass control to /usr/sbin/init
[ -x /usr/sbin/init ] && exec /usr/sbin/init
exec busybox init

View File

@ -0,0 +1 @@
ctf

View File

@ -0,0 +1 @@
root::::::::

View File

@ -0,0 +1,3 @@
#! /bin/sh
# Nothing to see here.

View File

@ -0,0 +1,14 @@
#! /bin/sh -e
# busybox's dc doesn't support i :<
# Its awk does support 0xa0 as an int, but gawk doesn't. This only works on busybox.
lastd=$(awk -F ':' '{for (i=1; i<NF; i++) {q = xor(q, "0x" $i);} print (q<2?2:q);}' /sys/class/net/eth0/address)
myip=10.0.0.$lastd
ifconfig eth0 $myip netmask 255.255.0.0
ifconfig eth1 192.168.0.1
while true; do
sleep 10d
done

View File

@ -0,0 +1,7 @@
#! /bin/sh
state=$(cat /sys/class/net/eth1/operstate)
if [ "$state" != "up" ]; then
exit 0
fi
exec tcpsvd 192.168.0.1 23 telnetd -i -l /bin/sh

View File

@ -0,0 +1,3 @@
#! /bin/sh
exec udpsvd 0 69 tftpd /var/lib/tftp