Add more challenges! (only one left (and easter eggs))

Co-authored-by: Ezequiel Bellver <ebellver@itba.edu.ar>
Co-authored-by: Juan Barmasch <jbarmasch@itba.edu.ar>
This commit is contained in:
Santiago Lo Coco 2021-11-06 13:19:24 -03:00
parent 26b5fafa01
commit 4b4f743642
8 changed files with 228 additions and 32 deletions

4
.gitignore vendored
View File

@ -7,3 +7,7 @@
.inputrc .inputrc
.viminfo .viminfo
.vscode/ .vscode/
server
client
*.o
quine

View File

@ -1,23 +1,28 @@
CC = gcc CC = gcc
CCFLAGS = -Wall -std=c99 -pedantic -g CCFLAGS = -Wall -std=c99 -pedantic -g
CLIENT=client.o CLIENT=client
SERVER=server.o SERVER=server
ERROR=errors.o ERROR=errors.o
CHALLENGE=challenges.o CHALLENGE=challenges.o
TMP := $(shell mktemp)
all: $(ERROR) $(CHALLENGE) $(CLIENT) $(SERVER) 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 $(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 $(CC) $(CCFLAGS) client.c -o client errors.o
%.o: %.c %.o: %.c
$(CC) $(CCFLAGS) -I./include -c $< $(CC) $(CCFLAGS) -I./include -c $<
clean: clean:
rm -rf $(ERROR) $(CHALLENGE) $(CLIENT) $(SERVER) server client rm -rf $(ERROR) $(CHALLENGE) $(CLIENT) $(SERVER)
test: test:
pvs-studio-analyzer trace -- make pvs-studio-analyzer trace -- make

40
README.md Normal file
View File

@ -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 <a name="requisitos"></a>
...
## Compilación <a name="compilación"></a>
Para compilar todos los archivos se debe hacer:
```bash
make all
```
## Ejecución <a name="ejecución"></a>
Ahora, tendrá dos ejecutables: `client` y `server`.
## Testeos <a name="tests"></a>
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)

View File

@ -1,15 +1,116 @@
#include "include/challenges.h" #include "include/challenges.h"
char genChallenge(int fd, char * output, challenge_t challenge) { // Lo necesito para quine, dps podemos ver cómo hacerlo más lindo (de última se lo pasamos a todas las funciones de challenge)
printf("%s\n", challenge.message); 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; size_t linecap = 0;
readChars = read(fd, output, MAX_LEN - 1); ssize_t linelen;
if (readChars < 0)
printSystemError("Challenges: read()");
output[readChars] = '\0';
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()");
}
}
}
} }

View File

@ -1,6 +1,8 @@
#ifndef CHALLENGES_H #ifndef CHALLENGES_H
#define CHALLENGES_H #define CHALLENGES_H
#define _POSIX_C_SOURCE 200809L
#include <stdio.h> #include <stdio.h>
#include <unistd.h> #include <unistd.h>
#include <string.h> #include <string.h>
@ -13,8 +15,14 @@ typedef struct challenge_t {
char * message; char * message;
char * question; char * question;
char * flag; char * flag;
void (*function) (void);
} challenge_t; } 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 #endif

View File

@ -1,6 +1,8 @@
#ifndef SERVER_H #ifndef SERVER_H
#define SERVER_H #define SERVER_H
#define _POSIX_C_SOURCE 200809L
#include <stdio.h> #include <stdio.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <arpa/inet.h> #include <arpa/inet.h>
@ -15,9 +17,43 @@
#define PORT 8080 #define PORT 8080
#define ADDRESS "127.0.0.1" #define ADDRESS "127.0.0.1"
#define MAX_PEND_REQ 3 #define MAX_PEND_REQ 3
#define MAX_CHALLENGES 2 #define MAX_CHALLENGES 11
#define TIME_SLEEP 2 #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(); void startChallenge();
#endif #endif

1
quine.c Normal file
View File

@ -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); }

View File

@ -1,12 +1,5 @@
#include "include/server.h" #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 main(int argc, char *argv[]) {
int fd; int fd;
if ((fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) 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) if (listen(fd, MAX_PEND_REQ) < 0)
printSystemError("Server: listen()"); printSystemError("Server: listen()");
int addrlen = sizeof(address); int addrlen = sizeof(address), fdAux;
if ((clientFd = accept(fd, (struct sockaddr *) &address, (socklen_t *) &addrlen)) < 0) if ((fdAux = accept(fd, (struct sockaddr *) &address, (socklen_t *) &addrlen)) < 0)
printSystemError("Server: accept()"); printSystemError("Server: accept()");
startChallenge(); startChallenge(fdAux);
close(clientFd); close(fdAux);
close(fd); close(fd);
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
void startChallenge() { void startChallenge(int fd) {
FILE * stream;
if ((stream = fdopen(fd, "r")) == NULL)
printSystemError("Server: fdopen()");
int challengeCount = 0; 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]; challenge_t currentChallenge = challenges[challengeCount];
printf("\033[1;1H\033[2J"); // Limpiamos shell printf("\033[1;1H\033[2J"); // Limpiamos shell
if ((ansChallenge = genChallenge(clientFd, output, currentChallenge))) { if (genChallenge(stream, &output, currentChallenge)) {
challengeCount++; challengeCount++;
} }
else { else {
printf("Incorrecta\n"); printf("Respuesta incorrecta: %s\n", output);
sleep(TIME_SLEEP); sleep(TIME_SLEEP);
} }
} }
//fclose(stream);
free(output);
free(stream);
return; return;
} }