From 48caa2655653f6613908571b4a241bd2ee86adbd Mon Sep 17 00:00:00 2001 From: Neale Pickett Date: Sun, 26 Sep 2010 21:54:31 -0600 Subject: [PATCH] Add in pwnables, start at octopus & tokencli --- Makefile | 9 +- common/arc4.c | 59 +++++ common/arc4.h | 16 ++ common/token.c | 97 ++++++++ common/token.h | 21 ++ mcp/mcp.mk | 7 +- mcp/src/arc4.c | 60 +---- mcp/src/arc4.h | 17 +- mcp/src/tokencli.c | 93 +------- octopus/octopus.mk | 18 ++ octopus/service/octopus/log/run | 3 + octopus/service/octopus/run | 4 + octopus/setup | 3 + octopus/src/Makefile | 7 + octopus/src/octopus.c | 373 ++++++++++++++++++++++++++++++ octopus/src/token.c | 1 + octopus/src/token.h | 1 + puzzles/puzzles.mk | 13 +- pwnables/pwnables.mk | 21 ++ pwnables/service/pwnables/log/run | 3 + pwnables/service/pwnables/motd | 4 + pwnables/service/pwnables/pwnie | 4 + pwnables/service/pwnables/run | 3 + pwnables/setup | 35 +++ pwnables/src/Makefile | 18 ++ pwnables/src/arc4.c | 49 ++++ pwnables/src/gimmie.c | 26 +++ pwnables/src/killme.c | 77 ++++++ pwnables/src/ltraceme.c | 60 +++++ pwnables/src/straceme.c | 91 ++++++++ pwnables/src/token.c | 1 + pwnables/src/token.h | 1 + tokencli/service/tokencli/log/run | 3 + tokencli/service/tokencli/run | 11 + tokencli/src/Makefile | 4 + tokencli/src/arc4.c | 1 + tokencli/src/arc4.h | 1 + tokencli/src/tokencli.c | 92 ++++++++ tokencli/tokencli.mk | 18 ++ 39 files changed, 1147 insertions(+), 178 deletions(-) create mode 100644 common/arc4.c create mode 100644 common/arc4.h create mode 100644 common/token.c create mode 100644 common/token.h mode change 100644 => 120000 mcp/src/arc4.c mode change 100644 => 120000 mcp/src/arc4.h mode change 100644 => 120000 mcp/src/tokencli.c create mode 100644 octopus/octopus.mk create mode 100755 octopus/service/octopus/log/run create mode 100755 octopus/service/octopus/run create mode 100755 octopus/setup create mode 100644 octopus/src/Makefile create mode 100644 octopus/src/octopus.c create mode 120000 octopus/src/token.c create mode 120000 octopus/src/token.h create mode 100644 pwnables/pwnables.mk create mode 100755 pwnables/service/pwnables/log/run create mode 100644 pwnables/service/pwnables/motd create mode 100755 pwnables/service/pwnables/pwnie create mode 100755 pwnables/service/pwnables/run create mode 100755 pwnables/setup create mode 100644 pwnables/src/Makefile create mode 100644 pwnables/src/arc4.c create mode 100644 pwnables/src/gimmie.c create mode 100644 pwnables/src/killme.c create mode 100644 pwnables/src/ltraceme.c create mode 100644 pwnables/src/straceme.c create mode 120000 pwnables/src/token.c create mode 120000 pwnables/src/token.h create mode 100755 tokencli/service/tokencli/log/run create mode 100755 tokencli/service/tokencli/run create mode 100644 tokencli/src/Makefile create mode 120000 tokencli/src/arc4.c create mode 120000 tokencli/src/arc4.h create mode 100644 tokencli/src/tokencli.c create mode 100644 tokencli/tokencli.mk diff --git a/Makefile b/Makefile index 6478e14..e76f452 100644 --- a/Makefile +++ b/Makefile @@ -10,7 +10,12 @@ endef include */*.mk -packages: $(addsuffix -package, $(PACKAGES)) +packages: $(addsuffix .pkg, $(PACKAGES)) + +install: $(addsuffix -install, $(PACKAGES)) clean: $(addsuffix -clean, $(PACKAGES)) - rm -rf build *.pkg + rm -rf build *.pkg *-install *-build + +%.pkg: %-install + mksquashfs build/$* $*.pkg -all-root -noappend diff --git a/common/arc4.c b/common/arc4.c new file mode 100644 index 0000000..641d46d --- /dev/null +++ b/common/arc4.c @@ -0,0 +1,59 @@ +#include +#include +#include "arc4.h" + +#define swap(a, b) do {int _swap=a; a=b, b=_swap;} while (0) + +struct arc4_ctx { + uint8_t S[256]; + uint8_t i; + uint8_t j; +}; + +void +arc4_init(struct arc4_ctx *ctx, uint8_t const *key, size_t keylen) +{ + int i; + int j = 0; + + for (i = 0; i < 256; i += 1) { + ctx->S[i] = i; + } + + for (i = 0; i < 256; i += 1) { + j = (j + ctx->S[i] + key[i % keylen]) % 256; + swap(ctx->S[i], ctx->S[j]); + } + ctx->i = 0; + ctx->j = 0; +} + +uint8_t +arc4_pad(struct arc4_ctx *ctx) +{ + ctx->i = (ctx->i + 1) % 256; + ctx->j = (ctx->j + ctx->S[ctx->i]) % 256; + swap(ctx->S[ctx->i], ctx->S[ctx->j]); + return ctx->S[(ctx->S[ctx->i] + ctx->S[ctx->j]) % 256]; +} + +void +arc4_crypt(struct arc4_ctx *ctx, + uint8_t *obuf, uint8_t const *ibuf, size_t buflen) +{ + size_t k; + + for (k = 0; k < buflen; k += 1) { + obuf[k] = ibuf[k] ^ arc4_pad(ctx); + } +} + +void +arc4_crypt_buffer(uint8_t const *key, size_t keylen, + uint8_t *buf, size_t buflen) +{ + struct arc4_ctx ctx; + + arc4_init(&ctx, key, keylen); + arc4_crypt(&ctx, buf, buf, buflen); +} diff --git a/common/arc4.h b/common/arc4.h new file mode 100644 index 0000000..5ae3bd7 --- /dev/null +++ b/common/arc4.h @@ -0,0 +1,16 @@ +#ifndef __ARC4_H__ +#define __ARC4_H__ + +#include +#include + +struct arc4_ctx; + +void arc4_init(struct arc4_ctx *ctx, uint8_t const *key, size_t keylen); +uint8_t arc4_pad(struct arc4_ctx *ctx); +void arc4_crypt(struct arc4_ctx *ctx, + uint8_t *obuf, uint8_t const *ibuf, size_t buflen); +void arc4_crypt_buffer(uint8_t const *key, size_t keylen, + uint8_t *buf, size_t buflen); + +#endif diff --git a/common/token.c b/common/token.c new file mode 100644 index 0000000..bbbf0cd --- /dev/null +++ b/common/token.c @@ -0,0 +1,97 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef CTF_BASE +#define CTF_BASE "/var/lib/ctf" +#endif + +struct arc4_ctx { + uint8_t S[256]; + uint8_t i; + uint8_t j; +}; + + +#define swap(a, b) do {int _swap=a; a=b, b=_swap;} while (0) + +void +arc4_init(struct arc4_ctx *ctx, uint8_t const *key, size_t keylen) +{ + int i; + int j = 0; + + for (i = 0; i < 256; i += 1) { + ctx->S[i] = i; + } + + for (i = 0; i < 256; i += 1) { + j = (j + ctx->S[i] + key[i % keylen]) % 256; + swap(ctx->S[i], ctx->S[j]); + } + ctx->i = 0; + ctx->j = 0; +} + +void +arc4_crypt(struct arc4_ctx *ctx, + uint8_t *obuf, uint8_t const *ibuf, size_t buflen) +{ + int i = ctx->i; + int j = ctx->j; + size_t k; + + for (k = 0; k < buflen; k += 1) { + uint8_t mask; + + i = (i + 1) % 256; + j = (j + ctx->S[i]) % 256; + swap(ctx->S[i], ctx->S[j]); + mask = ctx->S[(ctx->S[i] + ctx->S[j]) % 256]; + obuf[k] = ibuf[k] ^ mask; + } + ctx->i = i; + ctx->j = j; +} + +void +arc4_crypt_buffer(uint8_t const *key, size_t keylen, + uint8_t *buf, size_t buflen) +{ + struct arc4_ctx ctx; + + arc4_init(&ctx, key, keylen); + arc4_crypt(&ctx, buf, buf, buflen); +} + + +ssize_t +read_token(char *name, + uint8_t const *key, size_t keylen, + char *buf, size_t buflen) +{ + char path[PATH_MAX]; + int pathlen; + int fd; + ssize_t ret; + + pathlen = snprintf(path, sizeof(path) - 1, + CTF_BASE "/tokens/%s", name); + path[pathlen] = '\0'; + + fd = open(path, O_RDONLY); + if (-1 == fd) return -1; + + ret = read(fd, buf, buflen); + close(fd); + if (-1 != ret) { + arc4_crypt_buffer(key, keylen, (uint8_t *)buf, (size_t)ret); + } + return ret; +} diff --git a/common/token.h b/common/token.h new file mode 100644 index 0000000..3f4e30a --- /dev/null +++ b/common/token.h @@ -0,0 +1,21 @@ +#ifndef __TOKEN_H__ +#define __TOKEN_H__ + +#include +#include +#include + +/* ARC4 functions, in case anybody wants 'em */ +struct arc4_ctx; +void arc4_init(struct arc4_ctx *ctx, + uint8_t const *key, size_t keylen); +void arc4_crypt(struct arc4_ctx *ctx, + uint8_t *obuf, uint8_t const *ibuf, size_t buflen); +void arc4_crypt_buffer(uint8_t const *key, size_t keylen, + uint8_t *buf, size_t buflen); + +ssize_t read_token(char *name, + uint8_t const *key, size_t keylen, + char *buf, size_t buflen); + +#endif diff --git a/mcp/mcp.mk b/mcp/mcp.mk index cbaeaec..2fa6095 100644 --- a/mcp/mcp.mk +++ b/mcp/mcp.mk @@ -1,9 +1,7 @@ MCP_PKGDIR = build/mcp MCP_PACKAGE = mcp.pkg -mcp-package: $(MCP_PACKAGE) - -$(MCP_PACKAGE): mcp-build +mcp-install: mcp-build mkdir -p $(MCP_PKGDIR) cp mcp/setup $(MCP_PKGDIR) @@ -20,8 +18,7 @@ $(MCP_PACKAGE): mcp-build cp mcp/src/puzzler.cgi $(MCP_PKGDIR)/www/ cp mcp/src/claim.cgi $(MCP_PKGDIR)/www/ - mksquashfs $(MCP_PKGDIR) $(MCP_PACKAGE) -all-root -noappend - + touch $@ mcp-test: mcp-build mcp/test.sh diff --git a/mcp/src/arc4.c b/mcp/src/arc4.c deleted file mode 100644 index 641d46d..0000000 --- a/mcp/src/arc4.c +++ /dev/null @@ -1,59 +0,0 @@ -#include -#include -#include "arc4.h" - -#define swap(a, b) do {int _swap=a; a=b, b=_swap;} while (0) - -struct arc4_ctx { - uint8_t S[256]; - uint8_t i; - uint8_t j; -}; - -void -arc4_init(struct arc4_ctx *ctx, uint8_t const *key, size_t keylen) -{ - int i; - int j = 0; - - for (i = 0; i < 256; i += 1) { - ctx->S[i] = i; - } - - for (i = 0; i < 256; i += 1) { - j = (j + ctx->S[i] + key[i % keylen]) % 256; - swap(ctx->S[i], ctx->S[j]); - } - ctx->i = 0; - ctx->j = 0; -} - -uint8_t -arc4_pad(struct arc4_ctx *ctx) -{ - ctx->i = (ctx->i + 1) % 256; - ctx->j = (ctx->j + ctx->S[ctx->i]) % 256; - swap(ctx->S[ctx->i], ctx->S[ctx->j]); - return ctx->S[(ctx->S[ctx->i] + ctx->S[ctx->j]) % 256]; -} - -void -arc4_crypt(struct arc4_ctx *ctx, - uint8_t *obuf, uint8_t const *ibuf, size_t buflen) -{ - size_t k; - - for (k = 0; k < buflen; k += 1) { - obuf[k] = ibuf[k] ^ arc4_pad(ctx); - } -} - -void -arc4_crypt_buffer(uint8_t const *key, size_t keylen, - uint8_t *buf, size_t buflen) -{ - struct arc4_ctx ctx; - - arc4_init(&ctx, key, keylen); - arc4_crypt(&ctx, buf, buf, buflen); -} diff --git a/mcp/src/arc4.c b/mcp/src/arc4.c new file mode 120000 index 0000000..807950d --- /dev/null +++ b/mcp/src/arc4.c @@ -0,0 +1 @@ +../../common/arc4.c \ No newline at end of file diff --git a/mcp/src/arc4.h b/mcp/src/arc4.h deleted file mode 100644 index 5ae3bd7..0000000 --- a/mcp/src/arc4.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef __ARC4_H__ -#define __ARC4_H__ - -#include -#include - -struct arc4_ctx; - -void arc4_init(struct arc4_ctx *ctx, uint8_t const *key, size_t keylen); -uint8_t arc4_pad(struct arc4_ctx *ctx); -void arc4_crypt(struct arc4_ctx *ctx, - uint8_t *obuf, uint8_t const *ibuf, size_t buflen); -void arc4_crypt_buffer(uint8_t const *key, size_t keylen, - uint8_t *buf, size_t buflen); - -#endif diff --git a/mcp/src/arc4.h b/mcp/src/arc4.h new file mode 120000 index 0000000..2d31392 --- /dev/null +++ b/mcp/src/arc4.h @@ -0,0 +1 @@ +../../common/arc4.h \ No newline at end of file diff --git a/mcp/src/tokencli.c b/mcp/src/tokencli.c deleted file mode 100644 index 8cbbf5c..0000000 --- a/mcp/src/tokencli.c +++ /dev/null @@ -1,92 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include "arc4.h" - -/* I don't feel compelled to put all the TCP client code in here - * when it's so simple to run this with netcat or ucspi. Plus, using - * stdin and stdout makes it simpler to test. - */ - -int -read_key(char *filename, uint8_t *key, size_t *keylen) -{ - int fd = open(filename, O_RDONLY); - int len; - - if (-1 == fd) { - perror("open"); - return EX_NOINPUT; - } - - len = read(fd, key, *keylen); - if (-1 == len) { - perror("read"); - return EX_NOINPUT; - } - *keylen = (size_t)len; - - return 0; -} - -int -main(int argc, char *argv[]) { - uint8_t skey[200]; - size_t skeylen = sizeof(skey); - char token[200]; - size_t tokenlen; - int ret; - - if (argc != 3) { - fprintf(stderr, "Usage: %s SERVICE SERVICEKEY 3>TOKENFILE\n", argv[0]); - fprintf(stderr, "\n"); - fprintf(stderr, "SERVICEKEY is a filenames.\n"); - fprintf(stderr, "Tokens are written to file descriptor 3.\n"); - return EX_USAGE; - } - - /* read in keys */ - ret = read_key(argv[2], skey, &skeylen); - if (0 != ret) return ret; - - /* write service name */ - write(1, argv[1], strlen(argv[1])); - - /* read nonce, send back encrypted version */ - { - uint8_t nonce[80]; - int noncelen; - - noncelen = read(0, nonce, sizeof(nonce)); - if (0 >= noncelen) { - perror("read"); - return EX_IOERR; - } - arc4_crypt_buffer(skey, skeylen, nonce, (size_t)noncelen); - write(1, nonce, (size_t)noncelen); - } - - /* read token */ - { - int len; - - len = read(0, token, sizeof(token)); - if (0 >= len) { - perror("read"); - return EX_IOERR; - } - tokenlen = (size_t)len; - } - - /* decrypt it */ - arc4_crypt_buffer(skey, skeylen, (uint8_t *)token, tokenlen); - - /* write it to fd 3 */ - write(3, token, tokenlen); - - return 0; -} diff --git a/mcp/src/tokencli.c b/mcp/src/tokencli.c new file mode 120000 index 0000000..fd04434 --- /dev/null +++ b/mcp/src/tokencli.c @@ -0,0 +1 @@ +../../tokencli/src/tokencli.c \ No newline at end of file diff --git a/octopus/octopus.mk b/octopus/octopus.mk new file mode 100644 index 0000000..e584212 --- /dev/null +++ b/octopus/octopus.mk @@ -0,0 +1,18 @@ +OCTOPUS_PKGDIR = build/octopus +OCTOPUS_PACKAGE = octopus.pkg + +octopus-install: octopus-build + mkdir -p $(OCTOPUS_PKGDIR)/bin/ + + $(call COPYTREE, octopus/service, $(OCTOPUS_PKGDIR)/service) + + cp octopus/src/octopus $(OCTOPUS_PKGDIR)/bin/ + +octopus-clean: + rm -rf $(OCTOPUS_PKGDIR) $(OCTOPUS_PACKAGE) + $(MAKE) -C octopus/src clean + +octopus-build: + $(MAKE) -C octopus/src build + +PACKAGES += octopus diff --git a/octopus/service/octopus/log/run b/octopus/service/octopus/log/run new file mode 100755 index 0000000..049ab8e --- /dev/null +++ b/octopus/service/octopus/log/run @@ -0,0 +1,3 @@ +#! /bin/sh + +exec logger -t octopus diff --git a/octopus/service/octopus/run b/octopus/service/octopus/run new file mode 100755 index 0000000..6bdd947 --- /dev/null +++ b/octopus/service/octopus/run @@ -0,0 +1,4 @@ +#! /bin/sh + +exec 2>&1 +exec /opt/octopus/bin/octopus diff --git a/octopus/setup b/octopus/setup new file mode 100755 index 0000000..e1b048d --- /dev/null +++ b/octopus/setup @@ -0,0 +1,3 @@ +#! /bin/sh + +mkdir -p /var/lib/ctf/tokens diff --git a/octopus/src/Makefile b/octopus/src/Makefile new file mode 100644 index 0000000..38619cf --- /dev/null +++ b/octopus/src/Makefile @@ -0,0 +1,7 @@ +# Octopus / Some kind of octopus / Tearing my shell apart / Letting the +# sea get in / You make my insides outside + +octopus: octopus.o token.o + +clean: + rm -f octopus *.o diff --git a/octopus/src/octopus.c b/octopus/src/octopus.c new file mode 100644 index 0000000..7736861 --- /dev/null +++ b/octopus/src/octopus.c @@ -0,0 +1,373 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "token.h" + +#define OUTPUT_MAX 1024 +#define INPUT_MAX 1024 + +#ifndef max +#define max(a,b) (((a)>(b))?(a):(b)) +#endif + +uint8_t const key[] = {0x7d, 0x47, 0x84, 0x28, + 0x09, 0x87, 0xb5, 0xd2, + 0xd8, 0xab, 0x1c, 0xf3, + 0xf2, 0x96, 0xd6, 0x68}; + +char const octopus[] = + (" ___\n" + " .-' `'.\n" + " / \\\n" + " | ;\n" + " | | ___.--,\n" + " _.._ |8) ~ (8) | _.---'`__.-( (_.\n" + " __.--'`_.. '.__.\\ '--. \\_.-' ,.--'` `""`\n" + " ( ,.--'` ',__ /./; ;, '.__.'` __\n" + " _`) ) .---.__.' / | |\\ \\__..--\"\" \"\"\"--.,_\n" + " `---' .'.''-._.-'`_./ /\\ '. \\ _.-~~~````~~~-._`-.__.'\n" + " | | .' _.-' | | \\ \\ '. `~---`\n" + " \\ \\/ .' \\ \\ '. '-._)\n" + " \\/ / \\ \\ `=.__`~-.\n" + " jgs / /\\ `) ) / / `\"\".`\\\n" + " , _.-'.'\\ \\ / / ( ( / /\n" + " `--~` ) ) .-'.' '.'. | (\n" + " (/` ( (` ) ) '-;\n" + " ` '-; (-'\n" + ); + +const char *friends[8] = { + ("Help Olive Octopus visit all 8 of her friends to receive a prize!\n" + "Hurry though, things change quickly!\n" + "Next friend: %08o\n" + "%s" + ), + ("Thanks for stopping by, Olive! Good luck finding that prize!\n" + "Next friend: %08o\n" + " ,__\n" + " | `'.\n" + "__ |`-._/_.:---`-.._\n" + "\\='. _/..--'`__ `'-._\n" + " \\- '-.--\"` === / o `',\n" + " )= ( .--_ | _.'\n" + " /_=.'-._ {=_-_ | .--`-.\n" + "/_.' `\\`'-._ '-= \\ _.'\n" + " jgs ) _.-'`'-.. _..-'`\n" + " /_.' `/\";';`|\n" + " \\` .'/\n" + " '--'\n" + ), + ("Snap, snap! Good luck on your quest, Olive!\n" + "Next friend: %08o\n" + " .\"\".-._.-.\"\".\n" + " | \\ | / |\n" + " \\ \\.T./ /\n" + " '-./ \\.-'\n" + " / \\\n" + " ; ;\n" + " | |\n" + " | |\n" + " / \\\n" + " | . |\n" + " __.| : |.__\n" + " .-'` | : | `'-.\n" + " /` .\"\\ 0 : 0 /\". `\\\n" + " | _/ './ : \\.' \\_ |\n" + " | / /`\"\"\"`\\ \\ |\n" + " \\ \\ .-' '._ / /\n" + " jgs '-._\\ /_.-'\n" + ), + ("Nice talking with you, Olive. I'd best get back to my babies now!\n" + "Next friend: %08o\n" + " , ,\n" + " \\:.|`._\n" + " /\\/;.:':::;;;._\n" + " < .' ':::;(\n" + " < ' _ '::;>\n" + " \\ (9) _ :::;(\n" + " | / \\ ::;`>\n" + " | / | :;(\n" + " | ( <=- .::;>\n" + " ( a) )=- .::;(\n" + " '-' <=- .::;>\n" + " )==- ::::( ,\n" + " <==- :::(,-'(\n" + " )=- ':: _.->\n" + " <==- ':.' _(\n" + " <==- .:'_ (\n" + " )==- .::' '->\n" + " <=- .:;(`'.(\n" + " `) ':;> `\n" + " .-. < :;(\n" + " <`.':\\ ) :;>\n" + " < :/<_/ < .:;>\n" + " < '`---'` .::(`\n" + " jgs < .:;>'\n" + " `-..:::-'`\n" + ), + ("Spshhh! Good to see you, Olive! You're on the right track!\n" + "Next friend: %08o\n" + " ,_\n" + " \\::,\n" + " |::::\\\n" + " |:::::\\\n" + " __/:::::::\\,____\n" + " _.-::::::::::::::::::::==..,____\n" + " .-::::::::::::::::::::::::::::::::::::.,__\n" + " .:::::::::::::::::::::::::::::::::::::::::::::)\n" + " .:::::'```'-::::::::::::::::::::::(__,__`)::::-'\n" + " .;;;;;;::. ':::::::::::::::::::-:::::@::-'\"\"-,\n" + " .------:::::::::::' '-::::::::::' / `'--'\"\"\"\".-'\n" + "/:::::::::/:::/` _,..-----.,__ `''''`/ ;__,..--''--'`\n" + "`'--::::::::::|-'` `'---'| |\n" + " `\\::::\\ \\ /\n" + " |:::::| '-'\n" + " \\::::|\n" + " jgs `\\::|\n" + " \\/\n" + ), + ("You're getting close, Olive!\n" + "Next friend: %08o\n" + " .-------------'```'----......,,__ _,\n" + " | `'`'`'`'-.,.__ .'(\n" + " | `'--._.' )\n" + " | `'-.<\n" + " \\ .-'`'-. -. `\\\n" + " \\ -.o_. _ _,-'`\\ |\n" + " ``````''--.._.-=-._ .' \\ _,,--'` `-._(\n" + " (^^^^^^^^`___ '-. | \\ __,,,...--' `\n" + " ````````` `'--..___\\ |`\n" + " jgs `-.,'\n" + ), + ("Hi, Olive! Not much further now!\n" + "Next friend: %08o\n" + " , ,\n" + " /(_, ,_)\\\n" + " \\ _/ \\_ /\n" + " // \\\\\n" + " \\\\ (@)(@) //\n" + " \\'=\"==\"='/\n" + " ,===/ \\===,\n" + " \",===\\ /===,\"\n" + " \" ,==='------'===, \"\n" + " jgs \" \"\n" + ), + ("Aha! You found me!\n" + "Prize: %.*s\n" + " (\\.-./)\n" + " / \\\n" + " .' : '.\n" + " _.-'` ' `'-._\n" + " .-' : '-.\n" + " ,'_.._ . _.._',\n" + " '` `'-. ' .-'` `'\n" + " '. : .'\n" + " \\_. ._/\n" + " \\ |^|\n" + " | jgs | ;\n" + " \\'.___.' /\n" + " '-....-'\n") +}; + +const char invalid[] = "Who are you? Go away!\n"; + +#ifdef EASY +# define PORTS 15 +#else +# define PORTS 8 +#endif + +struct bound_port { + int fd; + char output[OUTPUT_MAX]; + size_t output_len; +} bound_ports[PORTS]; + +int +bind_port(int fd, uint16_t port) { + struct sockaddr_in addr; + + addr.sin_family = AF_INET; + addr.sin_port = htons(port); + addr.sin_addr.s_addr = INADDR_ANY; + return bind(fd, (struct sockaddr *)&addr, sizeof(addr)); +} + +int +rebind() +{ + static int offset = 0; + char token[200]; + size_t tokenlen; + int i; + + tokenlen = read_token("octopus", + key, sizeof(key), + token, sizeof(token)); + if (-1 == tokenlen) { + return -1; + } + + for (i = 1; i < 8; i += 1) { + int ret; + int last_guy; + in_port_t port; + + if (-1 != bound_ports[i + offset].fd) { + while (-1 == close(bound_ports[i + offset].fd)) { + if (errno != EINTR) { + return -1; + } + } + } + + /* Bind to a port */ + bound_ports[i + offset].fd = socket(PF_INET, SOCK_DGRAM, 0); + do { + port = (random() % 56635) + 10000; + ret = bind_port(bound_ports[i + offset].fd, port); + } while (-1 == ret); + + /* Set the last guy's port number */ + last_guy = i + offset - 1; + switch (i) { + case 1: + /* Always change the port 8888 one */ + last_guy = 0; + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + bound_ports[last_guy].output_len = + snprintf(bound_ports[last_guy].output, OUTPUT_MAX, + friends[i - 1], port, octopus); + break; + } + } + bound_ports[7 + offset].output_len = + snprintf(bound_ports[7 + offset].output, OUTPUT_MAX, + friends[7], tokenlen, token); + + if (offset == 0) { + offset = PORTS - 8; + } else { + offset = 0; + } + + return 0; +} + +void +do_io(int which) +{ + struct bound_port *bp = &bound_ports[which]; + char input[INPUT_MAX]; + ssize_t inlen; + struct sockaddr from; + socklen_t fromlen = sizeof(from); + + inlen = recvfrom(bp->fd, input, INPUT_MAX, 0, + &from, &fromlen); + if (-1 == inlen) { + /* Well don't that just beat all. */ + return; + } + + if (which > 0) { + if ((inlen != sizeof(octopus) - 1) || + (0 != memcmp(input, octopus, inlen))) { + /* Didn't send the octopus */ + sendto(bp->fd, invalid, sizeof(invalid), 0, + &from, fromlen); + return; + } + } + + sendto(bp->fd, bp->output, bp->output_len, 0, + &from, fromlen); +} + +int +loop() +{ + int i; + int nfds = 0; + fd_set rfds; + struct timeval timeout; + + timeout.tv_sec = 1; + timeout.tv_usec = 0; + + FD_ZERO(&rfds); + for (i = 0; i < PORTS; i += 1) { + nfds = max(nfds, bound_ports[i].fd); + FD_SET(bound_ports[i].fd, &rfds); + } + + /* Wait forever. There's no need to switch ports if nobody's doing + anything. */ + while (-1 == select(nfds+1, &rfds, NULL, NULL, &timeout)) { + if (EINTR == errno) { + continue; + } + return 0; + } + + for (i = 0; i < PORTS; i += 1) { + if (FD_ISSET(bound_ports[i].fd, &rfds)) { + do_io(i); + } + } + + return 1; +} + +int +main(int argc, char *argv[]) +{ + int ret; + int i; + time_t last = time(NULL); + + /* The random seed isn't super important here. */ + srand(8); + + bound_ports[0].fd = socket(PF_INET, SOCK_DGRAM, 0); + ret = bind_port(bound_ports[0].fd, 8888); + if (-1 == ret) { + perror("bind port 8888"); + return EX_IOERR; + } + + for (i = 1; i < PORTS; i += 1) { + bound_ports[i].fd = -1; + } + if (-1 == rebind()) { + perror("initial binding"); + return EX_IOERR; + } + + while (loop()) { + time_t now = time(NULL); + + if (last + 4 < now) { + last = now; + if (-1 == rebind()) break; + } + } + + perror("main loop"); + return EX_IOERR; +} diff --git a/octopus/src/token.c b/octopus/src/token.c new file mode 120000 index 0000000..8c6738e --- /dev/null +++ b/octopus/src/token.c @@ -0,0 +1 @@ +../../common/token.c \ No newline at end of file diff --git a/octopus/src/token.h b/octopus/src/token.h new file mode 120000 index 0000000..25f916f --- /dev/null +++ b/octopus/src/token.h @@ -0,0 +1 @@ +../../common/token.h \ No newline at end of file diff --git a/puzzles/puzzles.mk b/puzzles/puzzles.mk index 92185ce..b90d4df 100644 --- a/puzzles/puzzles.mk +++ b/puzzles/puzzles.mk @@ -3,12 +3,17 @@ PUZZLES += forensics hackme net-re sequence skynet webapp -include puzzles/*/*.mk -puzzles/%-package: +puzzles/%-install: mkdir -p build/$* puzzles/mkpuzzles puzzles/$* build/$* - mksquashfs build/$* $*.pkg -all-root -noappend + touch $@ puzzles/%-clean: - rm -rf build/$* + rm -rf build/$* puzzles/$*-install -PACKAGES += $(addprefix puzzles/, $(PUZZLES)) \ No newline at end of file +%.pkg: puzzles/%-install + mksquashfs build/$* $*.pkg -all-root -noappend + +packages: $(addsuffix .pkg, $(PUZZLES)) +install: $(patsubst %, puzzles/%-install, $(PUZZLES)) +clean: $(patsubst %, puzzles/%-clean, $(PUZZLES)) diff --git a/pwnables/pwnables.mk b/pwnables/pwnables.mk new file mode 100644 index 0000000..d07a528 --- /dev/null +++ b/pwnables/pwnables.mk @@ -0,0 +1,21 @@ +PWNABLES_PKGDIR = build/pwnables +PWNABLES_PACKAGE = pwnables.pkg + +pwnables-install: pwnables-build + mkdir -p $(PWNABLES_PKGDIR) + + cp pwnables/setup $(PWNABLES_PKGDIR) + + mkdir -p $(PWNABLES_PKGDIR)/bin/ + $(MAKE) -C pwnables/src install DESTDIR=$(CURDIR)/$(PWNABLES_PKGDIR) + + $(call COPYTREE, pwnables/service, $(PWNABLES_PKGDIR)/service) + +pwnables-clean: + rm -rf $(PWNABLES_PKGDIR) $(PWNABLES_PACKAGE) + $(MAKE) -C pwnables/src clean + +pwnables-build: + $(MAKE) -C pwnables/src build + +PACKAGES += pwnables diff --git a/pwnables/service/pwnables/log/run b/pwnables/service/pwnables/log/run new file mode 100755 index 0000000..c356994 --- /dev/null +++ b/pwnables/service/pwnables/log/run @@ -0,0 +1,3 @@ +#! /bin/sh + +exec logger -t pwnables diff --git a/pwnables/service/pwnables/motd b/pwnables/service/pwnables/motd new file mode 100644 index 0000000..47ed8b3 --- /dev/null +++ b/pwnables/service/pwnables/motd @@ -0,0 +1,4 @@ + .::7777::-. + /:'////' `::>/|/ + .', |||| `/( e\ + -==~-'`-Xm````-mr' `-_\ diff --git a/pwnables/service/pwnables/pwnie b/pwnables/service/pwnables/pwnie new file mode 100755 index 0000000..7317d69 --- /dev/null +++ b/pwnables/service/pwnables/pwnie @@ -0,0 +1,4 @@ +#! /bin/sh + +[ -f motd ] && cat motd +exec chroot /mnt/pwnables-root login -f alice diff --git a/pwnables/service/pwnables/run b/pwnables/service/pwnables/run new file mode 100755 index 0000000..39e6f0c --- /dev/null +++ b/pwnables/service/pwnables/run @@ -0,0 +1,3 @@ +#! /bin/sh -e + +exec tcpsvd -C 5:"Let's not be greedy" 0 23 /sbin/telnetd -l ./pwnie diff --git a/pwnables/setup b/pwnables/setup new file mode 100755 index 0000000..d22f4c9 --- /dev/null +++ b/pwnables/setup @@ -0,0 +1,35 @@ +#! /bin/sh + +if [ ! -d /opt/mcp ]; then + hostname pwnables +fi + +# Set up a chroot environment by duplicating the base +# image +if [ ! -x /mnt/pwnables-root/bin/busybox ]; then + mkdir -p /mnt/pwnables-root + mount -o bind / /mnt/pwnables-root + mount -t tmpfs -o size=5m,mode=0755 pwnables-var /mnt/pwnables-root/var + mount -t tmpfs -o size=15k pwnables-tmp /mnt/pwnables-root/tmp + mount -t tmpfs -o size=5m pwnables-home /mnt/pwnables-root/home + + # Make some skeleton junk + install -o root -m 0755 -d /mnt/pwnables-root/var/lib + install -o root -m 0755 -d /mnt/pwnables-root/var/log + install -o root -m 0755 -d /mnt/pwnables-root/var/spool + install -o root -m 0755 -d /mnt/pwnables-root/var/cache + install -o root -m 0777 -d /mnt/pwnables-root/var/run + install -o root -m 0777 -d /mnt/pwnables-root/var/cache + + install -o root -d /mnt/pwnables-root/home/alice/ + install -o root -m 0111 bin/* /mnt/pwnables-root/home/alice/ + + # ltrace needs to read the binary + chmod +r /mnt/pwnables-root/home/alice/ltraceme + + # strace needs to be suid + chown bob /mnt/pwnables-root/home/alice/straceme + chmod 04511 /mnt/pwnables-root/home/alice/straceme +fi + +cp -r service/* /var/service/ diff --git a/pwnables/src/Makefile b/pwnables/src/Makefile new file mode 100644 index 0000000..245bcba --- /dev/null +++ b/pwnables/src/Makefile @@ -0,0 +1,18 @@ +CFLAGS = -Wall -Werror +TARGETS = gimmie ltraceme straceme killme + +all: build + +build: $(TARGETS) + +gimmie: gimmie.o token.o +octopus: octopus.o token.o +ltraceme: ltraceme.o token.o +straceme: straceme.o token.o +killme: killme.o token.o + +install: $(TARGETS) + install -m 0755 $(TARGETS) $(DESTDIR)/bin + +clean: + rm -f *.o $(TARGETS) \ No newline at end of file diff --git a/pwnables/src/arc4.c b/pwnables/src/arc4.c new file mode 100644 index 0000000..f1a0dd0 --- /dev/null +++ b/pwnables/src/arc4.c @@ -0,0 +1,49 @@ +#include +#include +#include +#include "arc4.h" + +int +main(int argc, char *argv[]) +{ + struct arc4_ctx ctx; + + /* Read key and initialize context */ + { + uint8_t key[256]; + size_t keylen = 0; + FILE *f; + + if (argc == 2) { + if (! (f = fopen(argv[1], "r"))) { + perror(argv[0]); + } + } else { + f = fdopen(3, "r"); + } + + if (f) { + keylen = fread(key, 1, sizeof(key), f); + fclose(f); + } + + if (0 == keylen) { + fprintf(stderr, "Usage: %s [KEYFILE] +#include "token.h" + +uint8_t const key[] = {0x5f, 0x64, 0x13, 0x29, + 0x2e, 0x46, 0x76, 0xcd, + 0x65, 0xff, 0xe8, 0x03, + 0xa4, 0xa9, 0x4f, 0xd9}; + +int +main(int argc, char *argv[]) +{ + char token[200]; + ssize_t tokenlen; + + tokenlen = read_token("gimmie", + key, sizeof(key), + token, sizeof(token) - 1); + if (-1 == tokenlen) { + return 69; + } + + token[tokenlen++] = '\n'; + write(1, token, tokenlen); + + return 0; +} diff --git a/pwnables/src/killme.c b/pwnables/src/killme.c new file mode 100644 index 0000000..5184674 --- /dev/null +++ b/pwnables/src/killme.c @@ -0,0 +1,77 @@ +#include +#include +#include +#include +#include +#include "token.h" + +#define SIGS 20 + +uint8_t const key[] = {0x51, 0x91, 0x6d, 0x81, + 0x14, 0x21, 0xf8, 0x95, + 0xb8, 0x09, 0x87, 0xa6, + 0xa8, 0xb0, 0xa0, 0x46}; + +int lastsig; + +void +handler(int signum) +{ + lastsig = signum; +} + +int +main(int argc, char *argv[]) +{ + int i; + + { + /* Seed random number generator */ + FILE *f; + int seed; + + f = fopen("/dev/urandom", "r"); + if (f) { + fread(&seed, sizeof(seed), 1, f); + srandom(seed); + } else { + srandom(getpid() * time(NULL)); + } + } + + for (i = 1; i < 8; i += 1) { + signal(i, handler); + } + + for (i = 0; i < SIGS; i += 1) { + int desired = (random() % 7) + 1; + + lastsig = 0; + printf("%d\n", desired); + fflush(stdout); + if (i == 0) { + sleep(5); + } else { + sleep(1); + } + if (0 == lastsig) { + printf("Too slow.\n"); + return 1; + } + if (lastsig != desired) { + printf("Wrong one.\n"); + return 1; + } + } + + { + char token[200]; + size_t tokenlen; + + tokenlen = read_token("killme", + key, sizeof(key), + token, sizeof(token) - 1); + } + + return 0; +} diff --git a/pwnables/src/ltraceme.c b/pwnables/src/ltraceme.c new file mode 100644 index 0000000..ceccd37 --- /dev/null +++ b/pwnables/src/ltraceme.c @@ -0,0 +1,60 @@ +#include +#include +#include +#include +#include "token.h" + +/* This hopefully requires an LD_PRELOAD */ + +uint8_t const key[] = {0x94, 0xf2, 0x92, 0x45, + 0x12, 0x44, 0x80, 0xe1, + 0x95, 0x64, 0xcd, 0xe4, + 0xff, 0x0a, 0x00, 0x10}; + +int +main(int argc, char *argv[]) +{ + char token[200]; + size_t tokenlen; + + /* Do some bullshit. Override with: + * + * void strcmp(char *a, char *b) + * { + * return 0; + * } + */ + { + FILE *f = fopen("/dev/urandom", "r"); + unsigned int seed; + char seed_str[50]; + + printf("Checking credentials...\n"); + fread(&seed, sizeof(seed), 1, f); + sprintf(seed_str, "%d", seed); + if ((argc != 2) || strcmp(seed_str, argv[1])) { + printf("Ah ah ah! You didn't say the magic word!\n"); + return 1; + } + } + + tokenlen = read_token("ltraceme", + key, sizeof(key), + token, sizeof(token) - 1); + if (-1 == tokenlen) { + printf("Unable to read token.\n"); + return 1; + } + token[tokenlen++] = '\0'; + + /* You could override this with: + * + * void printf(char *fmt, size_t len, char *buf) + * { + * if (fmt[0] == 'T') write(1, buf, len); + * } + */ + printf("Token length %u at %p.\n", tokenlen, token); + + return 0; +} diff --git a/pwnables/src/straceme.c b/pwnables/src/straceme.c new file mode 100644 index 0000000..d73b0c1 --- /dev/null +++ b/pwnables/src/straceme.c @@ -0,0 +1,91 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "token.h" + +uint8_t const key[] = {0x30, 0x00, 0x55, 0x0f, + 0xc2, 0xf6, 0x52, 0x2a, + 0x31, 0xfd, 0x00, 0x92, + 0x9d, 0x49, 0x24, 0xce}; + +int +main(int argc, char *argv[]) +{ + /* Check argv[1]. + * + * If no args, argv[1] will be NULL, which causes a segfault. + * This is what we want. + * + * To pass this, run ./straceme $$. + * But you have to do it from a shell script, because if you run + * strace ./straceme $$ + * getppid() will return the PID of strace! + */ + if (getppid() != atoi(argv[1])) { + write(2, "argv[1] incorrect\n", 18); + return EX_USAGE; + } + + /* Read an rc file. + * + * To pass this, set $HOME to someplace you have access. + */ + { + int fd; + char fn[128]; + char bs[1000]; + int len; + + len = snprintf(fn, sizeof(fn) - 1, "%s/.stracemerc", getenv("HOME")); + if (len < 0) { + len = 0; + } + fn[len] = '\0'; + + if (-1 == (fd = open(fn, O_RDONLY))) { + fd = open("/etc/stracemerc", O_RDONLY); + } + if (-1 == fd) { + return EX_NOINPUT; + } + + /* We don't actually care about contents */ + read(fd, bs, sizeof(bs)); + close(fd); + } + + /* Read in category name from fd 2 (stderr!) + * + * echo -n straceme > foo.txt + * ./straceme $$ 2< foo.txt + */ + { + char cat[50]; + int catlen; + char token[200]; + size_t tokenlen; + int i; + + catlen = read(2, cat, sizeof(cat) - 1); + for (i = 0; i < catlen; i += 1) { + if (! isalnum(cat[i])) break; + } + cat[i] = '\0'; + + tokenlen = read_token(cat, + key, sizeof(key), + token, sizeof(token)); + if (-1 == tokenlen) { + return EX_NOINPUT; + } + + write(1, token, tokenlen); + } + return 0; +} diff --git a/pwnables/src/token.c b/pwnables/src/token.c new file mode 120000 index 0000000..8c6738e --- /dev/null +++ b/pwnables/src/token.c @@ -0,0 +1 @@ +../../common/token.c \ No newline at end of file diff --git a/pwnables/src/token.h b/pwnables/src/token.h new file mode 120000 index 0000000..25f916f --- /dev/null +++ b/pwnables/src/token.h @@ -0,0 +1 @@ +../../common/token.h \ No newline at end of file diff --git a/tokencli/service/tokencli/log/run b/tokencli/service/tokencli/log/run new file mode 100755 index 0000000..b9dfae2 --- /dev/null +++ b/tokencli/service/tokencli/log/run @@ -0,0 +1,3 @@ +#! /bin/sh + +exec logger -t tokencli diff --git a/tokencli/service/tokencli/run b/tokencli/service/tokencli/run new file mode 100755 index 0000000..10e4fbe --- /dev/null +++ b/tokencli/service/tokencli/run @@ -0,0 +1,11 @@ +#! /bin/sh + +exec 2>&1 + +while true; do + for fn in /opt/*/*.tokenkey; do + cat=$(basename $fn .tokenkey) + echo "XXX: not implemented yet" + done + sleep 60 +done diff --git a/tokencli/src/Makefile b/tokencli/src/Makefile new file mode 100644 index 0000000..f387147 --- /dev/null +++ b/tokencli/src/Makefile @@ -0,0 +1,4 @@ +tokencli: tokencli.o arc4.o + +clean: + rm *.o tokencli diff --git a/tokencli/src/arc4.c b/tokencli/src/arc4.c new file mode 120000 index 0000000..807950d --- /dev/null +++ b/tokencli/src/arc4.c @@ -0,0 +1 @@ +../../common/arc4.c \ No newline at end of file diff --git a/tokencli/src/arc4.h b/tokencli/src/arc4.h new file mode 120000 index 0000000..2d31392 --- /dev/null +++ b/tokencli/src/arc4.h @@ -0,0 +1 @@ +../../common/arc4.h \ No newline at end of file diff --git a/tokencli/src/tokencli.c b/tokencli/src/tokencli.c new file mode 100644 index 0000000..8cbbf5c --- /dev/null +++ b/tokencli/src/tokencli.c @@ -0,0 +1,92 @@ +#include +#include +#include +#include +#include +#include +#include +#include "arc4.h" + +/* I don't feel compelled to put all the TCP client code in here + * when it's so simple to run this with netcat or ucspi. Plus, using + * stdin and stdout makes it simpler to test. + */ + +int +read_key(char *filename, uint8_t *key, size_t *keylen) +{ + int fd = open(filename, O_RDONLY); + int len; + + if (-1 == fd) { + perror("open"); + return EX_NOINPUT; + } + + len = read(fd, key, *keylen); + if (-1 == len) { + perror("read"); + return EX_NOINPUT; + } + *keylen = (size_t)len; + + return 0; +} + +int +main(int argc, char *argv[]) { + uint8_t skey[200]; + size_t skeylen = sizeof(skey); + char token[200]; + size_t tokenlen; + int ret; + + if (argc != 3) { + fprintf(stderr, "Usage: %s SERVICE SERVICEKEY 3>TOKENFILE\n", argv[0]); + fprintf(stderr, "\n"); + fprintf(stderr, "SERVICEKEY is a filenames.\n"); + fprintf(stderr, "Tokens are written to file descriptor 3.\n"); + return EX_USAGE; + } + + /* read in keys */ + ret = read_key(argv[2], skey, &skeylen); + if (0 != ret) return ret; + + /* write service name */ + write(1, argv[1], strlen(argv[1])); + + /* read nonce, send back encrypted version */ + { + uint8_t nonce[80]; + int noncelen; + + noncelen = read(0, nonce, sizeof(nonce)); + if (0 >= noncelen) { + perror("read"); + return EX_IOERR; + } + arc4_crypt_buffer(skey, skeylen, nonce, (size_t)noncelen); + write(1, nonce, (size_t)noncelen); + } + + /* read token */ + { + int len; + + len = read(0, token, sizeof(token)); + if (0 >= len) { + perror("read"); + return EX_IOERR; + } + tokenlen = (size_t)len; + } + + /* decrypt it */ + arc4_crypt_buffer(skey, skeylen, (uint8_t *)token, tokenlen); + + /* write it to fd 3 */ + write(3, token, tokenlen); + + return 0; +} diff --git a/tokencli/tokencli.mk b/tokencli/tokencli.mk new file mode 100644 index 0000000..c559198 --- /dev/null +++ b/tokencli/tokencli.mk @@ -0,0 +1,18 @@ +TOKENCLI_PKGDIR = build/tokencli +TOKENCLI_PACKAGE = tokencli.pkg + +tokencli-install: tokencli-build + mkdir -p $(TOKENCLI_PKGDIR)/bin/ + + $(call COPYTREE, tokencli/service, $(TOKENCLI_PKGDIR)/service) + + cp tokencli/src/tokencli $(TOKENCLI_PKGDIR)/bin/ + +tokencli-clean: + rm -rf $(TOKENCLI_PKGDIR) $(TOKENCLI_PACKAGE) + $(MAKE) -C tokencli/src clean + +tokencli-build: + $(MAKE) -C tokencli/src build + +PACKAGES += tokencli