From 4b4f743642f4ff2e11e8e509b07e2ae7080731d5 Mon Sep 17 00:00:00 2001 From: Santiago Lo Coco Date: Sat, 6 Nov 2021 13:19:24 -0300 Subject: [PATCH] Add more challenges! (only one left (and easter eggs)) Co-authored-by: Ezequiel Bellver Co-authored-by: Juan Barmasch --- .gitignore | 4 ++ Makefile | 15 ++++-- README.md | 40 +++++++++++++++ challenges.c | 119 +++++++++++++++++++++++++++++++++++++++---- include/challenges.h | 10 +++- include/server.h | 38 +++++++++++++- quine.c | 1 + server.c | 33 ++++++------ 8 files changed, 228 insertions(+), 32 deletions(-) create mode 100644 README.md create mode 100644 quine.c diff --git a/.gitignore b/.gitignore index c4f2942..f9b9f32 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,7 @@ .inputrc .viminfo .vscode/ +server +client +*.o +quine diff --git a/Makefile b/Makefile index 28f057d..1dd4f95 100644 --- a/Makefile +++ b/Makefile @@ -1,23 +1,28 @@ CC = gcc CCFLAGS = -Wall -std=c99 -pedantic -g -CLIENT=client.o -SERVER=server.o +CLIENT=client +SERVER=server ERROR=errors.o CHALLENGE=challenges.o +TMP := $(shell mktemp) + all: $(ERROR) $(CHALLENGE) $(CLIENT) $(SERVER) -$(SERVER): +$(SERVER): server.c challenges.c errors.c include/errors.h include/challenges.h $(CC) $(CCFLAGS) server.c -o server challenges.o errors.o -$(CLIENT): + objcopy --add-section .RUN_ME="$(TMP)" --set-section-flags .mydata=noload,readonly server + rm "$(TMP)" + +$(CLIENT): client.c errors.c include/errors.h $(CC) $(CCFLAGS) client.c -o client errors.o %.o: %.c $(CC) $(CCFLAGS) -I./include -c $< clean: - rm -rf $(ERROR) $(CHALLENGE) $(CLIENT) $(SERVER) server client + rm -rf $(ERROR) $(CHALLENGE) $(CLIENT) $(SERVER) test: pvs-studio-analyzer trace -- make diff --git a/README.md b/README.md new file mode 100644 index 0000000..f047aad --- /dev/null +++ b/README.md @@ -0,0 +1,40 @@ +# BSSolver + +BCSSocket (Bottler Client-Server Socket) es un sistema que... + +## Table de contenidos +* [Requisitos](#requisitos) +* [Compilación](#compilación) +* [Ejecución](#ejecución) +* [Testeos](#tests) + +## Requisitos + +... + +## Compilación + +Para compilar todos los archivos se debe hacer: + +```bash +make all +``` + +## Ejecución + +Ahora, tendrá dos ejecutables: `client` y `server`. + +## Testeos + +En orden de realizar un análisis estático del sistema usted debe tener instalado [cppcheck](http://cppcheck.net/) y [pvs-studio](https://pvs-studio.com/). Luego, puede correrlos con: + +```bash +make test +``` + +Por último, si quiere hacer un análisis dinámico (usando [valgrind](https://valgrind.org/)) debe... + +# Autores +- Barmasch, Juan Martín (61033) +- Bellver, Ezequiel (61268) +- Lo Coco, Santiago (61301) \ No newline at end of file diff --git a/challenges.c b/challenges.c index af8a814..fb88ea5 100644 --- a/challenges.c +++ b/challenges.c @@ -1,15 +1,116 @@ #include "include/challenges.h" -char genChallenge(int fd, char * output, challenge_t challenge) { - printf("%s\n", challenge.message); +// Lo necesito para quine, dps podemos ver cómo hacerlo más lindo (de última se lo pasamos a todas las funciones de challenge) +FILE * streamGen; + +char genChallenge(FILE * stream, char ** output, challenge_t challenge) { + streamGen = stream; + + printf("------------- DESAFIO -------------\n"); + printf("%s\n\n", challenge.message); + + if (challenge.function != NULL) + challenge.function(); + + printf("\n----- PREGUNTA PARA INVESTIGAR -----\n"); + printf("%s\n\n", challenge.question); - int readChars; - readChars = read(fd, output, MAX_LEN - 1); - if (readChars < 0) - printSystemError("Challenges: read()"); - output[readChars] = '\0'; + size_t linecap = 0; + ssize_t linelen; - printf("%s\n", challenge.question); + if ((linelen = getline(output, &linecap, stream)) < 0) + printSystemError("Challenges: getline()"); - return strcmp(output, challenge.flag); + return !strcmp(*output, challenge.flag); +} + +void writeChallenge() { + if (write(0xd, "................................La respuesta es fk3wfLCm3QvS\n", 62) < 0) + perror("write"); +} + +void filterChallenge() { + char * ans = "La respuesta es K5n2UFfpFMUN\n"; + int i = 0; + while (ans[i] != '\0') { + // ver cómo haciamos en pi con numeros random. quiiero que me de entre 1 y 2 (stdout o stderr) + int fdRandom = ((double) rand() / (RAND_MAX)) + 1; + if (fdRandom == STDOUT_FILENO) { + if (write(STDOUT_FILENO, ans + i++, 1) < 0) + printSystemError("Challenges: write()"); + } + else { + // tmb generar string random para imprimir por stderr. por ahora hardcodeo a una letra + if (write(STDERR_FILENO, "=", 1) < 0) + printSystemError("Challenges: write()"); + } + } +} + +void questionChallenge() { + // idema a printf... + if (write(STDOUT_FILENO, "La respuesta es BUmyYq5XxXGt", 28) < 0) + printSystemError("Challenges: write()"); + + if (write(STDOUT_FILENO, "\033[1;1H\033[2J", 11) < 0) + printSystemError("Challenges: write()"); +} + +void quineChallenge() { + while(1) { + char outputGCC = system("gcc quine.c -o quine"); + if (!outputGCC) { + while (1) { + printf("¡Genial!, ya lograron meter un programa en quine.c, veamos si hace lo que corresponde.\n"); + char outputDIFF = system("./quine | diff quine.c -"); + if (!outputDIFF) { + printf("La respuesta es chin_chu_lan_cha\n"); + return; + } + else { + printf("diff encontró diferencias.\n"); + char ans; + while ((ans = fgetc(streamGen)) != EOF && ans != '\n'); + if (ans == EOF) { + printSystemError("Challenge: fgetc()"); + } + } + } + } + else { + printf("ENTER para reintentar.\n"); + char ans; + while ((ans = fgetc(streamGen)) != EOF && ans != '\n'); + if (ans == EOF) { + printSystemError("Challenge: fgetc()"); + } + } + } +} + +void gdbme(char * output) { + if (getpid() == 0x12345678) { + *output = 1; + return; + } + else *output = 0; +} + +void gdbChallenge() { + while(1) { + char gdbOutput; + gdbme(&gdbOutput); + if (gdbOutput) { + printf("La respuesta es gdb_rules\n"); + return; + } + else { + printf("ENTER para reintentar.\n"); + char ans; + while ((ans = fgetc(streamGen)) != EOF && ans != '\n'); + if (ans == EOF) { + printSystemError("Challenge: fgetc()"); + } + } + } } \ No newline at end of file diff --git a/include/challenges.h b/include/challenges.h index 515acf8..4df9a84 100644 --- a/include/challenges.h +++ b/include/challenges.h @@ -1,6 +1,8 @@ #ifndef CHALLENGES_H #define CHALLENGES_H +#define _POSIX_C_SOURCE 200809L + #include #include #include @@ -13,8 +15,14 @@ typedef struct challenge_t { char * message; char * question; char * flag; + void (*function) (void); } challenge_t; -char genChallenge(int fd, char * output, challenge_t challenge); +char genChallenge(FILE * stream, char ** output, challenge_t challenge); +void writeChallenge(); +void filterChallenge(); +void questionChallenge(); +void quineChallenge(); +void gdbChallenge(); #endif \ No newline at end of file diff --git a/include/server.h b/include/server.h index 000c3e6..8a67b31 100644 --- a/include/server.h +++ b/include/server.h @@ -1,6 +1,8 @@ #ifndef SERVER_H #define SERVER_H +#define _POSIX_C_SOURCE 200809L + #include #include #include @@ -15,9 +17,43 @@ #define PORT 8080 #define ADDRESS "127.0.0.1" #define MAX_PEND_REQ 3 -#define MAX_CHALLENGES 2 +#define MAX_CHALLENGES 11 #define TIME_SLEEP 2 +challenge_t challenges[] = { + {"Bienvenidos al TP3 y felicitaciones, ya resolvieron el primer acertijo.\n\n\ +En este TP deberán finalizar el juego que ya comenzaron resolviendo los desafíos \ +de cada nivel.\n\nAdemás tendrán que investigar otras preguntas para responder \ +durante la defensa.\n\nEl desafío final consiste en crear un programa que se \ +comporte igual que yo, es decir, que provea los mismos desafíos y que sea necesario \ +hacer lo mismo para resolverlos. No basta con esperar la respuesta.\n\nAdemás, \ +deberán implementar otro programa para comunicarse conmigo.\n\nDeberán estar atentos \ +a los easter eggs.\n\nPara verificar que sus respuestas tienen el formato correcto \ +respondan a este desafío con la palabra 'entendido\\n'", "¿Cómo descubrieron el protocolo, \ +la dirección y el puerto para conectarse?", "entendido\n", NULL}, + {"The Wire S1E5\n\n5295 888 6288", "¿Qué diferencias hay entre TCP y UDP y en qué casos \ +conviene usar cada uno?", "itba\n", NULL}, + {"https://ibb.co/tc0Hb6w", "¿El puerto que usaron para conectarse al server es el mismo \ +que usan para mandar las respuestas? ¿Por qué?", "M4GFKZ289aku\n", NULL}, + {"EBADF...", "¿Qué útil abstracción es utilizada para comunicarse con sockets? ¿se puede \ +utilizar read(2) y write(2) para operar?", "fk3wfLCm3QvS\n", writeChallenge}, + {"respuesta = strings:269", "¿Cómo garantiza TCP que los paquetes llegan en orden y no se \ +pierden?", "too_easy\n", NULL}, + {".data .bss .comment ? .shstrtab .symtab .strtab", "Un servidor suele crear un nuevo proceso \ +o thread para atender las conexiones entrantes. ¿Qué conviene más?", ".RUN_ME\n", NULL}, + {"Filter: ", "¿Cómo se puede implementar un servidor que atienda muchas conexiones sin usar \ +procesos ni threads?", "K5n2UFfpFMUN\n", filterChallenge}, + {"¿?", "¿Qué aplicaciones se pueden utilizar para ver el tráfico por la red?", + "BUmyYq5XxXGt\n", questionChallenge}, + {"Latexme\n\nSi\n \\mathrm{d}y = u^v{\\cdot}(v'{\\cdot}\\ln{(u)}+v{\\cdot}\\frac{u'}{u})\n \ +entonces y =", "sockets es un mecanismo de IPC. ¿Qué es más eficiente entre sockets y pipes?", + "u^v\n", NULL}, + {"quine\n\n", "¿Cuáles son las características del protocolo SCTP?", "chin_chu_lan_cha\n", quineChallenge}, + {"b gdbme y encontrá el valor mágico", "", "gdb_rules\n", gdbChallenge}, +}; + +char too_easy = 'a'; + void startChallenge(); #endif \ No newline at end of file diff --git a/quine.c b/quine.c new file mode 100644 index 0000000..c86c7ce --- /dev/null +++ b/quine.c @@ -0,0 +1 @@ +main() { char *s="main() { char *s=%c%s%c; printf(s,34,s,34,10); }%c"; printf(s,34,s,34,10); } diff --git a/server.c b/server.c index 656f632..5437b87 100644 --- a/server.c +++ b/server.c @@ -1,12 +1,5 @@ #include "include/server.h" -int clientFd; - -challenge_t challenges[] = { - {"A volar bobby", "Cómo es que matan?", "IZPUAN"}, - {"A cagar bobby", "A una niña", "PUANIZ"} -}; - int main(int argc, char *argv[]) { int fd; if ((fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) @@ -28,33 +21,41 @@ int main(int argc, char *argv[]) { if (listen(fd, MAX_PEND_REQ) < 0) printSystemError("Server: listen()"); - int addrlen = sizeof(address); - if ((clientFd = accept(fd, (struct sockaddr *) &address, (socklen_t *) &addrlen)) < 0) + int addrlen = sizeof(address), fdAux; + if ((fdAux = accept(fd, (struct sockaddr *) &address, (socklen_t *) &addrlen)) < 0) printSystemError("Server: accept()"); - startChallenge(); + startChallenge(fdAux); - close(clientFd); + close(fdAux); close(fd); return EXIT_SUCCESS; } -void startChallenge() { +void startChallenge(int fd) { + FILE * stream; + if ((stream = fdopen(fd, "r")) == NULL) + printSystemError("Server: fdopen()"); + int challengeCount = 0; - char ansChallenge = 1, output[MAX_LEN] = {0}; + char * output = NULL; - while (challengeCount < MAX_CHALLENGES && ansChallenge) { + while (challengeCount < MAX_CHALLENGES) { challenge_t currentChallenge = challenges[challengeCount]; printf("\033[1;1H\033[2J"); // Limpiamos shell - if ((ansChallenge = genChallenge(clientFd, output, currentChallenge))) { + if (genChallenge(stream, &output, currentChallenge)) { challengeCount++; } else { - printf("Incorrecta\n"); + printf("Respuesta incorrecta: %s\n", output); sleep(TIME_SLEEP); } } + //fclose(stream); + free(output); + free(stream); + return; } \ No newline at end of file