enowars5-service-stldoctor

STL-Analyzing A/D Service for ENOWARS5 in 2021
git clone https://git.sinitax.com/sinitax/enowars5-service-stldoctor
Log | Files | Refs | README | LICENSE | sfeed.txt

commit 1490268ea6ae75e5e9b78861c56dc9b04db903f3
parent 2a8416eaa85af6348fe34859859a7fb39db2003d
Author: Louis Burda <quent.burda@gmail.com>
Date:   Mon, 10 May 2021 17:18:28 +0200

extended query function to load file info, added poc test

Diffstat:
Mservice/src/printdoc.c | 211+++++++++++++++++++++++++++++++++++++++++++++++--------------------------------
Mservice/src/stlfile.c | 24++++++++++++++++--------
Mservice/src/stlfile.h | 1+
Mservice/src/test.sh | 72++++++++++++++++++++++++++++++++++++++++++++++++++----------------------
Mservice/src/tests/evil1.stl | 5++---
Mservice/src/util.c | 5+++--
6 files changed, 197 insertions(+), 121 deletions(-)

diff --git a/service/src/printdoc.c b/service/src/printdoc.c @@ -10,99 +10,51 @@ #include "stlfile.h" #include "util.h" +#define MAXFILESIZE 7000 + struct command { const char *name; void (*func)(char *); }; -void search_cmd(char *arg); -void submit_cmd(char *arg); -void list_cmd(char *arg); +int save_submission(struct parseinfo *info, char *data, int len); + void cat_cmd(char *arg); +void list_cmd(char *arg); +void submit_cmd(char *arg); +void query_cmd(char *arg); struct command commands[] = { - { "submit", submit_cmd }, { "cat", cat_cmd }, { "help", list_cmd }, - { "search", search_cmd } + { "submit", submit_cmd }, + { "query", query_cmd }, }; -struct parseinfo lastrun; +struct parseinfo cached; const char *resultdir; -void -search_cmd(char *arg) -{ - char *end, *resultfile = NULL; - const char *hash; - struct dirent *de; - int i, which; - DIR *d = NULL; - - if (lastrun.valid) - hash = lastrun.hash; - else - hash = mhash(ask("What is the model name?\n"), -1); - - d = opendir("scans"); - if (!d) return; - - i = 0; - while ((de = readdir(d))) { - if (de->d_type != DT_DIR && !strpfcmp(hash, de->d_name)) { - printf("%i : %s\n", i, de->d_name); - i++; - } - } - - if (i == 0) { - fprintf(stderr, "Sorry, couldnt find a matching scan result!\n"); - goto cleanup; - } else { - which = strtoul(ask("Which of these results?\n"), &end, 10); - if (which >= i || which < 0 || *end) { - fprintf(stderr, "Invalid index!\n"); - goto cleanup; - } - } - - while ((de = readdir(d))) { - if (de->d_type != DT_DIR && !strpfcmp(hash, de->d_name)) { - if (i == which) { - resultfile = aprintf("scans/%s/info", strdup(de->d_name)); - break; - } - i++; - } - } - - if (resultfile) - dump(resultfile); - -cleanup: - free(resultfile); - closedir(d); -} - int -save_submission(char *stldata, int stlsize) +save_submission(struct parseinfo *info, char *stldata, int stlsize) { DIR *d; FILE *f; char *dirpath = NULL, *infopath = NULL, *modelpath = NULL; - dirpath = aprintf("%s/%s-%i", resultdir, lastrun.hash, time(NULL)); + dirpath = aprintf("%s/%s-%i", resultdir, info->hash, time(NULL)); if (mkdir(dirpath, S_IRWXU | S_IRWXG | S_IRWXO)) goto fail; modelpath = aprintf("%s/%s", dirpath, "model"); if (!(f = fopen(modelpath, "w+"))) goto fail; if (fwrite(stldata, 1, stlsize, f) != stlsize) goto fail; fclose(f); + f = NULL; infopath = aprintf("%s/%s", dirpath, "info"); if (!(f = fopen(infopath, "w+"))) goto fail; - if (save_info(&lastrun, f) != OK) goto fail; + if (save_info(info, f) != OK) goto fail; fclose(f); + f = NULL; free(dirpath); free(modelpath); @@ -111,6 +63,8 @@ save_submission(char *stldata, int stlsize) return OK; fail: + if (f) fclose(f); + remove(infopath); remove(modelpath); remove(dirpath); @@ -123,54 +77,135 @@ fail: } void +cat_cmd(char *arg) +{ + if (arg && !strncmp(arg, "flag", 4)) + dump("msgs/cat_flag"); + else + printf("meow\n"); +} + +void +list_cmd(char *arg) +{ + int i; + + printf("Available commands:\n"); + for (i = 0; i < ARRSIZE(commands); i++) + printf("%s%s", i ? " " : "", commands[i].name); + printf("\n"); +} + +void submit_cmd(char *arg) { const char *bufp; char *end, *contents; size_t len; - bufp = ask("How large is your file?\n"); + bufp = ask("> How large is your file? "); len = strtoul(bufp, &end, 10); - if (len <= 0 || len >= 10000 || *end) { + if (len <= 0 || len >= MAXFILESIZE || *end) { fprintf(stderr, "Invalid file length!\n"); return; } - printf("Ok! Im listening..\n"); + printf("> Ok! Im listening..\n"); contents = checkp(malloc(len + 1)); fread(contents, 1, len, stdin); contents[len] = '\0'; - lastrun.valid = parse_file(&lastrun, contents, len); - - if (lastrun.valid) { - if (save_submission(contents, len) != OK) + if ((cached.valid = parse_file(&cached, contents, len))) { + if (save_submission(&cached, contents, len) != OK) fprintf(stderr, "Failed to save your submission!\n"); else - printf(">> Your file was saved with ID %s!\n", lastrun.hash); + printf("> Your file was saved with ID %s!\n", cached.hash); } free(contents); } void -cat_cmd(char *arg) +query_cmd(char *arg) { - if (arg && !strncmp(arg, "flag", 4)) - dump("msgs/cat_flag"); + char *end, *scandir = NULL, *infopath = NULL, *modelpath = NULL; + const char *hash; + struct dirent *de; + int i, which, dirstart; + DIR *d = NULL; + FILE *f = NULL; + size_t size; + + if (cached.valid) + hash = cached.hash; else - printf("meow\n"); -} + hash = mhash(ask("> What is the model name? "), -1); -void -list_cmd(char *arg) -{ - int i; + if (!(d = opendir(resultdir))) return; - printf("Available commands:\n"); - for (i = 0; i < ARRSIZE(commands); i++) - printf("%s%s", i ? " " : "", commands[i].name); - printf("\n"); + dirstart = telldir(d); + for (i = 0; (de = readdir(d));) { + if (de->d_type == DT_DIR && !strpfcmp(hash, de->d_name)) { + printf("%i : %s\n", i, de->d_name); + i++; + } + } + + if (i == 0) { + fprintf(stderr, "Sorry, couldnt find a matching scan result!\n"); + goto cleanup; + } else { + which = strtoul(ask("> Which of these results? "), &end, 10); + if (which >= i || which < 0 || *end) { + fprintf(stderr, "Invalid index!\n"); + goto cleanup; + } + } + + seekdir(d, dirstart); + for (i = 0; (de = readdir(d));) { + if (de->d_type == DT_DIR && !strpfcmp(hash, de->d_name)) { + if (i == which) { + scandir = aprintf("%s/%s", resultdir, de->d_name); + break; + } + i++; + } + } + + if (!scandir) { + fprintf(stderr, "Unexpected error!\n"); + goto cleanup; + } + + infopath = aprintf("%s/%s", scandir, "info"); + if (!(f = fopen(infopath, "r"))) goto cleanup; + if (load_info(&cached, f) != OK) goto cleanup; + fclose(f); + f = NULL; + + print_info(&cached); + + if (strchr(ask("> Download the model? "), 'y')) { + modelpath = aprintf("%s/%s", scandir, "model"); + if (!(f = fopen(modelpath, "r"))) goto cleanup; + fseek(f, 0, SEEK_END); + size = ftell(f); + fseek(f, 0, SEEK_SET); + if (size > MAXFILESIZE) goto cleanup; + printf("> Here you go.. (%liB)\n", size); + while ((i = getc(f)) != EOF) + putc(i, stdout); + fclose(f); + f = NULL; + } + +cleanup: + if (f) fclose(f); + closedir(d); + free(scandir); + free(infopath); + free(modelpath); } int @@ -180,7 +215,11 @@ main() int exit, i; if (!(resultdir = getenv("RESULTDIR"))) - resultdir = "/data"; + resultdir = "scans"; + + setvbuf(stdin, NULL, _IONBF, 0); + setvbuf(stdout, NULL, _IONBF, 0); + setvbuf(stderr, NULL, _IONBF, 0); dump("msgs/welcome"); @@ -211,5 +250,5 @@ main() } printf("see you later!\n"); - free_info(&lastrun); + free_info(&cached); } diff --git a/service/src/stlfile.c b/service/src/stlfile.c @@ -254,12 +254,14 @@ parse_file(struct parseinfo *info, char *buf, size_t len) const char *tmp; char *bp; + if (len < 7) return FAIL; + if (info->valid) free_info(info); for (bp = buf; strchr(wsset, *bp); bp++); /* check bin vs ascii with first keyword */ - status = !strncmp("solid ", bp, 6) + status = !strncmp("solid", bp, 5) && strchr(wsset, bp[5]) ? parse_file_ascii(info, buf, len) : parse_file_bin(info, buf, len); if (status == FAIL) return FAIL; @@ -312,8 +314,8 @@ load_info(struct parseinfo *info, FILE *f) nread += fread(&info->loopcount, sizeof(int), 1, f); for (i = 0; i < 3; i++) { - nread += fwrite(&info->bbmin[i], sizeof(float), 1, f); - nread += fwrite(&info->bbmax[i], sizeof(float), 1, f); + nread += fread(&info->bbmin[i], sizeof(float), 1, f); + nread += fread(&info->bbmax[i], sizeof(float), 1, f); } nread += fread(info->header, 80, 1, f); @@ -323,6 +325,8 @@ load_info(struct parseinfo *info, FILE *f) freadstr(f, &info->modelname); freadstr(f, &info->hash); + info->valid = 1; + return OK; } @@ -333,10 +337,12 @@ print_info(struct parseinfo *info) #define FILTERCHAR(c) ((c) >= 32 ? (c) : ' ') - printf("Name: %s\n", info->modelname); + printf(" === Model info === \n"); + + printf(" Name: %s\n", info->modelname); if (info->type == TYPE_BIN) { - printf("Header:\n"); + printf(" Header:\n "); for (i = 0; i < 80; i += k) { for (k = 0; k < MIN(80 - i, 20); k++) printf(" %02x", (uint8_t) info->header[i+k]); @@ -347,12 +353,14 @@ print_info(struct parseinfo *info) } } - printf("Hash: %s\n", info->hash); - printf("Triangles: %i\n", info->loopcount); - printf("Bounding Box: %.2f x %.2f x %.2f\n", + printf(" Hash: %s\n", info->hash); + printf(" Triangles: %i\n", info->loopcount); + printf(" Bounding Box: %.2f x %.2f x %.2f\n", info->bbmax[0] - info->bbmin[0], info->bbmax[1] - info->bbmin[1], info->bbmax[2] - info->bbmin[2]); + + printf(" ================== \n"); } void diff --git a/service/src/stlfile.h b/service/src/stlfile.h @@ -46,6 +46,7 @@ struct parseinfo { int parse_file(struct parseinfo *info, char *buf, size_t len); int save_info(struct parseinfo *info, FILE *f); +int load_info(struct parseinfo *info, FILE *f); void print_info(struct parseinfo *info); void free_info(struct parseinfo *info); diff --git a/service/src/test.sh b/service/src/test.sh @@ -26,26 +26,54 @@ checkleaks() { export RESULTDIR="scans" -announce "Trying ASCII STL" -( - echo "submit" - cat tests/sample-ascii.stl | wc -c - cat tests/sample-ascii.stl -) | checkleaks - -announce "Trying BIN STL" -( - echo "submit" - cat tests/sample-binary.stl | wc -c - cat tests/sample-binary.stl - echo "testname" -) | checkleaks - - -announce "Testing Proof-Of-Concept" -( - echo "submit" - cat tests/evil1.stl | wc -c - cat tests/evil1.stl -) | checkleaks +if [ "$1" == "stl" ]; then + announce "Testing ASCII STL Parsing" + ( + echo "submit" + cat tests/sample-ascii.stl | wc -c + cat tests/sample-ascii.stl + ) | checkleaks + + announce "Testing BIN STL Parsing" + ( + echo "submit" + cat tests/sample-binary.stl | wc -c + cat tests/sample-binary.stl + echo "testname" + ) | checkleaks + +elif [ "$1" == "poc" ]; then + + announce "Testing Proof-Of-Concept" + + rm -rf scans/* + + echo -e "\n--- Uploading evil STL ---\n" 1>&2 + ( + echo "submit" + cat tests/evil1.stl | wc -c + cat tests/evil1.stl + echo "AAAA" + ) | ./printdoc + + echo -e "\n--- Testing Exploit ---\n" 1>&2 + + ( + echo "query" + echo "AAAA" + echo "0" + echo "n" + + echo "query" + ) | ./printdoc + +else + ( + echo "submit" + echo "2" + echo "AA" + echo "AAAA" + ) | ./printdoc + +fi diff --git a/service/src/tests/evil1.stl b/service/src/tests/evil1.stl @@ -1,4 +1,4 @@ -solid test˙ +solid facet normal 0 0 1.0 outer loop vertex 1 0 0 @@ -6,4 +6,4 @@ solid test vertex 0 1 0 endloop endfacet -endsolid -\ No newline at end of file +endsolid diff --git a/service/src/util.c b/service/src/util.c @@ -55,8 +55,8 @@ mhash(const char *filename, int len) unsigned char v = 0; for (k = i; k < len; k += MHASHLEN) v ^= filename[k]; - buf[i*2+0] = hexalph[(v >> 0) & 0x0f]; buf[i*2+1] = hexalph[(v >> 4) & 0x0f]; + buf[i*2+0] = hexalph[(v >> 0) & 0x0f]; } if (i == 0) { @@ -78,7 +78,8 @@ freadstr(FILE *f, char **dst) char c; start = ftell(f); - while ((c = fgetc(f)) != EOF && c) len++; + for (len = 0; (c = fgetc(f)) != EOF && c; len++); + fseek(f, start, SEEK_SET); *dst = calloc(len + 1, 1); fread(*dst, len, 1, f);